alpaqa 0.0.1
Nonconvex constrained optimization
lbfgspp.hpp
Go to the documentation of this file.
1#pragma once
2
7
8#include <atomic>
9#include <chrono>
10#include <stdexcept>
11#include <string>
12
13#include <LBFGS.h>
14#include <LBFGSB.h>
15
16namespace alpaqa {
17
18using std::chrono::duration_cast;
19using std::chrono::microseconds;
20
21/// Unconstrained LBFGS solver for ALM.
22/// @ingroup grp_InnerSolvers
23template <template <class> class LineSearchT = LBFGSpp::LineSearchBacktracking>
25 public:
26 using Params = LBFGSpp::LBFGSParam<real_t>;
27 using LineSearch = LineSearchT<real_t>;
28
29 struct Stats {
30 unsigned iterations = 0;
32 std::chrono::microseconds elapsed_time;
34
35 // TODO: find more generic way of handling this
36 unsigned linesearch_failures = 0;
37 unsigned lbfgs_failures = 0; // TODO: more generic name
38 unsigned lbfgs_rejected = 0;
39 };
40
42
44 crvec Σ, // in
45 real_t ε, // in
46 bool always_overwrite_results, // in
47 rvec x, // inout
48 rvec y, // inout
49 rvec err_z // out
50 ) {
51 Stats s;
52 auto start_time = std::chrono::steady_clock::now();
53 work_n.resize(problem.n);
54 work_m.resize(problem.m);
55 auto calc_ψ_grad_ψ = [&](crvec x, rvec grad) {
56 return detail::calc_ψ_grad_ψ(problem, x, y, Σ, // in
57 grad, // out
58 work_n, work_m); // work
59 };
60 real_t ψ٭;
61 params.epsilon = ε;
62 vec x٭ = x;
63 try {
64 LBFGSpp::LBFGSSolver<double> solver(params);
65 s.iterations = solver.minimize(calc_ψ_grad_ψ, x٭, ψ٭);
66 s.status = SolverStatus::Converged; // TODO: <?>
67 } catch (std::runtime_error &) {
69 } catch (std::logic_error &) {
70 // TODO: when does the following error occur?
71 // “the moving direction increases the objective function value”
73 }
74 auto time_elapsed = std::chrono::steady_clock::now() - start_time;
75 s.elapsed_time = duration_cast<microseconds>(time_elapsed);
76 s.ε = ε; // TODO: <?>
79 bool conv = s.status == SolverStatus::Converged;
80 bool interrupted = s.status == SolverStatus::Interrupted;
81 if (conv || interrupted || always_overwrite_results) {
82 x٭.swap(x);
83 work_m.swap(y);
84 // TODO: could be optimized
87 }
88 return s;
89 }
90
91 std::string get_name() const { return "LBFGSSolver<?>"; }
92
93 const Params &get_params() const { return params; }
94
95 void stop() { stop_signal.stop(); }
96
97 private:
101};
102
106 std::chrono::microseconds elapsed_time;
107 unsigned iterations = 0;
108};
109
110/// Box-constrained LBFGS solver for ALM.
111/// @ingroup grp_InnerSolvers
112template <template <class> class LineSearchT = LBFGSpp::LineSearchBacktracking>
114 public:
115 using Params = LBFGSpp::LBFGSBParam<real_t>;
116 using LineSearch = LineSearchT<real_t>;
118
120
122 crvec Σ, // in
123 real_t ε, // in
124 bool always_overwrite_results, // in
125 rvec x, // inout
126 rvec y, // inout
127 rvec err_z // out
128 ) {
129 Stats s;
130 auto start_time = std::chrono::steady_clock::now();
131 work_n.resize(problem.n);
132 work_m.resize(problem.m);
133 auto calc_ψ_grad_ψ = [&](crvec x, rvec grad) {
134 return detail::calc_ψ_grad_ψ(problem, x, y, Σ, // in
135 grad, // out
136 work_n, work_m); // work
137 };
138 real_t ψ٭;
139 params.epsilon = ε;
140 vec x٭ = x;
141 try {
142 LBFGSpp::LBFGSBSolver<double> solver(params);
143 s.iterations =
144 solver.minimize(calc_ψ_grad_ψ, x٭, ψ٭, problem.C.lowerbound,
145 problem.C.upperbound);
146 s.status = SolverStatus::Converged; // TODO: <?>
147 } catch (std::runtime_error &) {
149 } catch (std::logic_error &) {
150 // TODO: when does the following error occur?
151 // “the moving direction increases the objective function value”
153 }
154 auto time_elapsed = std::chrono::steady_clock::now() - start_time;
155 s.elapsed_time = duration_cast<microseconds>(time_elapsed);
156 s.ε = ε; // TODO: <?>
159 bool conv = s.status == SolverStatus::Converged;
160 bool interrupted = s.status == SolverStatus::Interrupted;
161 if (conv || interrupted || always_overwrite_results) {
162 x٭.swap(x);
163 work_m.swap(y);
164 // TODO: could be optimized
167 }
168 return s;
169 }
170
171 std::string get_name() const { return "LBFGSBSolver<?>"; }
172
173 const Params &get_params() const { return params; }
174
175 void stop() { stop_signal.stop(); }
176
177 private:
181};
182
183template <class InnerSolverStats>
185
186template <>
188 std::chrono::microseconds elapsed_time;
189 unsigned iterations = 0;
190};
191
194 acc.iterations += s.iterations;
195 acc.elapsed_time += s.elapsed_time;
196 return acc;
197}
198
199} // namespace alpaqa
Box-constrained LBFGS solver for ALM.
Definition: lbfgspp.hpp:113
std::string get_name() const
Definition: lbfgspp.hpp:171
LBFGSBSolver(Params params)
Definition: lbfgspp.hpp:119
AtomicStopSignal stop_signal
Definition: lbfgspp.hpp:179
Stats operator()(const Problem &problem, crvec Σ, real_t ε, bool always_overwrite_results, rvec x, rvec y, rvec err_z)
Definition: lbfgspp.hpp:121
const Params & get_params() const
Definition: lbfgspp.hpp:173
LBFGSpp::LBFGSBParam< real_t > Params
Definition: lbfgspp.hpp:115
LineSearchT< real_t > LineSearch
Definition: lbfgspp.hpp:116
Unconstrained LBFGS solver for ALM.
Definition: lbfgspp.hpp:24
std::string get_name() const
Definition: lbfgspp.hpp:91
AtomicStopSignal stop_signal
Definition: lbfgspp.hpp:99
Stats operator()(const Problem &problem, crvec Σ, real_t ε, bool always_overwrite_results, rvec x, rvec y, rvec err_z)
Definition: lbfgspp.hpp:43
LBFGSSolver(Params params)
Definition: lbfgspp.hpp:41
const Params & get_params() const
Definition: lbfgspp.hpp:93
LBFGSpp::LBFGSParam< real_t > Params
Definition: lbfgspp.hpp:26
std::chrono::microseconds elapsed_time
Definition: lbfgspp.hpp:32
LineSearchT< real_t > LineSearch
Definition: lbfgspp.hpp:27
real_t calc_ψ_ŷ(const Problem &p, crvec x, crvec y, crvec Σ, rvec ŷ)
Calculate both ψ(x) and the vector ŷ that can later be used to compute ∇ψ.
real_t calc_ψ_grad_ψ(const Problem &p, crvec x, crvec y, crvec Σ, rvec grad_ψ, rvec work_n, rvec work_m)
Calculate both ψ(x) and its gradient ∇ψ(x).
void calc_err_z(const Problem &p, crvec x̂, crvec y, crvec Σ, rvec err_z)
Calculate the error between ẑ and g(x).
int Σ
Definition: test.py:72
int ε
Definition: test.py:73
InnerStatsAccumulator< PolymorphicInnerSolverWrapper::Stats > & operator+=(InnerStatsAccumulator< PolymorphicInnerSolverWrapper::Stats > &acc, const PolymorphicInnerSolverWrapper::Stats &s)
Eigen::Ref< const vec > crvec
Default type for immutable references to vectors.
Definition: vec.hpp:18
constexpr real_t inf
Definition: vec.hpp:26
SolverStatus
Exit status of a numerical solver such as ALM or PANOC.
Definition: solverstatus.hpp:7
@ Interrupted
Solver was interrupted by the user.
@ Unknown
Initial value.
@ MaxIter
Maximum number of iterations exceeded.
@ Converged
Converged and reached given tolerance.
@ NotFinite
Intermediate results were infinite or not-a-number.
realvec vec
Default type for vectors.
Definition: vec.hpp:14
std::chrono::microseconds elapsed_time
Definition: lbfgspp.hpp:106
double real_t
Default floating point type.
Definition: vec.hpp:8
unsigned iterations
Definition: lbfgspp.hpp:107
SolverStatus status
Definition: lbfgspp.hpp:104
Eigen::Ref< vec > rvec
Default type for mutable references to vectors.
Definition: vec.hpp:16
problem
Definition: main.py:16
Problem description for minimization problems.