PANOC-ALM  quadratic-penalty
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 
16 namespace pa {
17 
18 using std::chrono::duration_cast;
19 using std::chrono::microseconds;
20 
23 template <template <class> class LineSearchT = LBFGSpp::LineSearchBacktracking>
24 class LBFGSSolver {
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;
33  SolverStatus status = SolverStatus::Unknown;
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 &) {
68  s.status = SolverStatus::MaxIter;
69  } catch (std::logic_error &) {
70  // TODO: when does the following error occur?
71  // “the moving direction increases the objective function value”
72  s.status = SolverStatus::NotFinite; // <?>
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 
103 struct LBFGSBStats {
104  SolverStatus status = SolverStatus::Unknown;
106  std::chrono::microseconds elapsed_time;
107  unsigned iterations = 0;
108 };
109 
112 template <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 &) {
148  s.status = SolverStatus::MaxIter;
149  } catch (std::logic_error &) {
150  // TODO: when does the following error occur?
151  // “the moving direction increases the objective function value”
152  s.status = SolverStatus::NotFinite; // <?>
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
165  (void)detail::calc_ψ_ŷ(problem, x, work_m, Σ, y);
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 
183 template <class InnerSolverStats>
184 struct InnerStatsAccumulator;
185 
186 template <>
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 pa
pa::LBFGSBStats
Definition: lbfgspp.hpp:103
pa::LBFGSBSolver::stop
void stop()
Definition: lbfgspp.hpp:175
pa::AtomicStopSignal
Definition: atomic_stop_signal.hpp:7
pa::AtomicStopSignal::stop_requested
bool stop_requested() const
Definition: atomic_stop_signal.hpp:16
pa::LBFGSSolver::Stats::lbfgs_failures
unsigned lbfgs_failures
Definition: lbfgspp.hpp:37
pa::LBFGSBSolver::LineSearch
LineSearchT< real_t > LineSearch
Definition: lbfgspp.hpp:116
pa::LBFGSBSolver::stop_signal
AtomicStopSignal stop_signal
Definition: lbfgspp.hpp:179
pa::SolverStatus::Unknown
@ Unknown
Initial value.
pa::rvec
Eigen::Ref< vec > rvec
Default type for mutable references to vectors.
Definition: vec.hpp:16
pa::LBFGSSolver::Stats
Definition: lbfgspp.hpp:29
pa::LBFGSBStats::iterations
unsigned iterations
Definition: lbfgspp.hpp:107
pa::LBFGSSolver::work_n
vec work_n
Definition: lbfgspp.hpp:100
panocpy.test.y
y
Definition: test.py:76
atomic_stop_signal.hpp
pa::LBFGSSolver::LineSearch
LineSearchT< real_t > LineSearch
Definition: lbfgspp.hpp:27
pa::LBFGSSolver::work_m
vec work_m
Definition: lbfgspp.hpp:100
pa::LBFGSSolver::get_params
const Params & get_params() const
Definition: lbfgspp.hpp:93
panocpy.test.err_z
err_z
Definition: test.py:76
pa::SolverStatus
SolverStatus
Exit status of a numerical solver such as ALM or PANOC.
Definition: solverstatus.hpp:7
panocpy.test.ε
int ε
Definition: test.py:71
pa::LBFGSSolver
Unconstrained LBFGS solver for ALM.
Definition: lbfgspp.hpp:24
pa::LBFGSSolver::get_name
std::string get_name() const
Definition: lbfgspp.hpp:91
pa::vec
realvec vec
Default type for vectors.
Definition: vec.hpp:14
pa::LBFGSBSolver::work_m
vec work_m
Definition: lbfgspp.hpp:180
pa::LBFGSSolver::LBFGSSolver
LBFGSSolver(Params params)
Definition: lbfgspp.hpp:41
pa::operator+=
InnerStatsAccumulator< PANOCStats > & operator+=(InnerStatsAccumulator< PANOCStats > &acc, const PANOCStats &s)
Definition: inner/decl/panoc.hpp:217
pa::LBFGSBStats::status
SolverStatus status
Definition: lbfgspp.hpp:104
main.problem
problem
Definition: main.py:16
pa
Definition: alm.hpp:10
pa::detail::calc_ψ_grad_ψ
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).
Definition: panoc-helpers.hpp:113
panocpy.test.x
x
Definition: test.py:40
pa::LBFGSBSolver::get_name
std::string get_name() const
Definition: lbfgspp.hpp:171
pa::detail::calc_ψ_ŷ
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 ∇ψ.
Definition: panoc-helpers.hpp:16
pa::LBFGSBSolver::LBFGSBSolver
LBFGSBSolver(Params params)
Definition: lbfgspp.hpp:119
pa::LBFGSSolver::params
Params params
Definition: lbfgspp.hpp:98
pa::inf
constexpr real_t inf
Definition: vec.hpp:26
pa::LBFGSSolver::stop
void stop()
Definition: lbfgspp.hpp:95
panoc-helpers.hpp
pa::detail::calc_err_z
void calc_err_z(const Problem &p, crvec x̂, crvec y, crvec Σ, rvec err_z)
Calculate the error between ẑ and g(x).
Definition: panoc-helpers.hpp:212
pa::LBFGSBStats::ε
real_t ε
Definition: lbfgspp.hpp:105
pa::LBFGSSolver::Stats::ε
real_t ε
Definition: lbfgspp.hpp:31
pa::crvec
Eigen::Ref< const vec > crvec
Default type for immutable references to vectors.
Definition: vec.hpp:18
pa::LBFGSBSolver::Params
LBFGSpp::LBFGSBParam< real_t > Params
Definition: lbfgspp.hpp:115
pa::LBFGSSolver::Stats::elapsed_time
std::chrono::microseconds elapsed_time
Definition: lbfgspp.hpp:32
pa::LBFGSSolver::Stats::linesearch_failures
unsigned linesearch_failures
Definition: lbfgspp.hpp:36
pa::InnerStatsAccumulator< LBFGSBStats >
Definition: lbfgspp.hpp:187
panocpy.test.Σ
int Σ
Definition: test.py:70
panocpy.test.solver
solver
Definition: test.py:8
pa::LBFGSSolver::Params
LBFGSpp::LBFGSParam< real_t > Params
Definition: lbfgspp.hpp:26
pa::LBFGSSolver::stop_signal
AtomicStopSignal stop_signal
Definition: lbfgspp.hpp:99
pa::LBFGSBSolver::get_params
const Params & get_params() const
Definition: lbfgspp.hpp:173
pa::LBFGSSolver::Stats::status
SolverStatus status
Definition: lbfgspp.hpp:33
pa::LBFGSBSolver::operator()
Stats operator()(const Problem &problem, crvec Σ, real_t ε, bool always_overwrite_results, rvec x, rvec y, rvec err_z)
Definition: lbfgspp.hpp:121
problem.hpp
pa::LBFGSBSolver::work_n
vec work_n
Definition: lbfgspp.hpp:180
pa::InnerStatsAccumulator
Definition: panoc-fwd.hpp:10
pa::LBFGSSolver::operator()
Stats operator()(const Problem &problem, crvec Σ, real_t ε, bool always_overwrite_results, rvec x, rvec y, rvec err_z)
Definition: lbfgspp.hpp:43
pa::LBFGSBStats::elapsed_time
std::chrono::microseconds elapsed_time
Definition: lbfgspp.hpp:106
pa::real_t
double real_t
Default floating point type.
Definition: vec.hpp:8
pa::LBFGSBSolver::params
Params params
Definition: lbfgspp.hpp:178
solverstatus.hpp
pa::LBFGSSolver::Stats::iterations
unsigned iterations
Definition: lbfgspp.hpp:30
pa::AtomicStopSignal::stop
void stop()
Definition: atomic_stop_signal.hpp:15
pa::LBFGSSolver::Stats::lbfgs_rejected
unsigned lbfgs_rejected
Definition: lbfgspp.hpp:38
pa::Problem
Problem description for minimization problems.
Definition: include/panoc-alm/util/problem.hpp:24
pa::LBFGSBSolver
Box-constrained LBFGS solver for ALM.
Definition: lbfgspp.hpp:113