alpaqa 1.0.0a11
Nonconvex constrained optimization
Loading...
Searching...
No Matches
alm-driver.hpp
Go to the documentation of this file.
1#pragma once
2
6
7#include "options.hpp"
8#include "problem.hpp"
9#include "results.hpp"
10
11template <class InnerSolver>
12auto make_alm_solver(InnerSolver &&inner_solver, Options &opts) {
13 // Settings for the ALM solver
14 using ALMSolver = alpaqa::ALMSolver<InnerSolver>;
15 typename ALMSolver::Params alm_param;
16 alm_param.max_iter = 200;
17 alm_param.tolerance = 1e-8;
18 alm_param.dual_tolerance = 1e-8;
19 alm_param.print_interval = 1;
20 alm_param.print_precision = 1;
21 set_params(alm_param, "alm", opts);
22 return ALMSolver{alm_param, std::forward<InnerSolver>(inner_solver)};
23}
24
26
27template <class InnerSolver>
29 // Settings for the solver
30 typename InnerSolver::Params solver_param;
31 solver_param.max_iter = 50'000;
32 solver_param.print_interval = 0;
33 solver_param.stop_crit = alpaqa::PANOCStopCrit::ProjGradUnitNorm;
34 set_params(solver_param, "solver", opts);
35
36 if constexpr (requires { typename InnerSolver::Direction; }) {
37 // Settings for the direction provider
38 using Direction = typename InnerSolver::Direction;
39 typename Direction::DirectionParams dir_param;
40 typename Direction::AcceleratorParams accel_param;
41 set_params(dir_param, "dir", opts);
42 set_params(accel_param, "accel", opts);
43 return InnerSolver{
44 solver_param,
45 Direction{{
46 .accelerator = accel_param,
47 .direction = dir_param,
48 }},
49 };
50 } else {
51 return InnerSolver{solver_param};
52 }
53}
54
55template <class Solver>
57 std::ostream &os, unsigned N_exp) {
58 solver.os = &os;
59
60 // Initial guess
61 vec x = problem.initial_guess_x, y = problem.initial_guess_y;
62 // Final penalties
63 vec Σ = vec::Constant(problem.problem.get_m(), alpaqa::NaN<config_t>);
64
65 // Solve the problem
66 auto stats = solver(problem.problem, x, y, Σ);
67
68 // Store the evaluation counters
69 auto evals = *problem.evaluations;
70
71 // Solve the problems again to average runtimes
72 auto avg_duration = stats.elapsed_time;
73 os.setstate(std::ios_base::badbit); // suppress output
74 for (unsigned i = 0; i < N_exp; ++i) {
75 x = problem.initial_guess_x;
76 y = problem.initial_guess_y;
77 auto s = solver(problem.problem, x, y);
78 if (s.status == alpaqa::SolverStatus::Interrupted) {
79 os.clear();
80 os << "\rInterrupted after " << i << " runs" << std::endl;
81 N_exp = i;
82 break;
83 }
84 avg_duration += s.elapsed_time;
85 }
86 os.clear();
87 avg_duration /= (N_exp + 1);
88
89 solver.os = &std::cout;
90
91 // Results
92 real_t final_γ = 0, final_h = 0;
93 if constexpr (requires { stats.inner.final_γ; })
94 final_γ = stats.inner.final_γ;
95 if constexpr (requires { stats.inner.final_h; })
96 final_h = stats.inner.final_h;
97 decltype(SolverResults::extra) extra{};
98 if constexpr (requires { stats.inner.linesearch_failures; })
99 extra.emplace_back(
100 "linesearch_failures",
101 static_cast<index_t>(stats.inner.linesearch_failures));
102 if constexpr (requires { stats.inner.linesearch_backtracks; })
103 extra.emplace_back(
104 "linesearch_backtracks",
105 static_cast<index_t>(stats.inner.linesearch_backtracks));
106 if constexpr (requires { stats.inner.stepsize_backtracks; })
107 extra.emplace_back(
108 "stepsize_backtracks",
109 static_cast<index_t>(stats.inner.stepsize_backtracks));
110 if constexpr (requires { stats.inner.lbfgs_failures; })
111 extra.emplace_back("lbfgs_failures",
112 static_cast<index_t>(stats.inner.lbfgs_failures));
113 if constexpr (requires { stats.inner.lbfgs_rejected; })
114 extra.emplace_back("lbfgs_rejected",
115 static_cast<index_t>(stats.inner.lbfgs_rejected));
116 if constexpr (requires { stats.inner.accelerated_step_rejected; })
117 extra.emplace_back(
118 "accelerated_step_rejected",
119 static_cast<index_t>(stats.inner.accelerated_step_rejected));
120 if constexpr (requires { stats.inner.direction_failures; })
121 extra.emplace_back(
122 "direction_failures",
123 static_cast<index_t>(stats.inner.direction_failures));
124 if constexpr (requires { stats.inner.direction_update_rejected; })
125 extra.emplace_back(
126 "direction_update_rejected",
127 static_cast<index_t>(stats.inner.direction_update_rejected));
128 return SolverResults{
129 .status = enum_name(stats.status),
130 .success = stats.status == alpaqa::SolverStatus::Converged,
131 .evals = evals,
132 .duration = avg_duration,
133 .solver = solver.get_name(),
134 .h = final_h,
135 .δ = stats.δ,
136 .ε = stats.ε,
137 .γ = final_γ,
138 .Σ = stats.norm_penalty,
139 .solution = x,
140 .multipliers = y,
141 .multipliers_bounds = vec(0),
142 .penalties = Σ,
143 .outer_iter = static_cast<index_t>(stats.outer_iterations),
144 .inner_iter = static_cast<index_t>(stats.inner.iterations),
145 .extra = std::move(extra),
146 };
147}
auto make_inner_solver(Options &opts)
Definition: alm-driver.hpp:28
SolverResults run_alm_solver(LoadedProblem &problem, Solver &solver, std::ostream &os, unsigned N_exp)
Definition: alm-driver.hpp:56
auto make_alm_solver(InnerSolver &&inner_solver, Options &opts)
Definition: alm-driver.hpp:12
Augmented Lagrangian Method solver.
Definition: alm.hpp:96
length_t get_m() const
[Required] Number of constraints.
#define USING_ALPAQA_CONFIG(Conf)
Definition: config.hpp:54
std::string_view enum_name(Ipopt::ApplicationReturnStatus s)
Definition: ipopt-enums.hpp:6
@ ProjGradUnitNorm
∞-norm of the projected gradient with unit step size:
@ Interrupted
Solver was interrupted by the user.
@ Converged
Converged and reached given tolerance.
decltype(auto) set_params(T &t, std::string_view prefix, Options &opts)
Definition: options.hpp:27
vec initial_guess_y
Unknowns.
Definition: problem.hpp:21
vec initial_guess_x
Definition: problem.hpp:20
alpaqa::TypeErasedProblem< config_t > problem
Definition: problem.hpp:15
std::shared_ptr< alpaqa::EvalCounter > evaluations
Definition: problem.hpp:19
std::vector< std::pair< std::string, any_stat_t > > extra
Definition: results.hpp:37
std::string status
Definition: results.hpp:24
Double-precision double configuration.
Definition: config.hpp:127