PANOC-ALM  quadratic-penalty
Nonconvex constrained optimization
alm-helpers.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <panoc-alm/decl/alm.hpp>
4 #include <stdexcept>
5 
6 namespace pa::detail {
7 
8 inline void project_y(rvec y, // inout
9  crvec z_lb, // in
10  crvec z_ub, // in
11  real_t M // in
12 ) {
13  // TODO: Handle NaN correctly
14  auto max_lb = [M](real_t y, real_t z_lb) {
15  real_t y_lb = z_lb == -inf ? 0 : -M;
16  return std::max(y, y_lb);
17  };
18  auto min_ub = [M](real_t y, real_t z_ub) {
19  real_t y_ub = z_ub == inf ? 0 : M;
20  return std::min(y, y_ub);
21  };
22  y = y.binaryExpr(z_lb, max_lb).binaryExpr(z_ub, min_ub);
23 }
24 
26  bool first_iter, rvec e, rvec old_e,
27  real_t norm_e, real_t old_norm_e,
28  crvec Σ_old, rvec Σ) {
29  if (norm_e <= params.δ) {
30  Σ = Σ_old;
31  return;
32  }
33  if (params.single_penalty_factor) {
34  if (first_iter || norm_e > params.θ * old_norm_e) {
35  real_t new_Σ = std::fmin(params.Σ_max, Δ * Σ_old(0));
36  Σ.setConstant(new_Σ);
37  } else {
38  Σ = Σ_old;
39  }
40  } else {
41  for (Eigen::Index i = 0; i < e.rows(); ++i) {
42  if (first_iter || std::abs(e(i)) > params.θ * std::abs(old_e(i))) {
43  Σ(i) = std::fmin(params.Σ_max,
44  std::fmax(Δ * std::abs(e(i)) / norm_e, 1) *
45  Σ_old(i));
46  } else {
47  Σ(i) = Σ_old(i);
48  }
49  }
50  }
51 }
52 
53 inline void initialize_penalty(const Problem &p, const ALMParams &params,
54  crvec x0, rvec Σ) {
55  real_t f0 = p.f(x0);
56  vec g0(p.m);
57  p.g(x0, g0);
58  // TODO: reuse evaluations of f and g in PANOC?
59  real_t σ = params.σ₀ * std::max(real_t(1), std::abs(f0)) /
60  std::max(real_t(1), 0.5 * g0.squaredNorm());
61  σ = std::max(σ, params.Σ_min);
62  σ = std::min(σ, params.Σ_max);
63  Σ.fill(σ);
64 }
65 
66 inline void initialize_penalty(const ProblemFull &p, const ALMParams &params,
67  crvec x0, rvec Σ1, rvec Σ2) {
68  real_t f0 = p.f(x0);
69 
70  // Penalty parameters for ALM
71  vec g1_eval(p.m1);
72  p.g1(x0, g1_eval);
73  // TODO: reuse evaluations of f and g in PANOC?
74 
75  real_t σ = params.σ₀ * std::max(real_t(1), std::abs(f0)) /
76  std::max(real_t(1), 0.5 * g1_eval.squaredNorm());
77  σ = std::max(σ, params.Σ_min);
78  σ = std::min(σ, params.Σ_max);
79  Σ1.fill(σ);
80 
81  // Penalty parameters for quadratic penalty
82  vec g2_eval(p.m2);
83  p.g2(x0, g2_eval);
84 
85  σ = params.σ₀ * std::max(real_t(1), std::abs(f0)) /
86  std::max(real_t(1), 0.5 * g2_eval.squaredNorm());
87  σ = std::max(σ, params.Σ_min);
88  σ = std::min(σ, params.Σ_max);
89  Σ2.fill(σ);
90 }
91 
92 inline void apply_preconditioning(const Problem &problem, Problem &prec_problem,
93  crvec x, real_t &prec_f, vec &prec_g) {
94  vec grad_f(problem.n);
95  vec v = vec::Zero(problem.m);
96  vec grad_g(problem.n);
97  problem.grad_f(x, grad_f);
98  prec_f = 1. / std::max(grad_f.lpNorm<Eigen::Infinity>(), real_t{1});
99  prec_g.resize(problem.m);
100 
101  for (Eigen::Index i = 0; i < problem.m; ++i) {
102  v(i) = 1;
103  problem.grad_g_prod(x, v, grad_g);
104  v(i) = 0;
105  prec_g(i) = 1. / std::max(grad_g.lpNorm<Eigen::Infinity>(), real_t{1});
106  }
107 
108  auto prec_f_fun = [&](crvec x) { return problem.f(x) * prec_f; };
109  auto prec_grad_f_fun = [&](crvec x, rvec grad_f) {
110  problem.grad_f(x, grad_f);
111  grad_f *= prec_f;
112  };
113  auto prec_g_fun = [&](crvec x, rvec g) {
114  problem.g(x, g);
115  g = prec_g.asDiagonal() * g;
116  };
117  auto prec_grad_g_fun = [&](crvec x, crvec v, rvec grad_g) {
118  vec prec_v = prec_g.asDiagonal() * v;
119  problem.grad_g_prod(x, prec_v, grad_g);
120  };
121  prec_problem = Problem{
122  problem.n,
123  problem.m,
124  problem.C,
125  Box{prec_g.asDiagonal() * problem.D.upperbound,
126  prec_g.asDiagonal() * problem.D.lowerbound},
127  std::move(prec_f_fun),
128  std::move(prec_grad_f_fun),
129  std::move(prec_g_fun),
130  std::move(prec_grad_g_fun),
131  [](crvec, unsigned, rvec) {
132  throw std::logic_error("Preconditioning for second-order solvers "
133  "has not yet been implemented");
134  },
135  [](crvec, crvec, crvec, rvec) {
136  throw std::logic_error("Preconditioning for second-order solvers "
137  "has not yet been implemented");
138  },
139  [](crvec, crvec, rmat) {
140  throw std::logic_error("Preconditioning for second-order solvers "
141  "has not yet been implemented");
142  },
143  };
144 }
145 
146 } // namespace pa::detail
pa::rvec
Eigen::Ref< vec > rvec
Default type for mutable references to vectors.
Definition: vec.hpp:16
panocpy.test.y
y
Definition: test.py:76
pa::detail::initialize_penalty
void initialize_penalty(const Problem &p, const ALMParams &params, crvec x0, rvec Σ)
Definition: alm-helpers.hpp:53
alm.hpp
pa::vec
realvec vec
Default type for vectors.
Definition: vec.hpp:14
pa::rmat
Eigen::Ref< mat > rmat
Default type for mutable references to matrices.
Definition: vec.hpp:22
pa::detail
Definition: alm-helpers.hpp:6
main.problem
problem
Definition: main.py:16
panocpy.test.v
v
Definition: test.py:42
panocpy.test.x
x
Definition: test.py:40
pa::ALMParams
Parameters for the Augmented Lagrangian solver.
Definition: decl/alm.hpp:13
pa::Box
Definition: box.hpp:7
pa::inf
constexpr real_t inf
Definition: vec.hpp:26
panocpy.test.grad_f
grad_f
Definition: test.py:50
panocpy.test.x0
x0
Definition: test.py:68
pa::crvec
Eigen::Ref< const vec > crvec
Default type for immutable references to vectors.
Definition: vec.hpp:18
panocpy.test.params
params
Definition: test.py:217
pa::detail::project_y
void project_y(rvec y, crvec z_lb, crvec z_ub, real_t M)
Definition: alm-helpers.hpp:8
panocpy.test.Σ
int Σ
Definition: test.py:70
panocpy.test.g
g
Definition: test.py:51
panocpy.test.p
p
Definition: test.py:57
pa::ProblemFull
Problem description for minimization problems.
Definition: include/panoc-alm/util/problem.hpp:213
pa::real_t
double real_t
Default floating point type.
Definition: vec.hpp:8
pa::Problem
Problem description for minimization problems.
Definition: include/panoc-alm/util/problem.hpp:24
pa::detail::update_penalty_weights
void update_penalty_weights(const ALMParams &params, real_t Δ, bool first_iter, rvec e, rvec old_e, real_t norm_e, real_t old_norm_e, crvec Σ_old, rvec Σ)
Definition: alm-helpers.hpp:25
pa::detail::apply_preconditioning
void apply_preconditioning(const Problem &problem, Problem &prec_problem, crvec x, real_t &prec_f, vec &prec_g)
Definition: alm-helpers.hpp:92