quala 0.0.1a0
Quasi-Newton and other accelerators
quala.cpp
Go to the documentation of this file.
1/**
2 * @file
3 * This file defines all Python bindings.
4 */
5
6#include <pybind11/attr.h>
7#include <pybind11/cast.h>
8#include <pybind11/chrono.h>
9#include <pybind11/detail/common.h>
10#include <pybind11/eigen.h>
11#include <pybind11/functional.h>
12#include <pybind11/iostream.h>
13#include <pybind11/pybind11.h>
14#include <pybind11/pytypes.h>
15#include <pybind11/stl.h>
16
17#include <memory>
18#include <optional>
19#include <sstream>
20#include <stdexcept>
21#include <string>
22#include <tuple>
23#include <type_traits>
24#include <utility>
25
26#include "kwargs-to-struct.hpp"
27
28namespace py = pybind11;
29
30#define STRINGIFY(x) #x
31#define MACRO_STRINGIFY(x) STRINGIFY(x)
32
33PYBIND11_MODULE(QUALA_MODULE_NAME, m) {
34 using py::operator""_a;
35
36 py::options options;
37 options.enable_function_signatures();
38 options.enable_user_defined_docstrings();
39
40 m.doc() = "Quala Quasi-Newton algorithms";
41
42#ifdef VERSION_INFO
43 m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO);
44#else
45 m.attr("__version__") = "dev";
46#endif
47
48 py::class_<quala::LBFGSParams::CBFGSParams>(
49 m, "LBFGSParamsCBFGS",
50 "C++ documentation: :cpp:member:`quala::LBFGSParams::CBFGSParams `")
51 .def(py::init())
52 .def(py::init(&kwargs_to_struct<quala::LBFGSParams::CBFGSParams>))
53 .def("to_dict", &struct_to_dict<quala::LBFGSParams::CBFGSParams>)
54 .def_readwrite("α", &quala::LBFGSParams::CBFGSParams::α)
55 .def_readwrite("ϵ", &quala::LBFGSParams::CBFGSParams::ϵ)
56 .def("__bool__", &quala::LBFGSParams::CBFGSParams::operator bool);
57
58 py::class_<quala::LBFGSParams>(
59 m, "LBFGSParams", "C++ documentation: :cpp:class:`quala::LBFGSParams`")
60 .def(py::init())
61 .def(py::init(&kwargs_to_struct<quala::LBFGSParams>))
62 .def("to_dict", &struct_to_dict<quala::LBFGSParams>)
63 .def_readwrite("memory", &quala::LBFGSParams::memory)
64 .def_readwrite("min_div_fac", &quala::LBFGSParams::min_div_fac)
65 .def_readwrite("min_abs_s", &quala::LBFGSParams::min_abs_s)
66 .def_readwrite("force_pos_def", &quala::LBFGSParams::force_pos_def)
67 .def_readwrite("cbfgs", &quala::LBFGSParams::cbfgs);
68
69 auto lbfgs = py::class_<quala::LBFGS>(
70 m, "LBFGS", "C++ documentation: :cpp:class:`quala::LBFGS`");
71 auto lbfgssign = py::enum_<quala::LBFGS::Sign>(
72 lbfgs, "Sign", "C++ documentation :cpp:enum:`quala::LBFGS::Sign`");
73 lbfgssign //
74 .value("Positive", quala::LBFGS::Sign::Positive)
75 .value("Negative", quala::LBFGS::Sign::Negative)
76 .export_values();
77 lbfgs //
78 .def(py::init<quala::LBFGS::Params>(), "params"_a)
79 .def(py::init([](py::dict params) -> quala::LBFGS {
80 return {kwargs_to_struct<quala::LBFGS::Params>(params)};
81 }),
82 "params"_a)
83 .def(py::init<quala::LBFGS::Params, quala::length_t>(), "params"_a,
84 "n"_a)
85 .def(py::init([](py::dict params, quala::length_t n) -> quala::LBFGS {
86 return {kwargs_to_struct<quala::LBFGS::Params>(params), n};
87 }),
88 "params"_a, "n"_a)
89 .def_static("update_valid", quala::LBFGS::update_valid, "params"_a,
90 "yᵀs"_a, "sᵀs"_a, "pᵀp"_a)
91 .def(
92 "update",
93 [](quala::LBFGS &self, quala::crvec xk, quala::crvec xkp1,
95 bool forced) {
96 if (xk.size() != self.n())
97 throw std::invalid_argument("xk dimension mismatch");
98 if (xkp1.size() != self.n())
99 throw std::invalid_argument("xkp1 dimension mismatch");
100 if (pk.size() != self.n())
101 throw std::invalid_argument("pk dimension mismatch");
102 if (pkp1.size() != self.n())
103 throw std::invalid_argument("pkp1 dimension mismatch");
104 return self.update(xk, xkp1, pk, pkp1, sign, forced);
105 },
106 "xk"_a, "xkp1"_a, "pk"_a, "pkp1"_a,
107 "sign"_a = quala::LBFGS::Sign::Positive, "forced"_a = false)
108 .def(
109 "update_sy",
110 [](quala::LBFGS &self, quala::crvec sk, quala::crvec yk,
111 quala::real_t pkp1Tpkp1, bool forced) {
112 if (sk.size() != self.n())
113 throw std::invalid_argument("sk dimension mismatch");
114 if (yk.size() != self.n())
115 throw std::invalid_argument("yk dimension mismatch");
116 return self.update_sy(sk, yk, pkp1Tpkp1, forced);
117 },
118 "sk"_a, "yk"_a, "pkp1Tpkp1"_a, "forced"_a = false)
119 .def(
120 "apply",
121 [](quala::LBFGS &self, quala::rvec q, quala::real_t γ) {
122 if (q.size() != self.n())
123 throw std::invalid_argument("q dimension mismatch");
124 return self.apply(q, γ);
125 },
126 "q"_a, "γ"_a)
127 .def(
128 "apply",
129 [](quala::LBFGS &self, quala::rvec q, quala::real_t γ,
130 const std::vector<quala::vec::Index> &J) {
131 return self.apply(q, γ, J);
132 },
133 "q"_a, "γ"_a, "J"_a)
134 .def("reset", &quala::LBFGS::reset)
135 .def("current_history", &quala::LBFGS::current_history)
136 .def("resize", &quala::LBFGS::resize, "n"_a)
137 .def("scale_y", &quala::LBFGS::scale_y, "factor"_a)
138 .def_property_readonly("n", &quala::LBFGS::n)
139 .def("s",
140 [](quala::LBFGS &self, quala::index_t i) -> quala::rvec {
141 return self.s(i);
142 })
143 .def("y",
144 [](quala::LBFGS &self, quala::index_t i) -> quala::rvec {
145 return self.y(i);
146 })
147 .def("ρ",
148 [](quala::LBFGS &self, quala::index_t i) -> quala::real_t & {
149 return self.ρ(i);
150 })
151 .def("α",
152 [](quala::LBFGS &self, quala::index_t i) -> quala::real_t & {
153 return self.α(i);
154 })
155 .def_property_readonly("params", &quala::LBFGS::get_params);
156
157 py::class_<quala::AndersonAccelParams>(
158 m, "AndersonAccelParams",
159 "C++ documentation: :cpp:class:`quala::AndersonAccelParams`")
160 .def(py::init())
161 .def(py::init(&kwargs_to_struct<quala::AndersonAccelParams>))
162 .def("to_dict", &struct_to_dict<quala::AndersonAccelParams>)
163 .def_readwrite("memory", &quala::AndersonAccelParams::memory);
164
165 py::class_<quala::AndersonAccel>(
166 m, "AndersonAccel",
167 "C++ documentation: :cpp:class:`quala::AndersonAccel`")
168 .def(py::init<quala::AndersonAccel::Params>(), "params"_a)
169 .def(py::init([](py::dict params) -> quala::AndersonAccel {
170 return {
171 kwargs_to_struct<quala::AndersonAccel::Params>(params)};
172 }),
173 "params"_a)
174 .def(py::init<quala::AndersonAccel::Params, quala::length_t>(),
175 "params"_a, "n"_a)
176 .def(py::init([](py::dict params,
178 return {kwargs_to_struct<quala::AndersonAccel::Params>(params),
179 n};
180 }),
181 "params"_a, "n"_a)
182 .def("resize", &quala::AndersonAccel::resize, "n"_a)
183 .def(
184 "initialize",
185 [](quala::AndersonAccel &self, quala::crvec g_0, quala::vec r_0) {
186 if (g_0.size() != self.n())
187 throw std::invalid_argument("g_0 dimension mismatch");
188 if (r_0.size() != self.n())
189 throw std::invalid_argument("r_0 dimension mismatch");
190 self.initialize(g_0, std::move(r_0));
191 },
192 "g_0"_a, "r_0"_a)
193 .def(
194 "compute",
196 quala::rvec x_k_aa) {
197 if (g_k.size() != self.n())
198 throw std::invalid_argument("g_k dimension mismatch");
199 if (r_k.size() != self.n())
200 throw std::invalid_argument("r_k dimension mismatch");
201 if (x_k_aa.size() != self.n())
202 throw std::invalid_argument("x_k_aa dimension mismatch");
203 self.compute(g_k, std::move(r_k), x_k_aa);
204 },
205 "g_k"_a, "r_k"_a, "x_k_aa"_a)
206 .def(
207 "compute",
208 [](quala::AndersonAccel &self, quala::crvec g_k, quala::vec r_k) {
209 if (g_k.size() != self.n())
210 throw std::invalid_argument("g_k dimension mismatch");
211 if (r_k.size() != self.n())
212 throw std::invalid_argument("r_k dimension mismatch");
213 quala::vec x_k_aa(self.n());
214 self.compute(g_k, std::move(r_k), x_k_aa);
215 return x_k_aa;
216 },
217 "g_k"_a, "r_k"_a)
218 .def("reset", &quala::AndersonAccel::reset)
219 .def("current_history", &quala::AndersonAccel::current_history)
220 .def_property_readonly("params", &quala::AndersonAccel::get_params);
221
222 py::class_<quala::BroydenGoodParams>(
223 m, "BroydenGoodParams",
224 "C++ documentation: :cpp:class:`quala::BroydenGoodParams`")
225 .def(py::init())
226 .def(py::init(&kwargs_to_struct<quala::BroydenGoodParams>))
227 .def("to_dict", &struct_to_dict<quala::BroydenGoodParams>)
228 .def_readwrite("memory", &quala::BroydenGoodParams::memory)
229 .def_readwrite("min_div_abs", &quala::BroydenGoodParams::min_div_abs)
230 .def_readwrite("force_pos_def",
232 .def_readwrite("restarted", &quala::BroydenGoodParams::restarted);
233
234 py::class_<quala::BroydenGood>(
235 m, "BroydenGood", "C++ documentation: :cpp:class:`quala::BroydenGood`")
236 .def(py::init<quala::BroydenGood::Params>(), "params"_a)
237 .def(py::init([](py::dict params) -> quala::BroydenGood {
238 return {kwargs_to_struct<quala::BroydenGood::Params>(params)};
239 }),
240 "params"_a)
241 .def(py::init<quala::BroydenGood::Params, quala::length_t>(),
242 "params"_a, "n"_a)
243 .def(py::init([](py::dict params,
245 return {kwargs_to_struct<quala::BroydenGood::Params>(params),
246 n};
247 }),
248 "params"_a, "n"_a)
249 .def("resize", &quala::BroydenGood::resize, "n"_a)
250 .def(
251 "update",
253 quala::crvec pk, quala::crvec pkp1, bool forced) {
254 if (xk.size() != self.n())
255 throw std::invalid_argument("xk dimension mismatch");
256 if (xkp1.size() != self.n())
257 throw std::invalid_argument("xkp1 dimension mismatch");
258 if (pk.size() != self.n())
259 throw std::invalid_argument("pk dimension mismatch");
260 if (pkp1.size() != self.n())
261 throw std::invalid_argument("pkp1 dimension mismatch");
262 return self.update(xk, xkp1, pk, pkp1, forced);
263 },
264 "xk"_a, "xkp1"_a, "pk"_a, "pkp1"_a, "forced"_a = false)
265 .def(
266 "update_sy",
268 bool forced) {
269 if (sk.size() != self.n())
270 throw std::invalid_argument("sk dimension mismatch");
271 if (yk.size() != self.n())
272 throw std::invalid_argument("yk dimension mismatch");
273 return self.update_sy(sk, yk, forced);
274 },
275 "sk"_a, "yk"_a, "forced"_a = false)
276 .def(
277 "apply",
278 [](quala::BroydenGood &self, quala::rvec q) {
279 if (q.size() != self.n())
280 throw std::invalid_argument("q dimension mismatch");
281 return self.apply(q);
282 },
283 "q")
284 .def("reset", &quala::BroydenGood::reset)
285 .def("current_history", &quala::BroydenGood::current_history)
286 .def_property_readonly("params", &quala::BroydenGood::get_params);
287}
Anderson Acceleration.
length_t current_history() const
Get the number of columns currently stored in the buffer.
const Params & get_params() const
Get the parameters.
void resize(length_t n)
Change the problem dimension.
void reset()
Reset the accelerator (but keep the last function value and residual, so calling initialize is not ne...
Broyden's “Good” method for solving systems of nonlinear equations .
length_t current_history() const
Get the number of previous s and y vectors currently stored in the buffer.
const Params & get_params() const
Get the parameters.
void resize(length_t n)
Re-allocate storage for a problem with a different size.
void reset()
Throw away the approximation and all previous vectors s and y.
Limited memory Broyden–Fletcher–Goldfarb–Shanno (L-BFGS) algorithm.
Definition: decl/lbfgs.hpp:72
static bool update_valid(const LBFGSParams &params, real_t yᵀs, real_t sᵀs, real_t pᵀp)
Check if the new vectors s and y allow for a valid BFGS update that preserves the positive definitene...
Definition: lbfgs.hpp:9
length_t current_history() const
Get the number of previous s and y vectors currently stored in the buffer.
Definition: decl/lbfgs.hpp:134
length_t n() const
Get the size of the s and y vectors in the buffer.
Definition: decl/lbfgs.hpp:125
const Params & get_params() const
Get the parameters.
Definition: decl/lbfgs.hpp:122
void resize(length_t n)
Re-allocate storage for a problem with a different size.
Definition: lbfgs.hpp:185
void reset()
Throw away the approximation and all previous vectors s and y.
Definition: lbfgs.hpp:180
Sign
The sign of the vectors passed to the LBFGS::update method.
Definition: decl/lbfgs.hpp:78
void scale_y(real_t factor)
Scale the stored y vectors by the given factor.
Definition: lbfgs.hpp:196
This file defines mappings from Python dicts (kwargs) to simple parameter structs.
Eigen::Ref< const vec > crvec
Default type for immutable references to vectors.
Definition: vec.hpp:18
real_t min_abs_s
Reject update if .
Definition: decl/lbfgs.hpp:15
real_t min_div_abs
Reject update if .
CBFGSParams cbfgs
Parameters in the cautious BFGS update condition.
Definition: decl/lbfgs.hpp:26
bool restarted
If set to true, the buffer is cleared after memory iterations.
length_t memory
Length of the history to keep.
Definition: decl/lbfgs.hpp:11
index_t length_t
Default type for vector sizes.
Definition: vec.hpp:29
bool force_pos_def
If set to true, the inverse Hessian estimate should remain definite, i.e.
Definition: decl/lbfgs.hpp:33
realvec vec
Default type for vectors.
Definition: vec.hpp:14
Eigen::Index index_t
Default type for vector indices.
Definition: vec.hpp:27
double real_t
Default floating point type.
Definition: vec.hpp:8
real_t min_div_fac
Reject update if .
Definition: decl/lbfgs.hpp:13
Eigen::Ref< vec > rvec
Default type for mutable references to vectors.
Definition: vec.hpp:16
#define MACRO_STRINGIFY(x)
Definition: quala.cpp:31
PYBIND11_MODULE(QUALA_MODULE_NAME, m)
Definition: quala.cpp:33
real_t ϵ
Set to zero to disable CBFGS check.
Definition: decl/lbfgs.hpp:20