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>
45namespace py = pybind11;
47template <
class DirectionProv
iderT>
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),
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);
76template <
class DirectionProv
iderT>
78 return [](
const std::variant<alpaqa::PANOCParams, py::dict> &pp,
79 const std::variant<alpaqa::LBFGSParams, py::dict> &args) {
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),
101template <
class InnerSolverT>
103 return [](
const InnerSolverT &inner) {
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>);
116 std::is_constructible_v<InnerSolverT, InnerSolverArgumentsT...>);
117 InnerSolverT inner{args...};
118 return PolymorphicALMConstructor<InnerSolverT>()(pp, inner);
122#define STRINGIFY(x) #x
123#define MACRO_STRINGIFY(x) STRINGIFY(x)
126 using py::operator
""_a;
129 options.enable_function_signatures();
130 options.enable_user_defined_docstrings();
132 m.doc() =
"PANOC+ALM solvers";
137 m.attr(
"__version__") =
"dev";
140 py::class_<alpaqa::Box>(
m,
"Box",
"C++ documentation: :cpp:class:`alpaqa::Box`")
141 .def(py::init([](
unsigned n) {
146 "Create an :math:`n`-dimensional box at with bounds at "
147 ":math:`\\pm\\infty` (no constraints).")
149 if (ub.size() != lb.size())
150 throw std::invalid_argument(
151 "Upper bound and lower bound dimensions do not "
155 "ub"_a,
"lb"_a,
"Create a box with the given bounds.")
159 py::class_<alpaqa::Problem>(
m,
"Problem",
160 "C++ documentation: :cpp:class:`alpaqa::Problem`")
162 .def(py::init<unsigned, unsigned>(),
"n"_a,
"m"_a,
163 ":param n: Number of unknowns\n"
164 ":param m: Number of constraints")
166 "Number of unknowns, dimension of :math:`x`")
169 "Number of general constraints, dimension of :math:`g(x)`")
173 "Objective funcion, :math:`f(x)`")
176 "Gradient of the objective function, :math:`\\nabla f(x)`")
178 "Constraint function, :math:`g(x)`")
181 "Gradient of constraint function times vector, "
182 ":math:`\\nabla g(x)\\, v`")
184 "Gradient vector of the :math:`i`-th component of the "
185 "constriant function, :math:`\\nabla g_i(x)`")
188 "Hessian of the Lagrangian function, :math:`\\nabla^2_{xx} L(x,y)`")
191 "Hessian of the Lagrangian function times vector, "
192 ":math:`\\nabla^2_{xx} L(x,y)\\, v`");
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.")
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()) +
".");
219 "Parameter vector :math:`p` of the problem");
221 py::class_<alpaqa::EvalCounter::EvalTimer>(
223 "C++ documentation: "
224 ":cpp:class:`alpaqa::EvalCounter::EvalTimer`\n\n")
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);
232 throw std::runtime_error(
"Invalid state!");
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]),
252 py::class_<alpaqa::EvalCounter>(
m,
"EvalCounter",
253 "C++ documentation: "
254 ":cpp:class:`alpaqa::EvalCounter`\n\n")
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,
263 throw std::runtime_error(
"Invalid state!");
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]),
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)
302 .def_property_readonly(
304 return *
p.evaluations;
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)
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()) +
".");
338 "Parameter vector :math:`p` of the problem")
339 .def_property_readonly(
342 return *
p.evaluations;
346 std::shared_ptr<alpaqa::PolymorphicPANOCDirectionBase>,
349 "Class that provides fast directions for the PANOC algorithm (e.g. "
361 py::class_<paLBFGSParamCBFGS>(
362 m,
"LBFGSParamsCBFGS",
363 "C++ documentation: :cpp:member:`alpaqa::LBFGSParams::cbfgs`")
365 .def(py::init(&kwargs_to_struct<paLBFGSParamCBFGS>))
366 .def(
"to_dict", &struct_to_dict<paLBFGSParamCBFGS>)
368 .def_readwrite(
"ϵ", &paLBFGSParamCBFGS::ϵ);
370 py::class_<alpaqa::LBFGSParams>(
371 m,
"LBFGSParams",
"C++ documentation: :cpp:class:`alpaqa::LBFGSParams`")
373 .def(py::init(&kwargs_to_struct<alpaqa::LBFGSParams>))
374 .def(
"to_dict", &struct_to_dict<alpaqa::LBFGSParams>)
377 .def_readwrite(
"rescale_when_γ_changes",
381 std::shared_ptr<alpaqa::PolymorphicLBFGSDirection>,
384 "C++ documentation: :cpp:class:`alpaqa::LBFGSDirection`")
385 .def(py::init<alpaqa::LBFGSParams>(),
"params"_a)
393 .def_property_readonly(
"params",
396 py::enum_<alpaqa::LBFGSStepSize>(
397 m,
"LBFGSStepsize",
"C++ documentation: :cpp:enum:`alpaqa::LBFGSStepSize`")
398 .value(
"BasedOnGradientStepSize",
403 py::class_<alpaqa::LipschitzEstimateParams>(
404 m,
"LipschitzEstimateParams",
405 "C++ documentation: :cpp:class:`alpaqa::LipschitzEstimateParams`")
407 .def(py::init(&kwargs_to_struct<alpaqa::LipschitzEstimateParams>))
408 .def(
"to_dict", &struct_to_dict<alpaqa::LipschitzEstimateParams>)
414 py::class_<alpaqa::PANOCParams>(
415 m,
"PANOCParams",
"C++ documentation: :cpp:class:`alpaqa::PANOCParams`")
417 .def(py::init(&kwargs_to_struct<alpaqa::PANOCParams>))
418 .def(
"to_dict", &struct_to_dict<alpaqa::PANOCParams>)
427 .def_readwrite(
"quadratic_upperbound_tolerance_factor",
429 .def_readwrite(
"update_lipschitz_in_linesearch",
431 .def_readwrite(
"alternative_linesearch_cond",
435 py::enum_<alpaqa::SolverStatus>(
436 m,
"SolverStatus", py::arithmetic(),
437 "C++ documentation: :cpp:enum:`alpaqa::SolverStatus`")
440 "Converged and reached given tolerance")
442 "Maximum allowed execution time exceeded")
444 "Maximum number of iterations exceeded")
446 "Intermediate results were infinite or not-a-number")
448 "No progress was made in the last iteration")
450 "Solver was interrupted by the user")
453 py::class_<alpaqa::PolymorphicInnerSolverBase::Stats>(
m,
"InnerSolverStats")
457 std::shared_ptr<alpaqa::PolymorphicInnerSolverBase>,
460 .def(
"__call__", &alpaqa::PolymorphicInnerSolverBase::operator())
465 py::enum_<alpaqa::PANOCStopCrit>(
466 m,
"PANOCStopCrit",
"C++ documentation: :cpp:enum:`alpaqa::PANOCStopCrit`")
478 py::class_<alpaqa::PGAParams>(
m,
"PGAParams",
479 "C++ documentation: :cpp:class:`alpaqa::PGAParams`")
481 .def(py::init(&kwargs_to_struct<alpaqa::PGAParams>))
482 .def(
"to_dict", &struct_to_dict<alpaqa::PGAParams>)
490 .def_readwrite(
"quadratic_upperbound_tolerance_factor",
493 py::class_<alpaqa::PGAProgressInfo>(
494 m,
"PGAProgressInfo",
495 "C++ documentation: :cpp:class:`alpaqa::PGAProgressInfo`")
511 return std::sqrt(
p.norm_sq_p) /
p.γ;
514 py::class_<alpaqa::GAAPGAParams>(
515 m,
"GAAPGAParams",
"C++ documentation: :cpp:class:`alpaqa::GAAPGAParams`")
517 .def(py::init(&kwargs_to_struct<alpaqa::GAAPGAParams>))
518 .def(
"to_dict", &struct_to_dict<alpaqa::GAAPGAParams>)
527 .def_readwrite(
"quadratic_upperbound_tolerance_factor",
530 .def_readwrite(
"full_flush_on_γ_change",
533 py::class_<alpaqa::GAAPGAProgressInfo>(
534 m,
"GAAPGAProgressInfo",
535 "C++ documentation: :cpp:class:`alpaqa::GAAPGAProgressInfo`")
551 return std::sqrt(
p.norm_sq_p) /
p.γ;
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`")
561 "Decision variable :math:`x`")
563 "Projected gradient step :math:`p`")
565 ":math:`\\left\\|p\\right\\|^2`")
568 "Decision variable after projected gradient step :math:`\\hat x`")
570 "Forward-backward envelope :math:`\\varphi_\\gamma(x)`")
572 "Objective value :math:`\\psi(x)`")
574 "Gradient of objective :math:`\\nabla\\psi(x)`")
578 "Estimate of Lipschitz constant of objective :math:`L`")
580 "Step size :math:`\\gamma`")
582 "Line search parameter :math:`\\tau`")
584 "Tolerance reached :math:`\\varepsilon_k`")
586 "Penalty factor :math:`\\Sigma`")
588 "Lagrange multipliers :math:`y`")
589 .def_property_readonly(
592 return std::sqrt(
p.norm_sq_p) /
p.γ;
594 "Fixed-point residual :math:`\\left\\|p\\right\\| / \\gamma`");
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.γ;
624 std::shared_ptr<alpaqa::PolymorphicPANOCSolver>,
626 m,
"PANOCSolver",
"C++ documentation: :cpp:class:`alpaqa::PANOCSolver`")
628 return std::make_shared<alpaqa::PolymorphicPANOCSolver>(
631 std::static_pointer_cast<alpaqa::PolymorphicPANOCDirectionBase>(
632 std::make_shared<alpaqa::PolymorphicLBFGSDirection>(
637 "panoc_params"_a,
"lbfgs_direction"_a)
640 "panoc_params"_a,
"lbfgs_params"_a)
643 "panoc_params"_a,
"direction"_a)
645 "set_progress_callback",
647 "Attach a callback that is called on each iteration of the solver.")
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,
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"
665 .def_property_readonly(
"params",
667 .def_property_readonly(
673 std::shared_ptr<alpaqa::PolymorphicPGASolver>,
675 m,
"PGASolver",
"C++ documentation: :cpp:class:`alpaqa::PGASolver`")
676 .def(py::init<alpaqa::PGAParams>())
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,
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"
700 std::shared_ptr<alpaqa::PolymorphicGAAPGASolver>,
702 m,
"GAAPGASolver",
"C++ documentation: :cpp:class:`alpaqa::GAAPGASolver`")
703 .def(py::init<alpaqa::GAAPGAParams>())
705 "set_progress_callback",
707 "Attach a callback that is called on each iteration of the solver.")
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,
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"
725 .def_property_readonly(
"params",
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>)
740 .def_readwrite(
"nonmonotone_linesearch",
743 .def_readwrite(
"max_no_progress",
745 .def_readwrite(
"print_interval",
747 .def_readwrite(
"quadratic_upperbound_tolerance_factor",
749 quadratic_upperbound_tolerance_factor)
751 "update_lipschitz_in_linesearch",
754 "alternative_linesearch_cond",
756 .def_readwrite(
"hessian_vec",
759 "hessian_vec_finite_differences",
761 .def_readwrite(
"full_augmented_hessian",
764 "hessian_step_size_heuristic",
766 .def_readwrite(
"lbfgs_stepsize",
770 std::shared_ptr<alpaqa::PolymorphicStructuredPANOCLBFGSSolver>,
772 m,
"StructuredPANOCLBFGSSolver",
773 "C++ documentation: :cpp:class:`alpaqa::StructuredPANOCLBFGSSolver`")
775 return std::make_shared<alpaqa::PolymorphicStructuredPANOCLBFGSSolver>(
783 const std::variant<alpaqa::LBFGSParams, py::dict> &lp) {
784 return std::make_shared<
788 "panoc_params"_a,
"lbfgs_params"_a)
790 "set_progress_callback",
793 "Attach a callback that is called on each iteration of the solver.")
797 py::call_guard<py::scoped_ostream_redirect,
798 py::scoped_estream_redirect>(),
799 "problem"_a,
"Σ"_a,
"ε"_a,
"x"_a,
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"
812 .def_property_readonly(
815 py::class_<alpaqa::ALMParams>(
m,
"ALMParams",
816 "C++ documentation: :cpp:class:`alpaqa::ALMParams`")
818 .def(py::init(&kwargs_to_struct<alpaqa::ALMParams>))
819 .def(
"to_dict", &struct_to_dict<alpaqa::ALMParams>)
837 .def_readwrite(
"max_num_initial_retries",
840 .def_readwrite(
"max_total_num_retries",
844 .def_readwrite(
"single_penalty_factor",
847 py::class_<alpaqa::PolymorphicALMSolver>(
849 "Main augmented Lagrangian solver.\n\n"
850 "C++ documentation: :cpp:class:`alpaqa::ALMSolver`")
855 std::static_pointer_cast<alpaqa::PolymorphicInnerSolverBase>(
862 "Build an ALM solver using Structured PANOC as inner 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 "
873 "alm_params"_a,
"structuredpanoc_solver"_a,
874 "Build an ALM solver using Structured PANOC as inner solver.")
877 "alm_params"_a,
"inner_solver"_a,
878 "Build an ALM solver using a custom inner solver.")
883 "Build an ALM solver using PANOC as inner solver.")
887 "Build an ALM solver using the projected gradient algorithm as "
891 "structuredpanoc_solver"_a,
892 "Build an ALM solver using Structured PANOC as inner solver.")
896 "Build an ALM solver using a custom inner solver.")
901 std::static_pointer_cast<alpaqa::PolymorphicInnerSolverBase>(
909 "Build an ALM solver using Structured PANOC as inner solver.")
911 .def_property_readonly(
"inner_solver",
913 return s.inner_solver.solver;
918 std::optional<alpaqa::vec>
x, std::optional<alpaqa::vec>
y)
919 -> std::tuple<alpaqa::vec, alpaqa::vec, py::dict> {
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");
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 "
934 if (
p.C.upperbound.size() !=
p.n)
935 throw std::invalid_argument(
936 "Length of problem.C.upperbound does not match problem "
938 if (
p.D.lowerbound.size() !=
p.m)
939 throw std::invalid_argument(
940 "Length of problem.D.lowerbound does not match problem "
942 if (
p.D.upperbound.size() !=
p.m)
943 throw std::invalid_argument(
944 "Length of problem.D.upperbound does not match problem "
948 return std::make_tuple(std::move(*
x), std::move(*
y),
951 "problem"_a,
"x"_a = std::nullopt,
"y"_a = std::nullopt,
952 py::call_guard<py::scoped_ostream_redirect,
953 py::scoped_estream_redirect>(),
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"
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");
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");
979 auto &&
t = grad_ψ(
x);
980 if (
t.size() !=
x.size())
981 throw std::runtime_error(
"Invalid grad_ψ dimension");
985 alpaqa::panoc<alpaqa::LBFGS>(ψ, grad_ψ_,
C, *
x0,
ε,
params, {lbfgs_params});
989 m.def(
"panoc",
panoc,
"ψ"_a,
"grad_ψ"_a,
"C"_a,
"x0"_a = std::nullopt,
993#if !ALPAQA_HAVE_CASADI
996 throw std::runtime_error(
997 "This version of alpaqa was compiled without CasADi support");
1002 throw std::runtime_error(
1003 "This version of alpaqa was compiled without CasADi support");
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`");
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`");
auto prob_setter_grad_f()
auto prob_getter_grad_gi()
auto prob_setter_grad_gi()
auto prob_getter_hess_L_prod()
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()
#define MACRO_STRINGIFY(x)
PYBIND11_MODULE(ALPAQA_MODULE_NAME, m)
auto PolymorphicALMConstructorDefaultParams()
auto PolymorphicALMConversion()
auto PolymorphicPANOCConversion()
auto PolymorphicPANOCConstructor()
auto PolymorphicALMConstructor()
auto PolymorphicPANOCDefaultConversion()
Augmented Lagrangian Method solver.
std::string get_name() const
const Params & get_params() const
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
py::object get_params() const override
void initialize(crvec x₀, crvec x̂₀, crvec p₀, crvec grad₀) override
void changed_γ(real_t γₖ, real_t old_γₖ) override
std::string get_name() const 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)
real_t Δ_lower
Factor to reduce ALMParams::Δ when inner convergence fails.
real_t Σ_min
Minimum penalty factor (used during initialization).
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.
real_t θ
Error tolerance for penalty increase.
real_t ε₀
Initial primal tolerance.
@ 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.
real_t Lγ_factor
Factor that relates step size γ and Lipschitz constant.
bool alternative_linesearch_cond
Eigen::Ref< const vec > crvec
Default type for immutable references to vectors.
bool rescale_when_γ_changes
PolymorphicInnerSolver< PANOCSolver< PolymorphicPANOCDirectionBase > > PolymorphicPANOCSolver
real_t Δ
Factor used in updating the penalty parameters.
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.
real_t δ
Minimum step size for initial finite difference Lipschitz estimate.
PANOCStats panoc(ObjFunT &ψ, ObjGradFunT &grad_ψ, const Box &C, rvec x, real_t ε, const PANOCParams ¶ms, PANOCDirection< DirectionProviderT > direction, vec_allocator &alloc)
bool update_lipschitz_in_linesearch
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.
real_t ρ
Update factor for primal tolerance.
bool full_augmented_hessian
unsigned int max_iter
Maximum number of outer ALM iterations.
PolymorphicPANOCDirection< LBFGS > PolymorphicLBFGSDirection
unsigned memory
Length of the history to keep.
py::dict stats_to_dict(const PANOCStats &s)
@ Interrupted
Solver was interrupted by the user.
@ 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::...
bool hessian_vec_finite_differences
real_t Σ₀
Initial penalty parameter.
realvec vec
Default type for vectors.
bool full_flush_on_γ_change
real_t ε
Relative step size for initial finite difference Lipschitz estimate.
real_t L₀
Initial estimate of the Lipschitz constant of ∇ψ(x)
unsigned max_num_initial_retries
How many times can the initial penalty ALMParams::Σ₀ or ALMParams::σ₀ and the initial primal toleranc...
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.
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.
LBFGSStepSize lbfgs_stepsize
bool preconditioning
Apply preconditioning to the problem, based on the gradients in the starting point.
@ BasedOnGradientStepSize
auto InnerSolverCallWrapper()
PolymorphicInnerSolver< PGASolver > PolymorphicPGASolver
unsigned max_iter
Maximum number of inner PANOC iterations.
PANOCStopCrit stop_crit
What stop criterion to use.
bool single_penalty_factor
Use one penalty factor for all m constraints.
real_t Σ_max
Maximum penalty factor.
real_t M
Lagrange multiplier bound.
Eigen::Ref< vec > rvec
Default type for mutable references to vectors.
unsigned hessian_step_size_heuristic
real_t nonmonotone_linesearch
Factor used in update for exponentially weighted nonmonotone line search.
Parameters for the Augmented Lagrangian solver.
Parameters for the LBFGS and SpecializedLBFGS classes.
Tuning parameters for the PANOC algorithm.
Tuning parameters for the second order PANOC algorithm.
std::chrono::nanoseconds grad_gi
std::chrono::nanoseconds f
std::chrono::nanoseconds g
struct alpaqa::EvalCounter::EvalTimer time
std::chrono::nanoseconds hess_L
std::chrono::nanoseconds grad_f
std::chrono::nanoseconds grad_g_prod
std::chrono::nanoseconds hess_L_prod
static Stats from_dict(py::dict d)
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, .