alpaqa develop
Nonconvex constrained optimization
Loading...
Searching...
No Matches
problem.cpp
Go to the documentation of this file.
1#include <alpaqa/export.h>
8#if ALPAQA_WITH_DL
10#endif
11#if ALPAQA_WITH_CASADI
13#endif
14#ifdef ALPAQA_WITH_CUTEST
16#endif
17
18#include <filesystem>
19#include <mutex>
20#include <optional>
21#include <span>
22#include <stdexcept>
23#include <string>
24namespace fs = std::filesystem;
25
26#include "options.hpp"
27#include "problem.hpp"
28
29namespace {
30
32
33std::string get_reg_name_option(std::span<const std::string_view> prob_opts) {
34 std::string name = "register_alpaqa_problem";
35 std::string_view name_key = "register=";
36 auto name_it = std::find_if(
37 prob_opts.rbegin(), prob_opts.rend(),
38 [&](std::string_view opt) { return opt.starts_with(name_key); });
39 if (name_it != prob_opts.rend())
40 name = name_it->substr(name_key.size());
41 return name;
42}
43
46 set_params(flags, "dl_flags", opts);
47 return flags;
48}
49
51 const auto n = problem.problem.get_n(), m = problem.problem.get_m();
53 set_params(x0, "x0", opts);
54 if (x0.value)
55 problem.initial_guess_x = std::move(*x0.value);
56 set_params(y0, "mul_g0", opts);
57 if (y0.value)
58 problem.initial_guess_y = std::move(*y0.value);
59 set_params(w0, "mul_x0", opts);
60 if (w0.value)
61 problem.initial_guess_w = std::move(*w0.value);
62}
63
65 const auto n = C.lowerbound.size();
66 cnt.lb = 0;
67 cnt.ub = 0;
68 cnt.lbub = 0;
69 cnt.eq = 0;
70 for (index_t i = 0; i < n; ++i) {
71 bool lb = C.lowerbound(i) > -alpaqa::inf<config_t>;
72 bool ub = C.upperbound(i) < +alpaqa::inf<config_t>;
73 bool eq = C.lowerbound(i) == C.upperbound(i);
74 if (eq)
75 ++cnt.eq;
76 else if (lb && ub)
77 ++cnt.lbub;
78 else if (lb)
79 ++cnt.lb;
80 else if (ub)
81 ++cnt.ub;
82 }
83}
84
97
98#if ALPAQA_WITH_DL
99LoadedProblem load_dl_problem(const fs::path &full_path,
100 std::span<std::string_view> prob_opts,
101 Options &opts) {
102 using TEProblem = alpaqa::TypeErasedProblem<config_t>;
103 using DLProblem = alpaqa::dl::DLProblem;
105 auto register_name = get_reg_name_option(prob_opts);
106 auto flags = get_dl_flags(opts);
107 LoadedProblem problem{
108 .problem = TEProblem::make<CntProblem>(std::in_place, full_path,
109 register_name, prob_opts, flags),
110 .abs_path = fs::absolute(full_path),
111 .path = full_path,
112 };
113 auto &cnt_problem = problem.problem.as<CntProblem>();
114 problem.name = cnt_problem.problem.get_name();
115 problem.evaluations = cnt_problem.evaluations;
116 load_initial_guess(opts, problem);
117 count_problem(problem);
118 return problem;
119}
120#endif
121
122#if ALPAQA_WITH_CASADI
123template <bool = true>
124LoadedProblem load_cs_problem(const fs::path &full_path,
125 std::span<std::string_view> prob_opts,
126 Options &opts) {
127 static std::mutex mtx;
128 std::unique_lock lck{mtx};
129 using TEProblem = alpaqa::TypeErasedProblem<config_t>;
130 using CsProblem = alpaqa::CasADiProblem<config_t>;
132 auto flags = get_dl_flags(opts);
133 LoadedProblem problem{
134 .problem = TEProblem::make<CntProblem>(
135 std::in_place, full_path.string().c_str(), flags),
136 .abs_path = fs::absolute(full_path),
137 .path = full_path,
138 };
139 lck.unlock();
140 auto &cnt_problem = problem.problem.as<CntProblem>();
141 auto &cs_problem = cnt_problem.problem;
142 problem.name = cs_problem.get_name();
143 problem.evaluations = cnt_problem.evaluations;
144 auto param_size = cs_problem.param.size();
145 alpaqa::params::set_params(cs_problem.param, "param", prob_opts);
146 if (cs_problem.param.size() != param_size)
148 "Incorrect problem parameter size (expected " +
149 std::to_string(param_size) + ", but got " +
150 std::to_string(cs_problem.param.size()) + ")");
151 load_initial_guess(opts, problem);
152 count_problem(problem);
153 return problem;
154}
155#endif
156
157#ifdef ALPAQA_WITH_CUTEST
158template <bool = true>
159LoadedProblem load_cu_problem(const fs::path &full_path,
160 std::span<std::string_view> prob_opts,
161 Options &opts) {
162 std::string outsdif_path;
163 alpaqa::params::set_params(outsdif_path, "outsdif", prob_opts);
164 bool sparse = false;
165 alpaqa::params::set_params(sparse, "sparse", prob_opts);
166 static std::mutex mtx;
167 std::unique_lock lck{mtx};
168 using TEProblem = alpaqa::TypeErasedProblem<config_t>;
169 using CuProblem = alpaqa::CUTEstProblem;
171 auto flags = get_dl_flags(opts);
172 LoadedProblem problem{
173 .problem =
174 TEProblem::make<CntProblem>(std::in_place, full_path.c_str(),
175 outsdif_path.c_str(), sparse, flags),
176 .abs_path = fs::absolute(full_path),
177 .path = full_path,
178 };
179 lck.unlock();
180 auto &cnt_problem = problem.problem.as<CntProblem>();
181 auto &cu_problem = cnt_problem.problem;
182 problem.name = cu_problem.get_name();
183 problem.evaluations = cnt_problem.evaluations;
184 problem.initial_guess_x = std::move(cu_problem.x0);
185 problem.initial_guess_y = std::move(cu_problem.y0);
186 load_initial_guess(opts, problem);
187 count_problem(problem);
188 return problem;
189}
190#endif
191
192} // namespace
193
194LoadedProblem load_problem(std::string_view type, const fs::path &dir,
195 const fs::path &file, Options &opts) {
197 // Isolate problem-specific options
198 std::vector<std::string_view> prob_opts;
199 std::string_view prob_prefix = "problem.";
200 auto options = opts.options();
201 auto used = opts.used();
202 for (auto opt = options.begin(); opt != options.end(); ++opt) {
203 if (opt->starts_with(prob_prefix)) {
204 prob_opts.push_back(opt->substr(prob_prefix.size()));
205 ++used.begin()[opt - options.begin()];
206 }
207 }
208 // Load problem
209 auto full_path = dir / file;
210 if (type == "dl" || type.empty()) {
211#if ALPAQA_WITH_DL
212 return load_dl_problem(full_path, prob_opts, opts);
213#else
214 throw std::logic_error("This version of alpaqa was compiled without "
215 "support for dynamic problem loading");
216#endif
217 } else if (type == "cs") {
218#if ALPAQA_WITH_CASADI
219 if constexpr (std::is_same_v<config_t, alpaqa::EigenConfigd>)
220 return load_cs_problem(full_path, prob_opts, opts);
221 else
222 throw std::logic_error("CasADi only supports double precision.");
223#else
224 throw std::logic_error(
225 "This version of alpaqa was compiled without CasADi support");
226#endif
227 } else if (type == "cu") {
228#ifdef ALPAQA_WITH_CUTEST
229 if constexpr (std::is_same_v<config_t, alpaqa::EigenConfigd>)
230 return load_cu_problem(full_path, prob_opts, opts);
231 else
232 throw std::logic_error("CUTEst only supports double precision.");
233#else
234 throw std::logic_error(
235 "This version of alpaqa was compiled without CUTEst support");
236#endif
237 }
238 throw std::invalid_argument("Unknown problem type '" + std::string(type) +
239 "'");
240}
std::span< unsigned > used()
Definition options.hpp:61
std::span< const std::string_view > options() const
Definition options.hpp:58
Wrapper for CUTEst problems loaded from an external shared library.
Problem definition for a CasADi problem, loaded from a DLL.
The main polymorphic minimization problem interface.
bool provides_get_hess_L_sparsity() const
Returns true if the problem provides an implementation of get_hess_L_sparsity.
const Box & get_box_D() const
[Optional] Get the rectangular constraint set of the general constraint function, .
bool provides_get_box_C() const
Returns true if the problem provides an implementation of get_box_C.
Sparsity get_jac_g_sparsity() const
[Optional] Function that returns (a view of) the sparsity pattern of the Jacobian of the constraints.
Sparsity get_hess_ψ_sparsity() const
[Optional] Function that returns (a view of) the sparsity pattern of the Hessian of the augmented Lag...
length_t get_n() const
[Required] Number of decision variables.
Sparsity get_hess_L_sparsity() const
[Optional] Function that returns (a view of) the sparsity pattern of the Hessian of the Lagrangian.
length_t get_m() const
[Required] Number of constraints.
bool provides_get_hess_ψ_sparsity() const
Returns true if the problem provides an implementation of get_hess_ψ_sparsity.
bool provides_get_jac_g_sparsity() const
Returns true if the problem provides an implementation of get_jac_g_sparsity.
bool provides_get_box_D() const
Returns true if the problem provides an implementation of get_box_D.
const Box & get_box_C() const
[Optional] Get the rectangular constraint set of the decision variables, .
Class that loads a problem using dlopen.
T & as() &
Convert the type-erased object to the given type.
#define USING_ALPAQA_CONFIG(Conf)
Definition config.hpp:77
void set_params(T &t, std::string_view prefix, std::span< const std::string_view > options, std::optional< std::span< unsigned > > used=std::nullopt)
Overwrites t based on the options that start with prefix.
Definition params.hpp:49
constexpr const auto inf
Definition config.hpp:112
void count_constr(ConstrCount &cnt, const alpaqa::Box< config_t > &C)
Definition problem.cpp:64
alpaqa::DynamicLoadFlags get_dl_flags(Options &opts)
Definition problem.cpp:44
std::string get_reg_name_option(std::span< const std::string_view > prob_opts)
Definition problem.cpp:33
void count_problem(LoadedProblem &p)
Definition problem.cpp:85
void load_initial_guess(Options &opts, LoadedProblem &problem)
Definition problem.cpp:50
void set_params(T &t, std::string_view prefix, Options &opts)
Definition options.hpp:126
LoadedProblem load_problem(std::string_view type, const fs::path &dir, const fs::path &file, Options &opts)
Definition problem.cpp:194
vec initial_guess_y
Multipliers g.
Definition problem.hpp:31
vec initial_guess_x
Unknowns.
Definition problem.hpp:30
vec initial_guess_w
Multipliers bounds.
Definition problem.hpp:32
std::optional< length_t > nnz_hess_L
Definition problem.hpp:35
std::optional< ConstrCount > general_constr_count
Definition problem.hpp:34
std::optional< length_t > nnz_hess_ψ
Definition problem.hpp:36
alpaqa::TypeErasedProblem< config_t > problem
Definition problem.hpp:25
std::optional< ConstrCount > box_constr_count
Definition problem.hpp:33
std::optional< length_t > nnz_jac_g
Definition problem.hpp:35
length_t ub
Number of variables with only upper bound.
Definition problem.hpp:18
length_t eq
Number of variables with equal bounds.
Definition problem.hpp:20
length_t lb
Number of variables with only lower bound.
Definition problem.hpp:17
length_t lbub
Number of variables with both bounds.
Definition problem.hpp:19
Flags to be passed to dlopen.
Definition dl-flags.hpp:8
Double-precision double configuration.
Definition config.hpp:176
Problem wrapper that keeps track of the number of evaluations and the run time of each function.
Custom parameter parsing exception.
Definition params.hpp:26