alpaqa 1.0.0a11
Nonconvex constrained optimization
Loading...
Searching...
No Matches
params.cpp
Go to the documentation of this file.
11#include <alpaqa/outer/alm.hpp>
13#if ALPAQA_WITH_OCP
15#endif
16
18
19#include <fstream>
20
21#include "from_chars-compat.ipp"
22
23namespace alpaqa::params {
24
25template <>
26void ALPAQA_EXPORT set_param(bool &b, ParamString s) {
27 assert_key_empty<bool>(s);
28 if (s.value == "0" || s.value == "false")
29 b = false;
30 else if (s.value == "1" || s.value == "true")
31 b = true;
32 else
33 throw std::invalid_argument(
34 "Invalid value '" + std::string(s.value) +
35 "' for type 'bool' in '" + std::string(s.full_key) +
36 "',\n "
37 "possible values are: '0', '1', 'true', 'false'");
38}
39
40template <>
41void ALPAQA_EXPORT set_param(std::string_view &v, ParamString s) {
42 assert_key_empty<bool>(s);
43 v = s.value;
44}
45
46template <>
47void ALPAQA_EXPORT set_param(std::string &v, ParamString s) {
48 assert_key_empty<bool>(s);
49 v = s.value;
50}
51
52template <class T>
53 requires((std::floating_point<T> || std::integral<T>) && !std::is_enum_v<T>)
54void set_param(T &f, ParamString s) {
55 assert_key_empty<T>(s);
56 const auto *val_end = s.value.data() + s.value.size();
57 const auto *ptr = set_param_float_int(f, s);
58 if (ptr != val_end)
59 throw std::invalid_argument("Invalid suffix '" +
60 std::string(ptr, val_end) + "' for type '" +
61 demangled_typename(typeid(T)) + "' in '" +
62 std::string(s.full_key) + "'");
63}
64
65#ifdef ALPAQA_WITH_QUAD_PRECISION
66template <>
67void ALPAQA_EXPORT set_param(__float128 &f, ParamString s) {
68 long double ld;
69 set_param(ld, s);
70 f = static_cast<__float128>(ld);
71}
72#endif
73
74template <>
75void ALPAQA_EXPORT set_param(alpaqa::vec<config_t> &v, ParamString s) {
76 v.resize(std::count(s.value.begin(), s.value.end(), ',') + 1);
77 std::string_view value, remainder = s.value;
78 for (auto &e : v) {
79 std::tie(value, remainder) = split_key(remainder, ',');
80 set_param(e, {.full_key = s.full_key, .key = "", .value = value});
81 }
82}
83
84template <>
86 assert_key_empty<vec_from_file<config_t>>(s);
87 if (s.value.starts_with('@')) {
88 std::string fpath{s.value.substr(1)};
89 std::ifstream f(fpath);
90 if (!f)
91 throw std::invalid_argument("Unable to open file '" + fpath +
92 "' in '" + std::string(s.full_key) +
93 '\'');
94 try {
95 auto r = alpaqa::csv::read_row_std_vector<real_t<config_t>>(f);
96 auto r_size = static_cast<length_t<config_t>>(r.size());
97 if (v.expected_size >= 0 && r_size != v.expected_size)
98 throw std::invalid_argument(
99 "Incorrect size in '" + std::string(s.full_key) +
100 "' (got " + std::to_string(r.size()) + ", expected " +
101 std::to_string(v.expected_size) + ')');
102 v.value.emplace(cmvec<config_t>{r.data(), r_size});
103 } catch (alpaqa::csv::read_error &e) {
104 throw std::invalid_argument(
105 "Unable to read from file '" + fpath + "' in '" +
106 std::string(s.full_key) +
107 "': alpaqa::csv::read_error: " + e.what());
108 }
109 } else {
110 alpaqa::params::set_param(v.value.emplace(), s);
111 if (v.expected_size >= 0 && v.value->size() != v.expected_size)
112 throw std::invalid_argument(
113 "Incorrect size in '" + std::string(s.full_key) + "' (got " +
114 std::to_string(v.value->size()) + ", expected " +
115 std::to_string(v.expected_size) + ')');
116 }
117}
118
119template <class Rep, class Period>
120void set_param(std::chrono::duration<Rep, Period> &t, ParamString s) {
121 using Duration = std::remove_cvref_t<decltype(t)>;
122 assert_key_empty<Duration>(s);
123 const auto *val_end = s.value.data() + s.value.size();
124 double value;
125#if ALPAQA_USE_FROM_CHARS_FLOAT
126 auto [ptr, ec] = std::from_chars(s.value.data(), val_end, value);
127 if (ec != std::errc())
128 throw std::invalid_argument("Invalid value '" +
129 std::string(ptr, val_end) + "' for type '" +
130 demangled_typename(typeid(Duration)) +
131 "' in '" + std::string(s.full_key) +
132 "': " + std::make_error_code(ec).message());
133#else
134#pragma message "Using std::stod as a fallback to replace std::from_chars"
135 size_t end_index;
136 try {
137 value = std::stod(std::string(s.value), &end_index);
138 } catch (std::exception &e) {
139 throw std::invalid_argument(
140 "Invalid value '" + std::string(s.value) + "' for type '" +
141 demangled_typename(typeid(Duration)) + "' in '" +
142 std::string(s.full_key) + "': " + e.what());
143 }
144 const char *ptr = s.value.data() + end_index;
145#endif
146 std::string_view units{ptr, val_end};
147 auto cast = [](auto t) { return std::chrono::duration_cast<Duration>(t); };
148 if (units == "s" || units.empty())
149 t = cast(std::chrono::duration<double, std::ratio<1, 1>>{value});
150 else if (units == "ms")
151 t = cast(std::chrono::duration<double, std::ratio<1, 1000>>{value});
152 else if (units == "us" || units == "µs")
153 t = cast(std::chrono::duration<double, std::ratio<1, 1000000>>{value});
154 else if (units == "ns")
155 t = cast(
156 std::chrono::duration<double, std::ratio<1, 1000000000>>{value});
157 else if (units == "min")
158 t = cast(std::chrono::duration<double, std::ratio<60, 1>>{value});
159 else
160 throw std::invalid_argument("Invalid units '" + std::string(units) +
161 "' in '" + std::string(s.full_key) + "'");
162}
163
164template <>
165void ALPAQA_EXPORT set_param(LBFGSStepSize &t, ParamString s) {
166 if (s.value == "BasedOnExternalStepSize")
168 else if (s.value == "BasedOnCurvature")
170 else
171 throw std::invalid_argument("Invalid value '" + std::string(s.value) +
172 "' for type 'LBFGSStepSize' in '" +
173 std::string(s.full_key) + "'");
174}
175
176template <>
177void ALPAQA_EXPORT set_param(PANOCStopCrit &t, ParamString s) {
178 if (s.value == "ApproxKKT")
180 else if (s.value == "ApproxKKT2")
182 else if (s.value == "ProjGradNorm")
184 else if (s.value == "ProjGradNorm2")
186 else if (s.value == "ProjGradUnitNorm")
188 else if (s.value == "ProjGradUnitNorm2")
190 else if (s.value == "FPRNorm")
192 else if (s.value == "FPRNorm2")
194 else if (s.value == "Ipopt")
196 else if (s.value == "LBFGSBpp")
198 else
199 throw std::invalid_argument("Invalid value '" + std::string(s.value) +
200 "' for type 'PANOCStopCrit' in '" +
201 std::string(s.full_key) + "'");
202}
203
205 PARAMS_MEMBER(memory), //
206 PARAMS_MEMBER(min_div_fac), //
207 PARAMS_MEMBER(min_abs_s), //
208 PARAMS_MEMBER(cbfgs), //
209 PARAMS_MEMBER(force_pos_def), //
210 PARAMS_MEMBER(stepsize), //
212
214 PARAMS_MEMBER(memory), //
215 PARAMS_MEMBER(min_div_fac), //
217
219 PARAMS_MEMBER(α), //
220 PARAMS_MEMBER(ϵ), //
222
224 PARAMS_MEMBER(L_0), //
225 PARAMS_MEMBER(δ), //
226 PARAMS_MEMBER(ε), //
227 PARAMS_MEMBER(Lγ_factor), //
229
231 PARAMS_MEMBER(Lipschitz), //
232 PARAMS_MEMBER(max_iter), //
233 PARAMS_MEMBER(max_time), //
234 PARAMS_MEMBER(L_min), //
235 PARAMS_MEMBER(L_max), //
236 PARAMS_MEMBER(stop_crit), //
237 PARAMS_MEMBER(max_no_progress), //
238 PARAMS_MEMBER(print_interval), //
239 PARAMS_MEMBER(print_precision), //
240 PARAMS_MEMBER(quadratic_upperbound_tolerance_factor), //
241 PARAMS_MEMBER(TR_tolerance_factor), //
242 PARAMS_MEMBER(ratio_threshold_acceptable), //
243 PARAMS_MEMBER(ratio_threshold_good), //
244 PARAMS_MEMBER(radius_factor_rejected), //
245 PARAMS_MEMBER(radius_factor_acceptable), //
246 PARAMS_MEMBER(radius_factor_good), //
247 PARAMS_MEMBER(initial_radius), //
248 PARAMS_MEMBER(min_radius), //
249 PARAMS_MEMBER(compute_ratio_using_new_stepsize), //
250 PARAMS_MEMBER(update_direction_on_prox_step), //
251 PARAMS_MEMBER(recompute_last_prox_step_after_direction_reset), //
252 PARAMS_MEMBER(disable_acceleration), //
253 PARAMS_MEMBER(ratio_approx_fbe_quadratic_model), //
255
257 PARAMS_MEMBER(Lipschitz), //
258 PARAMS_MEMBER(max_iter), //
259 PARAMS_MEMBER(max_time), //
260 PARAMS_MEMBER(min_linesearch_coefficient), //
261 PARAMS_MEMBER(force_linesearch), //
262 PARAMS_MEMBER(linesearch_strictness_factor), //
263 PARAMS_MEMBER(L_min), //
264 PARAMS_MEMBER(L_max), //
265 PARAMS_MEMBER(stop_crit), //
266 PARAMS_MEMBER(max_no_progress), //
267 PARAMS_MEMBER(print_interval), //
268 PARAMS_MEMBER(print_precision), //
269 PARAMS_MEMBER(quadratic_upperbound_tolerance_factor), //
270 PARAMS_MEMBER(linesearch_tolerance_factor), //
271 PARAMS_MEMBER(update_direction_in_candidate), //
272 PARAMS_MEMBER(recompute_last_prox_step_after_lbfgs_flush), //
273 PARAMS_MEMBER(eager_gradient_eval), //
275
277 PARAMS_MEMBER(Lipschitz), //
278 PARAMS_MEMBER(max_iter), //
279 PARAMS_MEMBER(max_time), //
280 PARAMS_MEMBER(min_linesearch_coefficient), //
281 PARAMS_MEMBER(force_linesearch), //
282 PARAMS_MEMBER(linesearch_strictness_factor), //
283 PARAMS_MEMBER(L_min), //
284 PARAMS_MEMBER(L_max), //
285 PARAMS_MEMBER(stop_crit), //
286 PARAMS_MEMBER(max_no_progress), //
287 PARAMS_MEMBER(print_interval), //
288 PARAMS_MEMBER(print_precision), //
289 PARAMS_MEMBER(quadratic_upperbound_tolerance_factor), //
290 PARAMS_MEMBER(linesearch_tolerance_factor), //
291 PARAMS_MEMBER(update_direction_in_candidate), //
292 PARAMS_MEMBER(recompute_last_prox_step_after_lbfgs_flush), //
293 PARAMS_MEMBER(update_direction_from_prox_step), //
295
297 PARAMS_MEMBER(rescale_on_step_size_changes), //
299
301 PARAMS_MEMBER(rescale_on_step_size_changes), //
303
305 PARAMS_MEMBER(hessian_vec_factor), //
306 PARAMS_MEMBER(hessian_vec_finite_differences), //
307 PARAMS_MEMBER(full_augmented_hessian), //
309
311 PARAMS_MEMBER(rescale_on_step_size_changes), //
312 PARAMS_MEMBER(hessian_vec_factor), //
314 PARAMS_MEMBER(finite_diff_stepsize), //
316
318 PARAMS_MEMBER(tol_scale), //
319 PARAMS_MEMBER(tol_scale_root), //
320 PARAMS_MEMBER(tol_max), //
321 PARAMS_MEMBER(max_iter_factor), //
323
325 PARAMS_MEMBER(min_eig), //
326 PARAMS_MEMBER(print_eig), //
328
330 PARAMS_MEMBER(hessian_vec_factor), //
332
334 PARAMS_MEMBER(tolerance), //
335 PARAMS_MEMBER(dual_tolerance), //
336 PARAMS_MEMBER(penalty_update_factor), //
337 PARAMS_MEMBER(penalty_update_factor_lower), //
338 PARAMS_MEMBER(min_penalty_update_factor), //
339 PARAMS_MEMBER(initial_penalty), //
340 PARAMS_MEMBER(initial_penalty_factor), //
341 PARAMS_MEMBER(initial_penalty_lower), //
342 PARAMS_MEMBER(initial_tolerance), //
343 PARAMS_MEMBER(initial_tolerance_increase), //
344 PARAMS_MEMBER(tolerance_update_factor), //
345 PARAMS_MEMBER(ρ_increase), //
346 PARAMS_MEMBER(ρ_max), //
347 PARAMS_MEMBER(rel_penalty_increase_threshold), //
348 PARAMS_MEMBER(max_multiplier), //
349 PARAMS_MEMBER(max_penalty), //
350 PARAMS_MEMBER(min_penalty), //
351 PARAMS_MEMBER(max_iter), //
352 PARAMS_MEMBER(max_time), //
353 PARAMS_MEMBER(max_num_initial_retries), //
354 PARAMS_MEMBER(max_num_retries), //
355 PARAMS_MEMBER(max_total_num_retries), //
356 PARAMS_MEMBER(print_interval), //
357 PARAMS_MEMBER(print_precision), //
358 PARAMS_MEMBER(single_penalty_factor), //
360
361#if ALPAQA_WITH_OCP
363 PARAMS_MEMBER(Lipschitz), //
364 PARAMS_MEMBER(max_iter), //
365 PARAMS_MEMBER(max_time), //
366 PARAMS_MEMBER(min_linesearch_coefficient), //
367 PARAMS_MEMBER(linesearch_strictness_factor), //
368 PARAMS_MEMBER(L_min), //
369 PARAMS_MEMBER(L_max), //
370 PARAMS_MEMBER(L_max_inc), //
371 PARAMS_MEMBER(stop_crit), //
372 PARAMS_MEMBER(max_no_progress), //
373 PARAMS_MEMBER(gn_interval), //
374 PARAMS_MEMBER(gn_sticky), //
375 PARAMS_MEMBER(reset_lbfgs_on_gn_step), //
376 PARAMS_MEMBER(lqr_factor_cholesky), //
377 PARAMS_MEMBER(lbfgs_params), //
378 PARAMS_MEMBER(print_interval), //
379 PARAMS_MEMBER(print_precision), //
380 PARAMS_MEMBER(quadratic_upperbound_tolerance_factor), //
381 PARAMS_MEMBER(linesearch_tolerance_factor), //
382 PARAMS_MEMBER(disable_acceleration), //
384#endif
385
386namespace detail {
387
388/// Check if @p A is equal to any of @p Bs.
389template <class A, class... Bs>
390constexpr bool any_is_same() {
391 return (std::is_same_v<A, Bs> || ...);
392}
393
394/// Unused unique type tag for template specializations that were rejected
395/// because some types were not distinct.
396template <class...>
397struct _dummy;
398
399/// If @p NewAlias is not the same type as any of @p PossibleAliases, the result
400/// is @p NewAlias. If @p NewAlias is not distinct from @p PossibleAliases, the
401/// result is a dummy type, uniquely determined by @p NewAlias and
402/// @p PossibleAliases.
403template <class NewAlias, class... PossibleAliases>
405 std::conditional_t<any_is_same<NewAlias, PossibleAliases...>(),
406 _dummy<NewAlias, PossibleAliases...>, NewAlias>;
407
408} // namespace detail
409
410template <class... Ts>
411void set_param(detail::_dummy<Ts...> &, ParamString) {}
412
413#define ALPAQA_SET_PARAM_INST(...) \
414 template void ALPAQA_EXPORT set_param( \
415 detail::possible_alias_t<__VA_ARGS__> &, ParamString)
416
419ALPAQA_SET_PARAM_INST(long double, double, float);
420
429
430// Here, we would like to instantiate alpaqa::params::set_param for all standard
431// integer types, but the issue is that they might not be distinct types:
432// For example, on some platforms, int32_t might be a weak alias to int, whereas
433// on other platforms, it could be a distinct type.
434// To resolve this issue, we use some metaprogramming to ensure distinct
435// instantiations with unique dummy types.
436#define ALPAQA_SET_PARAM_INST_INT(...) \
437 ALPAQA_SET_PARAM_INST(__VA_ARGS__, int8_t, uint8_t, int16_t, uint16_t, \
438 int32_t, int64_t, uint32_t, uint64_t)
439
443ALPAQA_SET_PARAM_INST_INT(long long, long, int, short);
444ALPAQA_SET_PARAM_INST_INT(ptrdiff_t, long long, long, int, short);
446ALPAQA_SET_PARAM_INST_INT(unsigned int, unsigned short);
447ALPAQA_SET_PARAM_INST_INT(unsigned long, unsigned int, unsigned short);
448ALPAQA_SET_PARAM_INST_INT(unsigned long long, unsigned long, unsigned int,
449 unsigned short);
450ALPAQA_SET_PARAM_INST_INT(size_t, unsigned long long, unsigned long,
451 unsigned int, unsigned short);
452
453ALPAQA_SET_PARAM_INST(std::chrono::nanoseconds);
454ALPAQA_SET_PARAM_INST(std::chrono::microseconds);
455ALPAQA_SET_PARAM_INST(std::chrono::milliseconds);
456ALPAQA_SET_PARAM_INST(std::chrono::seconds);
457ALPAQA_SET_PARAM_INST(std::chrono::minutes);
458ALPAQA_SET_PARAM_INST(std::chrono::hours);
459
473#if ALPAQA_WITH_OCP
475#endif
476
477} // namespace alpaqa::params
std::string demangled_typename(const std::type_info &t)
Get the pretty name of the given type as a string.
vec finite_diff(const std::function< real_t(crvec)> &f, crvec x)
std::conditional_t< any_is_same< NewAlias, PossibleAliases... >(), _dummy< NewAlias, PossibleAliases... >, NewAlias > possible_alias_t
If NewAlias is not the same type as any of PossibleAliases, the result is NewAlias.
Definition: params.cpp:406
constexpr bool any_is_same()
Check if A is equal to any of Bs.
Definition: params.cpp:390
void set_param(bool &b, ParamString s)
Definition: params.cpp:26
std::string_view full_key
Full key string, used for diagnostics.
Definition: params.hpp:18
auto split_key(std::string_view full, char tok='.')
Split the string full on the first occurrence of tok.
Definition: params.hpp:32
std::optional< vec > value
Definition: params.hpp:70
std::string_view value
The value of the parameter to store.
Definition: params.hpp:22
Represents a parameter value encoded as a string in the format abc.def.key=value.
Definition: params.hpp:16
@ LBFGSBpp
The stopping criterion used by LBFGS++, see https://lbfgspp.statr.me/doc/classLBFGSpp_1_1LBFGSBParam....
@ 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:
typename Conf::length_t length_t
Definition: config.hpp:74
typename Conf::cmvec cmvec
Definition: config.hpp:66
typename Conf::vec vec
Definition: config.hpp:64
LBFGSStepSize
Which method to use to select the L-BFGS step size.
Definition: lbfgs.hpp:25
@ BasedOnCurvature
Initial inverse Hessian approximation is set to .
@ BasedOnExternalStepSize
Initial inverse Hessian approximation is set to .
Parameters for the Augmented Lagrangian solver.
Definition: alm.hpp:20
Parameters for the AndersonAccel class.
Definition: anderson.hpp:14
Parameters for the AndersonDirection class.
Definition: anderson.hpp:11
Parameters for the LBFGSDirection class.
Definition: lbfgs.hpp:11
Parameters for the LBFGS class.
Definition: lbfgs.hpp:39
Parameters for the NewtonTRDirection class.
Definition: newton-tr.hpp:16
Tuning parameters for the PANOC algorithm.
Definition: panoc-ocp.hpp:16
Tuning parameters for the PANOC algorithm.
Definition: panoc.hpp:24
Tuning parameters for the PANTR algorithm.
Definition: pantr.hpp:22
Parameters for the StructuredNewtonDirection class.
Parameters for the StructuredNewtonDirection class.
Tuning parameters for the ZeroFPR algorithm.
Definition: zerofpr.hpp:23
#define ALPAQA_SET_PARAM_INST(...)
Definition: params.cpp:413
#define ALPAQA_SET_PARAM_INST_INT(...)
Definition: params.cpp:436
#define PARAMS_MEMBER(name)
Helper macro to easily initialize a alpaqa::params::dict_to_struct_table_t.
Definition: params.tpp:137
#define PARAMS_TABLE(type_,...)
Helper macro to easily specialize alpaqa::params::dict_to_struct_table.
Definition: params.tpp:128
Cautious BFGS update.
Definition: lbfgs.hpp:17
Parameters for the StructuredLBFGSDirection class.