alpaqa 0.0.1
Nonconvex constrained optimization
alpaqa.cpp
Go to the documentation of this file.
1/**
2 * @file
3 * This file defines all Python bindings.
4 */
5
6#include <alpaqa/decl/alm.hpp>
12#include <alpaqa/inner/pga.hpp>
16
17#if ALPAQA_HAVE_CASADI
19#endif
20
21#include <pybind11/attr.h>
22#include <pybind11/cast.h>
23#include <pybind11/chrono.h>
24#include <pybind11/detail/common.h>
25#include <pybind11/eigen.h>
26#include <pybind11/functional.h>
27#include <pybind11/iostream.h>
28#include <pybind11/pybind11.h>
29#include <pybind11/pytypes.h>
30#include <pybind11/stl.h>
31
32#include <memory>
33#include <optional>
34#include <stdexcept>
35#include <string>
36#include <tuple>
37#include <type_traits>
38#include <utility>
39
40#include "kwargs-to-struct.hpp"
43#include "problem.hpp"
44
45namespace py = pybind11;
46
47template <class DirectionProviderT>
49 return [](const std::variant<alpaqa::PANOCParams, py::dict> &pp,
50 const DirectionProviderT &dir) {
52 static_assert(std::is_base_of_v<Base, DirectionProviderT>);
53 auto full_python_copy = std::make_shared<py::object>(py::cast(dir));
54 auto base_copy = full_python_copy->template cast<Base *>();
55 return std::make_shared<alpaqa::PolymorphicPANOCSolver>(
58 std::shared_ptr<Base>(full_python_copy, base_copy),
59 });
60 };
61}
62
63template <class DirectionProviderT, class... DirectionArgumentsT>
65 return [](const std::variant<alpaqa::PANOCParams, py::dict> &pp,
66 const DirectionArgumentsT &...args) {
68 static_assert(std::is_base_of_v<Base, DirectionProviderT>);
69 static_assert(std::is_constructible_v<DirectionProviderT,
70 DirectionArgumentsT...>);
71 DirectionProviderT dir{args...};
72 return PolymorphicPANOCConstructor<DirectionProviderT>()(pp, dir);
73 };
74}
75
76template <class DirectionProviderT>
78 return [](const std::variant<alpaqa::PANOCParams, py::dict> &pp,
79 const std::variant<alpaqa::LBFGSParams, py::dict> &args) {
80 return PolymorphicPANOCConversion<DirectionProviderT,
82 pp, var_kwargs_to_struct(args));
83 };
84}
85
86template <class InnerSolverT>
88 return [](const std::variant<alpaqa::ALMParams, py::dict> &pp,
89 const InnerSolverT &inner) {
91 static_assert(std::is_base_of_v<Base, InnerSolverT>);
92 auto full_python_copy = std::make_shared<py::object>(py::cast(inner));
93 auto base_copy = full_python_copy->template cast<Base *>();
95 var_kwargs_to_struct<alpaqa::ALMParams>(pp),
96 std::shared_ptr<Base>(full_python_copy, base_copy),
97 };
98 };
99}
100
101template <class InnerSolverT>
103 return [](const InnerSolverT &inner) {
104 return PolymorphicALMConstructor<InnerSolverT>()(alpaqa::ALMParams(),
105 inner);
106 };
107}
108
109template <class InnerSolverT, class... InnerSolverArgumentsT>
111 return [](const std::variant<alpaqa::ALMParams, py::dict> &pp,
112 const InnerSolverArgumentsT &...args) {
114 static_assert(std::is_base_of_v<Base, InnerSolverT>);
115 static_assert(
116 std::is_constructible_v<InnerSolverT, InnerSolverArgumentsT...>);
117 InnerSolverT inner{args...};
118 return PolymorphicALMConstructor<InnerSolverT>()(pp, inner);
119 };
120}
121
122#define STRINGIFY(x) #x
123#define MACRO_STRINGIFY(x) STRINGIFY(x)
124
125PYBIND11_MODULE(ALPAQA_MODULE_NAME, m) {
126 using py::operator""_a;
127
128 py::options options;
129 options.enable_function_signatures();
130 options.enable_user_defined_docstrings();
131
132 m.doc() = "PANOC+ALM solvers"; // TODO
133
134#ifdef VERSION_INFO
135 m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO);
136#else
137 m.attr("__version__") = "dev";
138#endif
139
140 py::class_<alpaqa::Box>(m, "Box", "C++ documentation: :cpp:class:`alpaqa::Box`")
141 .def(py::init([](unsigned n) {
142 return alpaqa::Box{alpaqa::vec::Constant(n, alpaqa::inf),
143 alpaqa::vec::Constant(n, -alpaqa::inf)};
144 }),
145 "n"_a,
146 "Create an :math:`n`-dimensional box at with bounds at "
147 ":math:`\\pm\\infty` (no constraints).")
148 .def(py::init([](alpaqa::vec ub, alpaqa::vec lb) {
149 if (ub.size() != lb.size())
150 throw std::invalid_argument(
151 "Upper bound and lower bound dimensions do not "
152 "match");
153 return alpaqa::Box{std::move(ub), std::move(lb)};
154 }),
155 "ub"_a, "lb"_a, "Create a box with the given bounds.")
156 .def_readwrite("upperbound", &alpaqa::Box::upperbound)
157 .def_readwrite("lowerbound", &alpaqa::Box::lowerbound);
158
159 py::class_<alpaqa::Problem>(m, "Problem",
160 "C++ documentation: :cpp:class:`alpaqa::Problem`")
161 // .def(py::init())
162 .def(py::init<unsigned, unsigned>(), "n"_a, "m"_a,
163 ":param n: Number of unknowns\n"
164 ":param m: Number of constraints")
165 .def_readwrite("n", &alpaqa::Problem::n,
166 "Number of unknowns, dimension of :math:`x`")
167 .def_readwrite(
168 "m", &alpaqa::Problem::m,
169 "Number of general constraints, dimension of :math:`g(x)`")
170 .def_readwrite("C", &alpaqa::Problem::C, "Box constraints on :math:`x`")
171 .def_readwrite("D", &alpaqa::Problem::D, "Box constraints on :math:`g(x)`")
172 .def_property("f", prob_getter_f(), prob_setter_f(),
173 "Objective funcion, :math:`f(x)`")
174 .def_property(
176 "Gradient of the objective function, :math:`\\nabla f(x)`")
177 .def_property("g", prob_getter_g(), prob_setter_g(),
178 "Constraint function, :math:`g(x)`")
179 .def_property("grad_g_prod", prob_getter_grad_g_prod(),
181 "Gradient of constraint function times vector, "
182 ":math:`\\nabla g(x)\\, v`")
183 .def_property("grad_gi", prob_getter_grad_gi(), prob_setter_grad_gi(),
184 "Gradient vector of the :math:`i`-th component of the "
185 "constriant function, :math:`\\nabla g_i(x)`")
186 .def_property(
188 "Hessian of the Lagrangian function, :math:`\\nabla^2_{xx} L(x,y)`")
189 .def_property("hess_L_prod", prob_getter_hess_L_prod(),
191 "Hessian of the Lagrangian function times vector, "
192 ":math:`\\nabla^2_{xx} L(x,y)\\, v`");
193
194 py::class_<alpaqa::ProblemWithParam, alpaqa::Problem>(
195 m, "ProblemWithParam",
196 "C++ documentation: :cpp:class:`alpaqa::ProblemWithParam`\n\n"
197 "See :py:class:`alpaqa._alpaqa.Problem` for the full documentation.")
198 .def_readwrite("n", &alpaqa::ProblemWithParam::n)
199 .def_readwrite("m", &alpaqa::ProblemWithParam::m)
200 .def_readwrite("C", &alpaqa::ProblemWithParam::C)
201 .def_readwrite("D", &alpaqa::ProblemWithParam::D)
202 .def_property_readonly("f", prob_getter_f())
203 .def_property_readonly("grad_f", prob_getter_grad_f())
204 .def_property_readonly("g", prob_getter_g())
205 .def_property_readonly("grad_g_prod", prob_getter_grad_g_prod())
206 .def_property_readonly("grad_gi", prob_getter_grad_gi())
207 .def_property_readonly("hess_L", prob_getter_hess_L())
208 .def_property_readonly("hess_L_prod", prob_getter_hess_L_prod())
209 .def_property(
210 "param", py::overload_cast<>(&alpaqa::ProblemWithParam::get_param),
212 if (param.size() != p.get_param().size())
213 throw std::invalid_argument(
214 "Invalid parameter dimension: got " +
215 std::to_string(param.size()) + ", should be " +
216 std::to_string(p.get_param().size()) + ".");
217 p.set_param(param);
218 },
219 "Parameter vector :math:`p` of the problem");
220
221 py::class_<alpaqa::EvalCounter::EvalTimer>(
222 m, "EvalTimer",
223 "C++ documentation: "
224 ":cpp:class:`alpaqa::EvalCounter::EvalTimer`\n\n")
225 .def(py::pickle(
226 [](const alpaqa::EvalCounter::EvalTimer &p) { // __getstate__
227 return py::make_tuple(p.f, p.grad_f, p.g, p.grad_g_prod,
228 p.grad_gi, p.hess_L_prod, p.hess_L);
229 },
230 [](py::tuple t) { // __setstate__
231 if (t.size() != 7)
232 throw std::runtime_error("Invalid state!");
234 return T{
235 py::cast<decltype(T::f)>(t[0]),
236 py::cast<decltype(T::grad_f)>(t[1]),
237 py::cast<decltype(T::g)>(t[2]),
238 py::cast<decltype(T::grad_g_prod)>(t[3]),
239 py::cast<decltype(T::grad_gi)>(t[4]),
240 py::cast<decltype(T::hess_L_prod)>(t[5]),
241 py::cast<decltype(T::hess_L)>(t[6]),
242 };
243 }))
244 .def_readwrite("f", &alpaqa::EvalCounter::EvalTimer::f)
245 .def_readwrite("grad_f", &alpaqa::EvalCounter::EvalTimer::grad_f)
246 .def_readwrite("g", &alpaqa::EvalCounter::EvalTimer::g)
247 .def_readwrite("grad_g_prod", &alpaqa::EvalCounter::EvalTimer::grad_g_prod)
248 .def_readwrite("grad_gi", &alpaqa::EvalCounter::EvalTimer::grad_gi)
249 .def_readwrite("hess_L_prod", &alpaqa::EvalCounter::EvalTimer::hess_L_prod)
250 .def_readwrite("hess_L", &alpaqa::EvalCounter::EvalTimer::hess_L);
251
252 py::class_<alpaqa::EvalCounter>(m, "EvalCounter",
253 "C++ documentation: "
254 ":cpp:class:`alpaqa::EvalCounter`\n\n")
255 .def(py::pickle(
256 [](const alpaqa::EvalCounter &p) { // __getstate__
257 return py::make_tuple(p.f, p.grad_f, p.g, p.grad_g_prod,
258 p.grad_gi, p.hess_L_prod, p.hess_L,
259 p.time);
260 },
261 [](py::tuple t) { // __setstate__
262 if (t.size() != 8)
263 throw std::runtime_error("Invalid state!");
264 using T = alpaqa::EvalCounter;
265 return T{
266 py::cast<decltype(T::f)>(t[0]),
267 py::cast<decltype(T::grad_f)>(t[1]),
268 py::cast<decltype(T::g)>(t[2]),
269 py::cast<decltype(T::grad_g_prod)>(t[3]),
270 py::cast<decltype(T::grad_gi)>(t[4]),
271 py::cast<decltype(T::hess_L_prod)>(t[5]),
272 py::cast<decltype(T::hess_L)>(t[6]),
273 py::cast<decltype(T::time)>(t[7]),
274 };
275 }))
276 .def_readwrite("f", &alpaqa::EvalCounter::f)
277 .def_readwrite("grad_f", &alpaqa::EvalCounter::grad_f)
278 .def_readwrite("g", &alpaqa::EvalCounter::g)
279 .def_readwrite("grad_g_prod", &alpaqa::EvalCounter::grad_g_prod)
280 .def_readwrite("grad_gi", &alpaqa::EvalCounter::grad_gi)
281 .def_readwrite("hess_L_prod", &alpaqa::EvalCounter::hess_L_prod)
282 .def_readwrite("hess_L", &alpaqa::EvalCounter::hess_L)
283 .def_readwrite("time", &alpaqa::EvalCounter::time);
284
285 py::class_<alpaqa::ProblemWithCounters<alpaqa::Problem>, alpaqa::Problem>(
286 m, "ProblemWithCounters",
287 "C++ documentation: "
288 ":cpp:class:`alpaqa::ProblemWithCounters<alpaqa::Problem>`\n\n"
289 "See :py:class:`alpaqa._alpaqa.Problem` for the full documentation.")
290 .def(py::init<const alpaqa::Problem &>(), "problem"_a)
295 .def_property_readonly("f", prob_getter_f())
296 .def_property_readonly("grad_f", prob_getter_grad_f())
297 .def_property_readonly("g", prob_getter_g())
298 .def_property_readonly("grad_g_prod", prob_getter_grad_g_prod())
299 .def_property_readonly("grad_gi", prob_getter_grad_gi())
300 .def_property_readonly("hess_L", prob_getter_hess_L())
301 .def_property_readonly("hess_L_prod", prob_getter_hess_L_prod())
302 .def_property_readonly(
303 "evaluations", [](const alpaqa::ProblemWithCounters<alpaqa::Problem> &p) {
304 return *p.evaluations;
305 });
306
307 py::class_<alpaqa::ProblemWithCounters<alpaqa::ProblemWithParam>,
309 m, "ProblemWithParamWithCounters",
310 "C++ documentation: "
311 ":cpp:class:`alpaqa::ProblemWithCounters<alpaqa::ProblemWithParam>`\n\n"
312 "See :py:class:`alpaqa._alpaqa.Problem` for the full documentation.")
313 .def(py::init<const alpaqa::ProblemWithParam &>(), "problem"_a)
318 .def_property_readonly("f", prob_getter_f())
319 .def_property_readonly("grad_f", prob_getter_grad_f())
320 .def_property_readonly("g", prob_getter_g())
321 .def_property_readonly("grad_g_prod", prob_getter_grad_g_prod())
322 .def_property_readonly("grad_gi", prob_getter_grad_gi())
323 .def_property_readonly("hess_L", prob_getter_hess_L())
324 .def_property_readonly("hess_L_prod", prob_getter_hess_L_prod())
325 .def_property(
326 "param",
327 py::overload_cast<>(
331 if (param.size() != p.get_param().size())
332 throw std::invalid_argument(
333 "Invalid parameter dimension: got " +
334 std::to_string(param.size()) + ", should be " +
335 std::to_string(p.get_param().size()) + ".");
336 p.set_param(param);
337 },
338 "Parameter vector :math:`p` of the problem")
339 .def_property_readonly(
340 "evaluations",
342 return *p.evaluations;
343 });
344
346 std::shared_ptr<alpaqa::PolymorphicPANOCDirectionBase>,
348 m, "PANOCDirection",
349 "Class that provides fast directions for the PANOC algorithm (e.g. "
350 "L-BFGS)")
351 .def(py::init<>())
359
360 using paLBFGSParamCBFGS = decltype(alpaqa::LBFGSParams::cbfgs);
361 py::class_<paLBFGSParamCBFGS>(
362 m, "LBFGSParamsCBFGS",
363 "C++ documentation: :cpp:member:`alpaqa::LBFGSParams::cbfgs`")
364 .def(py::init())
365 .def(py::init(&kwargs_to_struct<paLBFGSParamCBFGS>))
366 .def("to_dict", &struct_to_dict<paLBFGSParamCBFGS>)
367 .def_readwrite("α", &paLBFGSParamCBFGS::α)
368 .def_readwrite("ϵ", &paLBFGSParamCBFGS::ϵ);
369
370 py::class_<alpaqa::LBFGSParams>(
371 m, "LBFGSParams", "C++ documentation: :cpp:class:`alpaqa::LBFGSParams`")
372 .def(py::init())
373 .def(py::init(&kwargs_to_struct<alpaqa::LBFGSParams>))
374 .def("to_dict", &struct_to_dict<alpaqa::LBFGSParams>)
375 .def_readwrite("memory", &alpaqa::LBFGSParams::memory)
376 .def_readwrite("cbfgs", &alpaqa::LBFGSParams::cbfgs)
377 .def_readwrite("rescale_when_γ_changes",
379
381 std::shared_ptr<alpaqa::PolymorphicLBFGSDirection>,
383 m, "LBFGSDirection",
384 "C++ documentation: :cpp:class:`alpaqa::LBFGSDirection`")
385 .def(py::init<alpaqa::LBFGSParams>(), "params"_a)
393 .def_property_readonly("params",
395
396 py::enum_<alpaqa::LBFGSStepSize>(
397 m, "LBFGSStepsize", "C++ documentation: :cpp:enum:`alpaqa::LBFGSStepSize`")
398 .value("BasedOnGradientStepSize",
400 .value("BasedOnCurvature", alpaqa::LBFGSStepSize::BasedOnCurvature)
401 .export_values();
402
403 py::class_<alpaqa::LipschitzEstimateParams>(
404 m, "LipschitzEstimateParams",
405 "C++ documentation: :cpp:class:`alpaqa::LipschitzEstimateParams`")
406 .def(py::init())
407 .def(py::init(&kwargs_to_struct<alpaqa::LipschitzEstimateParams>))
408 .def("to_dict", &struct_to_dict<alpaqa::LipschitzEstimateParams>)
409 .def_readwrite("L_0", &alpaqa::LipschitzEstimateParams::L₀)
410 .def_readwrite("ε", &alpaqa::LipschitzEstimateParams::ε)
411 .def_readwrite("δ", &alpaqa::LipschitzEstimateParams::δ)
412 .def_readwrite("Lγ_factor", &alpaqa::LipschitzEstimateParams::Lγ_factor);
413
414 py::class_<alpaqa::PANOCParams>(
415 m, "PANOCParams", "C++ documentation: :cpp:class:`alpaqa::PANOCParams`")
416 .def(py::init())
417 .def(py::init(&kwargs_to_struct<alpaqa::PANOCParams>))
418 .def("to_dict", &struct_to_dict<alpaqa::PANOCParams>)
419 .def_readwrite("Lipschitz", &alpaqa::PANOCParams::Lipschitz)
420 .def_readwrite("max_iter", &alpaqa::PANOCParams::max_iter)
421 .def_readwrite("max_time", &alpaqa::PANOCParams::max_time)
422 .def_readwrite("τ_min", &alpaqa::PANOCParams::τ_min)
423 .def_readwrite("L_min", &alpaqa::PANOCParams::L_min)
424 .def_readwrite("L_max", &alpaqa::PANOCParams::L_max)
425 .def_readwrite("max_no_progress", &alpaqa::PANOCParams::max_no_progress)
426 .def_readwrite("print_interval", &alpaqa::PANOCParams::print_interval)
427 .def_readwrite("quadratic_upperbound_tolerance_factor",
429 .def_readwrite("update_lipschitz_in_linesearch",
431 .def_readwrite("alternative_linesearch_cond",
433 .def_readwrite("lbfgs_stepsize", &alpaqa::PANOCParams::lbfgs_stepsize);
434
435 py::enum_<alpaqa::SolverStatus>(
436 m, "SolverStatus", py::arithmetic(),
437 "C++ documentation: :cpp:enum:`alpaqa::SolverStatus`")
438 .value("Unknown", alpaqa::SolverStatus::Unknown, "Initial value")
439 .value("Converged", alpaqa::SolverStatus::Converged,
440 "Converged and reached given tolerance")
441 .value("MaxTime", alpaqa::SolverStatus::MaxTime,
442 "Maximum allowed execution time exceeded")
443 .value("MaxIter", alpaqa::SolverStatus::MaxIter,
444 "Maximum number of iterations exceeded")
445 .value("NotFinite", alpaqa::SolverStatus::NotFinite,
446 "Intermediate results were infinite or not-a-number")
447 .value("NoProgress", alpaqa::SolverStatus::NoProgress,
448 "No progress was made in the last iteration")
449 .value("Interrupted", alpaqa::SolverStatus::Interrupted,
450 "Solver was interrupted by the user")
451 .export_values();
452
453 py::class_<alpaqa::PolymorphicInnerSolverBase::Stats>(m, "InnerSolverStats")
455
457 std::shared_ptr<alpaqa::PolymorphicInnerSolverBase>,
459 .def(py::init<>())
460 .def("__call__", &alpaqa::PolymorphicInnerSolverBase::operator())
464
465 py::enum_<alpaqa::PANOCStopCrit>(
466 m, "PANOCStopCrit", "C++ documentation: :cpp:enum:`alpaqa::PANOCStopCrit`")
467 .value("ApproxKKT", alpaqa::PANOCStopCrit::ApproxKKT)
468 .value("ApproxKKT2", alpaqa::PANOCStopCrit::ApproxKKT2)
469 .value("ProjGradNorm", alpaqa::PANOCStopCrit::ProjGradNorm)
470 .value("ProjGradNorm2", alpaqa::PANOCStopCrit::ProjGradNorm2)
471 .value("ProjGradUnitNorm", alpaqa::PANOCStopCrit::ProjGradUnitNorm)
472 .value("ProjGradUnitNorm2", alpaqa::PANOCStopCrit::ProjGradUnitNorm2)
473 .value("FPRNorm", alpaqa::PANOCStopCrit::FPRNorm)
474 .value("FPRNorm2", alpaqa::PANOCStopCrit::FPRNorm2)
475 .value("Ipopt", alpaqa::PANOCStopCrit::Ipopt)
476 .export_values();
477
478 py::class_<alpaqa::PGAParams>(m, "PGAParams",
479 "C++ documentation: :cpp:class:`alpaqa::PGAParams`")
480 .def(py::init())
481 .def(py::init(&kwargs_to_struct<alpaqa::PGAParams>))
482 .def("to_dict", &struct_to_dict<alpaqa::PGAParams>)
483 .def_readwrite("Lipschitz", &alpaqa::PGAParams::Lipschitz)
484 .def_readwrite("max_iter", &alpaqa::PGAParams::max_iter)
485 .def_readwrite("max_time", &alpaqa::PGAParams::max_time)
486 .def_readwrite("L_min", &alpaqa::PGAParams::L_min)
487 .def_readwrite("L_max", &alpaqa::PGAParams::L_max)
488 .def_readwrite("stop_crit", &alpaqa::PGAParams::stop_crit)
489 .def_readwrite("print_interval", &alpaqa::PGAParams::print_interval)
490 .def_readwrite("quadratic_upperbound_tolerance_factor",
492
493 py::class_<alpaqa::PGAProgressInfo>(
494 m, "PGAProgressInfo",
495 "C++ documentation: :cpp:class:`alpaqa::PGAProgressInfo`")
496 .def_readonly("k", &alpaqa::PGAProgressInfo::k)
497 .def_readonly("x", &alpaqa::PGAProgressInfo::x)
498 .def_readonly("p", &alpaqa::PGAProgressInfo::p)
499 .def_readonly("norm_sq_p", &alpaqa::PGAProgressInfo::norm_sq_p)
500 .def_readonly("x_hat", &alpaqa::PGAProgressInfo::x_hat)
501 .def_readonly("ψ", &alpaqa::PGAProgressInfo::ψ)
502 .def_readonly("grad_ψ", &alpaqa::PGAProgressInfo::grad_ψ)
503 .def_readonly("ψ_hat", &alpaqa::PGAProgressInfo::ψ_hat)
504 .def_readonly("grad_ψ_hat", &alpaqa::PGAProgressInfo::grad_ψ_hat)
505 .def_readonly("L", &alpaqa::PGAProgressInfo::L)
506 .def_readonly("γ", &alpaqa::PGAProgressInfo::γ)
507 .def_readonly("ε", &alpaqa::PGAProgressInfo::ε)
508 .def_readonly("Σ", &alpaqa::PGAProgressInfo::Σ)
509 .def_readonly("y", &alpaqa::PGAProgressInfo::y)
510 .def_property_readonly("fpr", [](const alpaqa::PGAProgressInfo &p) {
511 return std::sqrt(p.norm_sq_p) / p.γ;
512 });
513
514 py::class_<alpaqa::GAAPGAParams>(
515 m, "GAAPGAParams", "C++ documentation: :cpp:class:`alpaqa::GAAPGAParams`")
516 .def(py::init())
517 .def(py::init(&kwargs_to_struct<alpaqa::GAAPGAParams>))
518 .def("to_dict", &struct_to_dict<alpaqa::GAAPGAParams>)
519 .def_readwrite("Lipschitz", &alpaqa::GAAPGAParams::Lipschitz)
520 .def_readwrite("limitedqr_mem", &alpaqa::GAAPGAParams::limitedqr_mem)
521 .def_readwrite("max_iter", &alpaqa::GAAPGAParams::max_iter)
522 .def_readwrite("max_time", &alpaqa::GAAPGAParams::max_time)
523 .def_readwrite("L_min", &alpaqa::GAAPGAParams::L_min)
524 .def_readwrite("L_max", &alpaqa::GAAPGAParams::L_max)
525 .def_readwrite("stop_crit", &alpaqa::GAAPGAParams::stop_crit)
526 .def_readwrite("print_interval", &alpaqa::GAAPGAParams::print_interval)
527 .def_readwrite("quadratic_upperbound_tolerance_factor",
529 .def_readwrite("max_no_progress", &alpaqa::GAAPGAParams::max_no_progress)
530 .def_readwrite("full_flush_on_γ_change",
532
533 py::class_<alpaqa::GAAPGAProgressInfo>(
534 m, "GAAPGAProgressInfo",
535 "C++ documentation: :cpp:class:`alpaqa::GAAPGAProgressInfo`")
536 .def_readonly("k", &alpaqa::GAAPGAProgressInfo::k)
537 .def_readonly("x", &alpaqa::GAAPGAProgressInfo::x)
538 .def_readonly("p", &alpaqa::GAAPGAProgressInfo::p)
539 .def_readonly("norm_sq_p", &alpaqa::GAAPGAProgressInfo::norm_sq_p)
540 .def_readonly("x_hat", &alpaqa::GAAPGAProgressInfo::x_hat)
541 .def_readonly("ψ", &alpaqa::GAAPGAProgressInfo::ψ)
542 .def_readonly("grad_ψ", &alpaqa::GAAPGAProgressInfo::grad_ψ)
543 .def_readonly("ψ_hat", &alpaqa::GAAPGAProgressInfo::ψ_hat)
544 .def_readonly("grad_ψ_hat", &alpaqa::GAAPGAProgressInfo::grad_ψ_hat)
545 .def_readonly("L", &alpaqa::GAAPGAProgressInfo::L)
546 .def_readonly("γ", &alpaqa::GAAPGAProgressInfo::γ)
547 .def_readonly("ε", &alpaqa::GAAPGAProgressInfo::ε)
548 .def_readonly("Σ", &alpaqa::GAAPGAProgressInfo::Σ)
549 .def_readonly("y", &alpaqa::GAAPGAProgressInfo::y)
550 .def_property_readonly("fpr", [](const alpaqa::GAAPGAProgressInfo &p) {
551 return std::sqrt(p.norm_sq_p) / p.γ;
552 });
553
554 py::class_<alpaqa::PANOCProgressInfo>(
555 m, "PANOCProgressInfo",
556 "Data passed to the PANOC progress callback.\n\n"
557 "C++ documentation: :cpp:class:`alpaqa::PANOCProgressInfo`")
558 .def_readonly("k", &alpaqa::PANOCProgressInfo::k, //
559 "Iteration")
560 .def_readonly("x", &alpaqa::PANOCProgressInfo::x, //
561 "Decision variable :math:`x`")
562 .def_readonly("p", &alpaqa::PANOCProgressInfo::p, //
563 "Projected gradient step :math:`p`")
564 .def_readonly("norm_sq_p", &alpaqa::PANOCProgressInfo::norm_sq_p, //
565 ":math:`\\left\\|p\\right\\|^2`")
566 .def_readonly(
568 "Decision variable after projected gradient step :math:`\\hat x`")
569 .def_readonly("φγ", &alpaqa::PANOCProgressInfo::φγ, //
570 "Forward-backward envelope :math:`\\varphi_\\gamma(x)`")
571 .def_readonly("ψ", &alpaqa::PANOCProgressInfo::ψ, //
572 "Objective value :math:`\\psi(x)`")
573 .def_readonly("grad_ψ", &alpaqa::PANOCProgressInfo::grad_ψ, //
574 "Gradient of objective :math:`\\nabla\\psi(x)`")
575 .def_readonly("ψ_hat", &alpaqa::PANOCProgressInfo::ψ_hat)
576 .def_readonly("grad_ψ_hat", &alpaqa::PANOCProgressInfo::grad_ψ_hat)
577 .def_readonly("L", &alpaqa::PANOCProgressInfo::L, //
578 "Estimate of Lipschitz constant of objective :math:`L`")
579 .def_readonly("γ", &alpaqa::PANOCProgressInfo::γ,
580 "Step size :math:`\\gamma`")
581 .def_readonly("τ", &alpaqa::PANOCProgressInfo::τ, //
582 "Line search parameter :math:`\\tau`")
583 .def_readonly("ε", &alpaqa::PANOCProgressInfo::ε, //
584 "Tolerance reached :math:`\\varepsilon_k`")
585 .def_readonly("Σ", &alpaqa::PANOCProgressInfo::Σ, //
586 "Penalty factor :math:`\\Sigma`")
587 .def_readonly("y", &alpaqa::PANOCProgressInfo::y, //
588 "Lagrange multipliers :math:`y`")
589 .def_property_readonly(
590 "fpr",
591 [](const alpaqa::PANOCProgressInfo &p) {
592 return std::sqrt(p.norm_sq_p) / p.γ;
593 },
594 "Fixed-point residual :math:`\\left\\|p\\right\\| / \\gamma`");
595
596 py::class_<alpaqa::StructuredPANOCLBFGSProgressInfo>(
597 m, "StructuredPANOCLBFGSProgressInfo",
598 "Data passed to the structured PANOC progress callback.\n\n"
599 "C++ documentation: :cpp:class:`alpaqa::StructuredPANOCLBFGSProgressInfo`")
603 .def_readonly("norm_sq_p",
610 .def_readonly("grad_ψ_hat",
618 .def_property_readonly(
620 return std::sqrt(p.norm_sq_p) / p.γ;
621 });
622
624 std::shared_ptr<alpaqa::PolymorphicPANOCSolver>,
626 m, "PANOCSolver", "C++ documentation: :cpp:class:`alpaqa::PANOCSolver`")
627 .def(py::init([] {
628 return std::make_shared<alpaqa::PolymorphicPANOCSolver>(
631 std::static_pointer_cast<alpaqa::PolymorphicPANOCDirectionBase>(
632 std::make_shared<alpaqa::PolymorphicLBFGSDirection>(
634 }))
635 .def(py::init(PolymorphicPANOCConstructor< //
637 "panoc_params"_a, "lbfgs_direction"_a)
638 .def(py::init(PolymorphicPANOCDefaultConversion< //
640 "panoc_params"_a, "lbfgs_params"_a)
641 .def(py::init(PolymorphicPANOCConstructor< //
643 "panoc_params"_a, "direction"_a)
644 .def(
645 "set_progress_callback",
647 "Attach a callback that is called on each iteration of the solver.")
648 .def("__call__",
649 alpaqa::InnerSolverCallWrapper<alpaqa::PolymorphicPANOCSolver>(),
650 py::call_guard<py::scoped_ostream_redirect,
651 py::scoped_estream_redirect>(),
652 "problem"_a, "Σ"_a, "ε"_a, "x"_a,
653 "y"_a, //
654 "Solve.\n\n"
655 ":param problem: Problem to solve\n"
656 ":param Σ: Penalty factor\n"
657 ":param ε: Desired tolerance\n"
658 ":param x: Initial guess\n"
659 ":param y: Initial Lagrange multipliers\n\n"
660 ":return: * Solution :math:`x`\n"
661 " * Updated Lagrange multipliers :math:`y`\n"
662 " * Slack variable error :math:`g(x) - z`\n"
663 " * Statistics\n\n")
665 .def_property_readonly("params",
667 .def_property_readonly(
668 "direction", [](const alpaqa::PolymorphicPANOCSolver &s) {
669 return s.innersolver.direction_provider.direction;
670 });
671
673 std::shared_ptr<alpaqa::PolymorphicPGASolver>,
675 m, "PGASolver", "C++ documentation: :cpp:class:`alpaqa::PGASolver`")
676 .def(py::init<alpaqa::PGAParams>())
677 .def(
678 "set_progress_callback",
680 "Attach a callback that is called on each iteration of the solver.")
681 .def("__call__", alpaqa::InnerSolverCallWrapper<alpaqa::PolymorphicPGASolver>(),
682 py::call_guard<py::scoped_ostream_redirect,
683 py::scoped_estream_redirect>(),
684 "problem"_a, "Σ"_a, "ε"_a, "x"_a,
685 "y"_a, //
686 "Solve.\n\n"
687 ":param problem: Problem to solve\n"
688 ":param Σ: Penalty factor\n"
689 ":param ε: Desired tolerance\n"
690 ":param x: Initial guess\n"
691 ":param y: Initial Lagrange multipliers\n\n"
692 ":return: * Solution :math:`x`\n"
693 " * Updated Lagrange multipliers :math:`y`\n"
694 " * Slack variable error :math:`g(x) - z`\n"
695 " * Statistics\n\n")
697 .def_property_readonly("params", &alpaqa::PolymorphicPGASolver::get_params);
698
700 std::shared_ptr<alpaqa::PolymorphicGAAPGASolver>,
702 m, "GAAPGASolver", "C++ documentation: :cpp:class:`alpaqa::GAAPGASolver`")
703 .def(py::init<alpaqa::GAAPGAParams>())
704 .def(
705 "set_progress_callback",
707 "Attach a callback that is called on each iteration of the solver.")
708 .def("__call__",
709 alpaqa::InnerSolverCallWrapper<alpaqa::PolymorphicGAAPGASolver>(),
710 py::call_guard<py::scoped_ostream_redirect,
711 py::scoped_estream_redirect>(),
712 "problem"_a, "Σ"_a, "ε"_a, "x"_a,
713 "y"_a, //
714 "Solve.\n\n"
715 ":param problem: Problem to solve\n"
716 ":param Σ: Penalty factor\n"
717 ":param ε: Desired tolerance\n"
718 ":param x: Initial guess\n"
719 ":param y: Initial Lagrange multipliers\n\n"
720 ":return: * Solution :math:`x`\n"
721 " * Updated Lagrange multipliers :math:`y`\n"
722 " * Slack variable error :math:`g(x) - z`\n"
723 " * Statistics\n\n")
725 .def_property_readonly("params",
727
728 py::class_<alpaqa::StructuredPANOCLBFGSParams>(
729 m, "StructuredPANOCLBFGSParams",
730 "C++ documentation: :cpp:class:`alpaqa::StructuredPANOCLBFGSParams`")
731 .def(py::init(&kwargs_to_struct<alpaqa::StructuredPANOCLBFGSParams>))
732 .def("to_dict", &struct_to_dict<alpaqa::StructuredPANOCLBFGSParams>)
733
734 .def_readwrite("Lipschitz", &alpaqa::StructuredPANOCLBFGSParams::Lipschitz)
735 .def_readwrite("max_iter", &alpaqa::StructuredPANOCLBFGSParams::max_iter)
736 .def_readwrite("max_time", &alpaqa::StructuredPANOCLBFGSParams::max_time)
737 .def_readwrite("τ_min", &alpaqa::StructuredPANOCLBFGSParams::τ_min)
738 .def_readwrite("L_min", &alpaqa::StructuredPANOCLBFGSParams::L_min)
739 .def_readwrite("L_max", &alpaqa::StructuredPANOCLBFGSParams::L_max)
740 .def_readwrite("nonmonotone_linesearch",
742 .def_readwrite("stop_crit", &alpaqa::StructuredPANOCLBFGSParams::stop_crit)
743 .def_readwrite("max_no_progress",
745 .def_readwrite("print_interval",
747 .def_readwrite("quadratic_upperbound_tolerance_factor",
749 quadratic_upperbound_tolerance_factor)
750 .def_readwrite(
751 "update_lipschitz_in_linesearch",
753 .def_readwrite(
754 "alternative_linesearch_cond",
756 .def_readwrite("hessian_vec",
758 .def_readwrite(
759 "hessian_vec_finite_differences",
761 .def_readwrite("full_augmented_hessian",
763 .def_readwrite(
764 "hessian_step_size_heuristic",
766 .def_readwrite("lbfgs_stepsize",
768
770 std::shared_ptr<alpaqa::PolymorphicStructuredPANOCLBFGSSolver>,
772 m, "StructuredPANOCLBFGSSolver",
773 "C++ documentation: :cpp:class:`alpaqa::StructuredPANOCLBFGSSolver`")
774 .def(py::init([] {
775 return std::make_shared<alpaqa::PolymorphicStructuredPANOCLBFGSSolver>(
779 });
780 }))
781 .def(py::init([](const std::variant<alpaqa::StructuredPANOCLBFGSParams,
782 py::dict> &pp,
783 const std::variant<alpaqa::LBFGSParams, py::dict> &lp) {
784 return std::make_shared<
787 }),
788 "panoc_params"_a, "lbfgs_params"_a)
789 .def(
790 "set_progress_callback",
792 "callback"_a,
793 "Attach a callback that is called on each iteration of the solver.")
794 .def("__call__",
797 py::call_guard<py::scoped_ostream_redirect,
798 py::scoped_estream_redirect>(),
799 "problem"_a, "Σ"_a, "ε"_a, "x"_a,
800 "y"_a, //
801 "Solve.\n\n"
802 ":param problem: Problem to solve\n"
803 ":param Σ: Penalty factor\n"
804 ":param ε: Desired tolerance\n"
805 ":param x: Initial guess\n"
806 ":param y: Initial Lagrange multipliers\n\n"
807 ":return: * Solution :math:`x`\n"
808 " * Updated Lagrange multipliers :math:`y`\n"
809 " * Slack variable error :math:`g(x) - z`\n"
810 " * Statistics\n\n")
812 .def_property_readonly(
814
815 py::class_<alpaqa::ALMParams>(m, "ALMParams",
816 "C++ documentation: :cpp:class:`alpaqa::ALMParams`")
817 .def(py::init())
818 .def(py::init(&kwargs_to_struct<alpaqa::ALMParams>))
819 .def("to_dict", &struct_to_dict<alpaqa::ALMParams>)
820 .def_readwrite("ε", &alpaqa::ALMParams::ε)
821 .def_readwrite("δ", &alpaqa::ALMParams::δ)
822 .def_readwrite("Δ", &alpaqa::ALMParams::Δ)
823 .def_readwrite("Δ_lower", &alpaqa::ALMParams::Δ_lower)
824 .def_readwrite("Σ_0", &alpaqa::ALMParams::Σ₀)
825 .def_readwrite("σ_0", &alpaqa::ALMParams::σ₀)
826 .def_readwrite("Σ_0_lower", &alpaqa::ALMParams::Σ₀_lower)
827 .def_readwrite("ε_0", &alpaqa::ALMParams::ε₀)
828 .def_readwrite("ε_0_increase", &alpaqa::ALMParams::ε₀_increase)
829 .def_readwrite("ρ", &alpaqa::ALMParams::ρ)
830 .def_readwrite("ρ_increase", &alpaqa::ALMParams::ρ_increase)
831 .def_readwrite("θ", &alpaqa::ALMParams::θ)
832 .def_readwrite("M", &alpaqa::ALMParams::M)
833 .def_readwrite("Σ_max", &alpaqa::ALMParams::Σ_max)
834 .def_readwrite("Σ_min", &alpaqa::ALMParams::Σ_min)
835 .def_readwrite("max_iter", &alpaqa::ALMParams::max_iter)
836 .def_readwrite("max_time", &alpaqa::ALMParams::max_time)
837 .def_readwrite("max_num_initial_retries",
839 .def_readwrite("max_num_retries", &alpaqa::ALMParams::max_num_retries)
840 .def_readwrite("max_total_num_retries",
842 .def_readwrite("print_interval", &alpaqa::ALMParams::print_interval)
843 .def_readwrite("preconditioning", &alpaqa::ALMParams::preconditioning)
844 .def_readwrite("single_penalty_factor",
846
847 py::class_<alpaqa::PolymorphicALMSolver>(
848 m, "ALMSolver",
849 "Main augmented Lagrangian solver.\n\n"
850 "C++ documentation: :cpp:class:`alpaqa::ALMSolver`")
851 // Default constructor
852 .def(py::init([] {
855 std::static_pointer_cast<alpaqa::PolymorphicInnerSolverBase>(
856 std::make_shared<
860 };
861 }),
862 "Build an ALM solver using Structured PANOC as inner solver.")
863 // Params and solver
864 .def(py::init(PolymorphicALMConstructor<alpaqa::PolymorphicPANOCSolver>()),
865 "alm_params"_a, "panoc_solver"_a,
866 "Build an ALM solver using PANOC as inner solver.")
867 .def(py::init(PolymorphicALMConstructor<alpaqa::PolymorphicPGASolver>()),
868 "alm_params"_a, "pga_solver"_a,
869 "Build an ALM solver using the projected gradient algorithm as "
870 "inner solver.")
871 .def(py::init(PolymorphicALMConstructor<
873 "alm_params"_a, "structuredpanoc_solver"_a,
874 "Build an ALM solver using Structured PANOC as inner solver.")
875 .def(py::init(PolymorphicALMConstructor<
877 "alm_params"_a, "inner_solver"_a,
878 "Build an ALM solver using a custom inner solver.")
879 // Only solver (default params)
882 "panoc_solver"_a,
883 "Build an ALM solver using PANOC as inner solver.")
886 "pga_solver"_a,
887 "Build an ALM solver using the projected gradient algorithm as "
888 "inner solver.")
891 "structuredpanoc_solver"_a,
892 "Build an ALM solver using Structured PANOC as inner solver.")
895 "inner_solver"_a,
896 "Build an ALM solver using a custom inner solver.")
897 // Only params (default solver)
898 .def(py::init([](const alpaqa::ALMParams &params) {
900 params,
901 std::static_pointer_cast<alpaqa::PolymorphicInnerSolverBase>(
902 std::make_shared<
906 };
907 }),
908 "alm_params"_a,
909 "Build an ALM solver using Structured PANOC as inner solver.")
910 // Other functions and properties
911 .def_property_readonly("inner_solver",
912 [](const alpaqa::PolymorphicALMSolver &s) {
913 return s.inner_solver.solver;
914 })
915 .def(
916 "__call__",
918 std::optional<alpaqa::vec> x, std::optional<alpaqa::vec> y)
919 -> std::tuple<alpaqa::vec, alpaqa::vec, py::dict> {
920 if (!x)
921 x = alpaqa::vec::Zero(p.n);
922 else if (x->size() != p.n)
923 throw std::invalid_argument(
924 "Length of x does not match problem size problem.n");
925 if (!y)
926 y = alpaqa::vec::Zero(p.m);
927 else if (y->size() != p.m)
928 throw std::invalid_argument(
929 "Length of y does not match problem size problem.m");
930 if (p.C.lowerbound.size() != p.n)
931 throw std::invalid_argument(
932 "Length of problem.C.lowerbound does not match problem "
933 "size problem.n");
934 if (p.C.upperbound.size() != p.n)
935 throw std::invalid_argument(
936 "Length of problem.C.upperbound does not match problem "
937 "size problem.n");
938 if (p.D.lowerbound.size() != p.m)
939 throw std::invalid_argument(
940 "Length of problem.D.lowerbound does not match problem "
941 "size problem.m");
942 if (p.D.upperbound.size() != p.m)
943 throw std::invalid_argument(
944 "Length of problem.D.upperbound does not match problem "
945 "size problem.m");
946
947 auto stats = solver(p, *y, *x);
948 return std::make_tuple(std::move(*x), std::move(*y),
950 },
951 "problem"_a, "x"_a = std::nullopt, "y"_a = std::nullopt,
952 py::call_guard<py::scoped_ostream_redirect,
953 py::scoped_estream_redirect>(),
954 "Solve.\n\n"
955 ":param problem: Problem to solve.\n"
956 ":param y: Initial guess for Lagrange multipliers :math:`y`\n"
957 ":param x: Initial guess for decision variables :math:`x`\n\n"
958 ":return: * Lagrange multipliers :math:`y` at the solution\n"
959 " * Solution :math:`x`\n"
960 " * Statistics\n\n")
962 .def_property_readonly("params", &alpaqa::PolymorphicALMSolver::get_params);
963
964 constexpr auto panoc = [](std::function<alpaqa::real_t(alpaqa::crvec)> ψ,
965 std::function<alpaqa::vec(alpaqa::crvec)> grad_ψ,
966 const alpaqa::Box &C, std::optional<alpaqa::vec> x0,
968 const alpaqa::LBFGSParams &lbfgs_params) {
969 auto n = C.lowerbound.size();
970 if (C.upperbound.size() != n)
971 throw std::invalid_argument("Length of C.upperbound does not "
972 "match length of C.lowerbound");
973 if (!x0)
974 x0 = alpaqa::vec::Zero(n);
975 else if (x0->size() != n)
976 throw std::invalid_argument(
977 "Length of x does not match length of bounds C");
978 auto grad_ψ_ = [&](alpaqa::crvec x, alpaqa::rvec gr) {
979 auto &&t = grad_ψ(x);
980 if (t.size() != x.size())
981 throw std::runtime_error("Invalid grad_ψ dimension");
982 gr = std::move(t);
983 };
984 auto stats =
985 alpaqa::panoc<alpaqa::LBFGS>(ψ, grad_ψ_, C, *x0, ε, params, {lbfgs_params});
986 return std::make_tuple(std::move(*x0), stats_to_dict(stats));
987 };
988
989 m.def("panoc", panoc, "ψ"_a, "grad_ψ"_a, "C"_a, "x0"_a = std::nullopt,
990 "ε"_a = 1e-8, "params"_a = alpaqa::PANOCParams{},
991 "lbfgs_params"_a = alpaqa::LBFGSParams{});
992
993#if !ALPAQA_HAVE_CASADI
994 auto load_CasADi_problem = [](const char *, unsigned, unsigned,
995 bool) -> alpaqa::Problem {
996 throw std::runtime_error(
997 "This version of alpaqa was compiled without CasADi support");
998 };
999 auto load_CasADi_problem_with_param = [](const char *, unsigned, unsigned,
1000 unsigned,
1001 bool) -> alpaqa::ProblemWithParam {
1002 throw std::runtime_error(
1003 "This version of alpaqa was compiled without CasADi support");
1004 };
1005#else
1008#endif
1009
1010 m.def("load_casadi_problem", load_CasADi_problem, "so_name"_a, "n"_a = 0,
1011 "m"_a = 0, "second_order"_a = false,
1012 "Load a compiled CasADi problem without parameters.\n\n"
1013 "C++ documentation: :cpp:func:`alpaqa::load_CasADi_problem`");
1014 m.def("load_casadi_problem_with_param", load_CasADi_problem_with_param,
1015 "so_name"_a, "n"_a = 0, "m"_a = 0, "p"_a = 0,
1016 "second_order"_a = false,
1017 "Load a compiled CasADi problem with parameters.\n\n"
1018 "C++ documentation: :cpp:func:`alpaqa::load_CasADi_problem_with_param`");
1019}
auto prob_getter_f()
auto prob_setter_grad_f()
auto prob_getter_grad_gi()
auto prob_setter_grad_gi()
auto prob_setter_g()
auto prob_getter_hess_L_prod()
auto prob_getter_g()
auto prob_setter_hess_L_prod()
auto prob_setter_grad_g_prod()
auto prob_getter_hess_L()
auto prob_setter_hess_L()
auto prob_getter_grad_g_prod()
auto prob_getter_grad_f()
auto prob_setter_f()
#define MACRO_STRINGIFY(x)
Definition: alpaqa.cpp:123
PYBIND11_MODULE(ALPAQA_MODULE_NAME, m)
Definition: alpaqa.cpp:125
auto PolymorphicALMConstructorDefaultParams()
Definition: alpaqa.cpp:102
auto PolymorphicALMConversion()
Definition: alpaqa.cpp:110
auto PolymorphicPANOCConversion()
Definition: alpaqa.cpp:64
auto PolymorphicPANOCConstructor()
Definition: alpaqa.cpp:48
auto PolymorphicALMConstructor()
Definition: alpaqa.cpp:87
auto PolymorphicPANOCDefaultConversion()
Definition: alpaqa.cpp:77
Augmented Lagrangian Method solver.
Definition: decl/alm.hpp:82
std::string get_name() const
Definition: decl/alm.hpp:142
const Params & get_params() const
Definition: decl/alm.hpp:150
PANOC solver for ALM.
virtual std::string get_name() const =0
virtual py::object get_params() const =0
py::object get_params() const override
void set_progress_callback(std::function< void(const typename InnerSolver::ProgressInfo &)> cb)
std::string get_name() const override
virtual void changed_γ(real_t γₖ, real_t old_γₖ)=0
virtual void initialize(crvec x₀, crvec x̂₀, crvec p₀, crvec grad₀)=0
vec apply_ret(crvec xₖ, crvec x̂ₖ, crvec pₖ, real_t γ)
virtual std::string get_name() const =0
virtual bool update(crvec xₖ, crvec xₖ₊₁, crvec pₖ, crvec pₖ₊₁, crvec grad_new, const Box &C, real_t γ_new)=0
bool update(crvec xₖ, crvec xₖ₊₁, crvec pₖ, crvec pₖ₊₁, crvec grad_new, const Box &C, real_t γ_new) override
void initialize(crvec x₀, crvec x̂₀, crvec p₀, crvec grad₀) override
void changed_γ(real_t γₖ, real_t old_γₖ) override
Second order PANOC solver for ALM.
ProblemWithParam load_CasADi_problem_with_param(const std::string &filename, unsigned n=0, unsigned m=0, unsigned p=0, bool second_order=false)
Load a problem generated by CasADi (with parameters).
alpaqa::Problem load_CasADi_problem(const std::string &filename, unsigned n=0, unsigned m=0, bool second_order=false)
Load a problem generated by CasADi (without parameters).
This file defines mappings from Python dicts (kwargs) to simple parameter structs.
T var_kwargs_to_struct(const std::variant< T, py::dict > &p)
int m
Definition: test.py:41
int n
Definition: test.py:40
int ε
Definition: test.py:73
real_t Δ_lower
Factor to reduce ALMParams::Δ when inner convergence fails.
Definition: decl/alm.hpp:21
real_t Σ_min
Minimum penalty factor (used during initialization).
Definition: decl/alm.hpp:50
LipschitzEstimateParams Lipschitz
Parameters related to the Lipschitz constant estimate and step size.
PolymorphicInnerSolver< StructuredPANOCLBFGSSolver > PolymorphicStructuredPANOCLBFGSSolver
real_t ε₀_increase
Factor to increase the initial primal tolerance if convergence fails in the first iteration.
Definition: decl/alm.hpp:37
real_t θ
Error tolerance for penalty increase.
Definition: decl/alm.hpp:44
real_t ε₀
Initial primal tolerance.
Definition: decl/alm.hpp:34
@ ProjGradUnitNorm
∞-norm of the projected gradient with unit step size:
@ ProjGradNorm
∞-norm of the projected gradient with step size γ:
@ Ipopt
The stopping criterion used by Ipopt, see https://link.springer.com/article/10.1007/s10107-004-0559-y...
@ FPRNorm2
2-norm of fixed point residual:
@ ProjGradNorm2
2-norm of the projected gradient with step size γ:
@ ApproxKKT
Find an ε-approximate KKT point in the ∞-norm:
@ FPRNorm
∞-norm of fixed point residual:
@ ApproxKKT2
Find an ε-approximate KKT point in the 2-norm:
@ ProjGradUnitNorm2
2-norm of the projected gradient with unit step size:
unsigned max_total_num_retries
Combined limit for ALMParams::max_num_initial_retries and ALMParams::max_num_retries.
Definition: decl/alm.hpp:65
real_t Lγ_factor
Factor that relates step size γ and Lipschitz constant.
Definition: lipschitz.hpp:15
Eigen::Ref< const vec > crvec
Default type for immutable references to vectors.
Definition: vec.hpp:18
PolymorphicInnerSolver< PANOCSolver< PolymorphicPANOCDirectionBase > > PolymorphicPANOCSolver
real_t Δ
Factor used in updating the penalty parameters.
Definition: decl/alm.hpp:19
unsigned limitedqr_mem
Length of the history to keep in the limited-memory QR algorithm.
real_t Σ₀_lower
Factor to reduce the initial penalty factor by if convergence fails in in the first iteration.
Definition: decl/alm.hpp:32
real_t δ
Minimum step size for initial finite difference Lipschitz estimate.
Definition: lipschitz.hpp:13
PANOCStats panoc(ObjFunT &ψ, ObjGradFunT &grad_ψ, const Box &C, rvec x, real_t ε, const PANOCParams &params, PANOCDirection< DirectionProviderT > direction, vec_allocator &alloc)
constexpr real_t inf
Definition: vec.hpp:26
unsigned max_no_progress
Maximum number of iterations without any progress before giving up.
real_t L_max
Maximum Lipschitz constant estimate.
real_t σ₀
Initial penalty parameter factor.
Definition: decl/alm.hpp:29
real_t ρ
Update factor for primal tolerance.
Definition: decl/alm.hpp:39
vec upperbound
Definition: box.hpp:8
unsigned int max_iter
Maximum number of outer ALM iterations.
Definition: decl/alm.hpp:52
PolymorphicPANOCDirection< LBFGS > PolymorphicLBFGSDirection
unsigned memory
Length of the history to keep.
Definition: decl/lbfgs.hpp:14
py::dict stats_to_dict(const PANOCStats &s)
@ Interrupted
Solver was interrupted by the user.
@ Unknown
Initial value.
@ MaxTime
Maximum allowed execution time exceeded.
@ NoProgress
No progress was made in the last iteration.
@ MaxIter
Maximum number of iterations exceeded.
@ Converged
Converged and reached given tolerance.
@ NotFinite
Intermediate results were infinite or not-a-number.
std::chrono::microseconds max_time
Maximum duration.
unsigned max_num_retries
How many times can the penalty update factor ALMParams::Δ and the primal tolerance factor ALMParams::...
Definition: decl/alm.hpp:62
real_t Σ₀
Initial penalty parameter.
Definition: decl/alm.hpp:26
realvec vec
Default type for vectors.
Definition: vec.hpp:14
vec lowerbound
Definition: box.hpp:9
real_t ε
Relative step size for initial finite difference Lipschitz estimate.
Definition: lipschitz.hpp:11
real_t L₀
Initial estimate of the Lipschitz constant of ∇ψ(x)
Definition: lipschitz.hpp:9
unsigned max_num_initial_retries
How many times can the initial penalty ALMParams::Σ₀ or ALMParams::σ₀ and the initial primal toleranc...
Definition: decl/alm.hpp:59
struct alpaqa::LBFGSParams::@0 cbfgs
Parameters in the cautious BFGS update condition.
real_t quadratic_upperbound_tolerance_factor
double real_t
Default floating point type.
Definition: vec.hpp:8
unsigned print_interval
When to print progress.
PolymorphicInnerSolver< GAAPGASolver > PolymorphicGAAPGASolver
real_t τ_min
Minimum weight factor between Newton step and projected gradient step.
real_t L_min
Minimum Lipschitz constant estimate.
real_t ρ_increase
Factor to increase the primal tolerance update factor by if convergence fails.
Definition: decl/alm.hpp:42
LBFGSStepSize lbfgs_stepsize
bool preconditioning
Apply preconditioning to the problem, based on the gradients in the starting point.
Definition: decl/alm.hpp:73
auto InnerSolverCallWrapper()
PolymorphicInnerSolver< PGASolver > PolymorphicPGASolver
unsigned max_iter
Maximum number of inner PANOC iterations.
PANOCStopCrit stop_crit
What stop criterion to use.
Definition: pga.hpp:30
bool single_penalty_factor
Use one penalty factor for all m constraints.
Definition: decl/alm.hpp:75
real_t Σ_max
Maximum penalty factor.
Definition: decl/alm.hpp:48
real_t M
Lagrange multiplier bound.
Definition: decl/alm.hpp:46
Eigen::Ref< vec > rvec
Default type for mutable references to vectors.
Definition: vec.hpp:16
real_t nonmonotone_linesearch
Factor used in update for exponentially weighted nonmonotone line search.
Parameters for the Augmented Lagrangian solver.
Definition: decl/alm.hpp:13
Parameters for the LBFGS and SpecializedLBFGS classes.
Definition: decl/lbfgs.hpp:12
Tuning parameters for the PANOC algorithm.
Tuning parameters for the second order PANOC algorithm.
struct alpaqa::EvalCounter::EvalTimer time
Problem description for minimization problems.
Box C
Constraints of the decision variables, .
unsigned int m
Number of constraints, dimension of g(x) and z.
unsigned int n
Number of decision variables, dimension of x.
Box D
Other constraints, .