alpaqa 1.0.0a13
Nonconvex constrained optimization
Loading...
Searching...
No Matches
problem.cpp
Go to the documentation of this file.
5#if ALPAQA_HAVE_DL
7#endif
8#if ALPAQA_HAVE_CASADI
10#endif
11#ifdef ALPAQA_HAVE_CUTEST
13#endif
14
15#include <filesystem>
16#include <fstream>
17#include <mutex>
18#include <optional>
19#include <span>
20#include <stdexcept>
21#include <string>
22
23#include "options.hpp"
24#include "problem.hpp"
25
26namespace fs = std::filesystem;
27
28namespace {
29
31
32std::string get_reg_name_option(std::span<const std::string_view> prob_opts) {
33 std::string name = "register_alpaqa_problem";
34 std::string_view name_key = "register=";
35 auto name_it = std::find_if(
36 prob_opts.rbegin(), prob_opts.rend(),
37 [&](std::string_view opt) { return opt.starts_with(name_key); });
38 if (name_it != prob_opts.rend())
39 name = name_it->substr(name_key.size());
40 return name;
41}
42
44 const auto n = problem.problem.get_n(), m = problem.problem.get_m();
45 alpaqa::params::vec_from_file<config_t> x0{n}, y0{m}, w0{2 * n};
46 set_params(x0, "x0", opts);
47 if (x0.value)
48 problem.initial_guess_x = std::move(*x0.value);
49 set_params(y0, "mul_g0", opts);
50 if (y0.value)
51 problem.initial_guess_y = std::move(*y0.value);
52 set_params(w0, "mul_x0", opts);
53 if (w0.value)
54 problem.initial_guess_w = std::move(*w0.value);
55}
56
57#if ALPAQA_HAVE_DL
58LoadedProblem load_dl_problem(const fs::path &full_path,
59 std::span<std::string_view> prob_opts,
60 Options &opts) {
62 using DLProblem = alpaqa::dl::DLProblem;
64 auto register_name = get_reg_name_option(prob_opts);
65 std::any dl_opt = prob_opts;
66 LoadedProblem problem{
67 .problem = TEProblem::make<CntProblem>(std::in_place, full_path.c_str(),
68 register_name, &dl_opt),
69 .abs_path = fs::absolute(full_path),
70 .path = full_path,
71 };
72 auto &cnt_problem = problem.problem.as<CntProblem>();
73 try {
74 using sig_t = std::string(const DLProblem::instance_t *);
75 problem.name = cnt_problem.problem.call_extra_func<sig_t>("get_name");
76 } catch (std::out_of_range &) {
77 problem.name = problem.path.filename();
78 }
79 problem.evaluations = cnt_problem.evaluations;
80 load_initial_guess(opts, problem);
81 return problem;
82}
83#endif
84
85#if ALPAQA_HAVE_CASADI
86template <bool = true>
87LoadedProblem load_cs_problem(const fs::path &full_path,
88 std::span<std::string_view> prob_opts,
89 Options &opts) {
90 static std::mutex mtx;
91 std::unique_lock lck{mtx};
93 using CsProblem = alpaqa::CasADiProblem<config_t>;
95 LoadedProblem problem{
96 .problem = TEProblem::make<CntProblem>(std::in_place,
97 full_path.string().c_str()),
98 .abs_path = fs::absolute(full_path),
99 .path = full_path,
100 };
101 lck.unlock();
102 auto &cnt_problem = problem.problem.as<CntProblem>();
103 auto &cs_problem = cnt_problem.problem;
104 problem.name = problem.path.filename().string();
105 problem.evaluations = cnt_problem.evaluations;
106 auto param_size = cs_problem.param.size();
107 alpaqa::params::set_params(cs_problem.param, "param", prob_opts);
108 if (cs_problem.param.size() != param_size)
110 "Incorrect problem parameter size: got " +
111 std::to_string(cs_problem.param.size()) + ", should be " +
112 std::to_string(param_size));
113 load_initial_guess(opts, problem);
114 return problem;
115}
116#endif
117
118#ifdef ALPAQA_HAVE_CUTEST
119template <bool = true>
120LoadedProblem load_cu_problem(const fs::path &full_path,
121 std::span<std::string_view> prob_opts,
122 Options &opts) {
123 std::string outsdif_path;
124 alpaqa::params::set_params(outsdif_path, "outsdif", prob_opts);
125 bool sparse = false;
126 alpaqa::params::set_params(sparse, "sparse", prob_opts);
127 static std::mutex mtx;
128 std::unique_lock lck{mtx};
129 using TEProblem = alpaqa::TypeErasedProblem<config_t>;
130 using CuProblem = alpaqa::CUTEstProblem;
132 LoadedProblem problem{
133 .problem = TEProblem::make<CntProblem>(std::in_place, full_path.c_str(),
134 outsdif_path.c_str(), sparse),
135 .abs_path = fs::absolute(full_path),
136 .path = full_path,
137 };
138 lck.unlock();
139 auto &cnt_problem = problem.problem.as<CntProblem>();
140 auto &cu_problem = cnt_problem.problem;
141 problem.name = cu_problem.name;
142 problem.evaluations = cnt_problem.evaluations;
143 problem.initial_guess_x = std::move(cu_problem.x0);
144 problem.initial_guess_y = std::move(cu_problem.y0);
145 load_initial_guess(opts, problem);
146 return problem;
147}
148#endif
149
150} // namespace
151
152LoadedProblem load_problem(std::string_view type, const fs::path &dir,
153 const fs::path &file, Options &opts) {
155 // Isolate problem-specific options
156 std::vector<std::string_view> prob_opts;
157 std::string_view prob_prefix = "problem.";
158 auto options = opts.options();
159 auto used = opts.used();
160 for (auto opt = options.begin(); opt != options.end(); ++opt) {
161 if (opt->starts_with(prob_prefix)) {
162 prob_opts.push_back(opt->substr(prob_prefix.size()));
163 ++used.begin()[opt - options.begin()];
164 }
165 }
166 // Load problem
167 auto full_path = dir / file;
168 if (type == "dl" || type.empty()) {
169#if ALPAQA_HAVE_DL
170 return load_dl_problem(full_path, prob_opts, opts);
171#else
172 throw std::logic_error("This version of alpaqa was compiled without "
173 "support for dynamic problem loading");
174#endif
175 } else if (type == "cs") {
176#if ALPAQA_HAVE_CASADI
177 if constexpr (std::is_same_v<config_t, alpaqa::EigenConfigd>)
178 return load_cs_problem(full_path, prob_opts, opts);
179 else
180 throw std::logic_error("CasADi only supports double precision.");
181#else
182 throw std::logic_error(
183 "This version of alpaqa was compiled without CasADi support");
184#endif
185 } else if (type == "cu") {
186#ifdef ALPAQA_HAVE_CUTEST
187 if constexpr (std::is_same_v<config_t, alpaqa::EigenConfigd>)
188 return load_cu_problem(full_path, prob_opts, opts);
189 else
190 throw std::logic_error("CUTEst only supports double precision.");
191#else
192 throw std::logic_error(
193 "This version of alpaqa was compiled without CUTEst support");
194#endif
195 }
196 throw std::invalid_argument("Unknown problem type '" + std::string(type) +
197 "'");
198}
std::span< unsigned > used()
Definition options.hpp:23
std::span< const std::string_view > options() const
Definition options.hpp:20
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.
length_t get_n() const
[Required] Number of decision variables.
length_t get_m() const
[Required] Number of constraints.
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:56
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
std::string get_reg_name_option(std::span< const std::string_view > prob_opts)
Definition problem.cpp:32
void load_initial_guess(Options &opts, LoadedProblem &problem)
Definition problem.cpp:43
decltype(auto) set_params(T &t, std::string_view prefix, Options &opts)
Definition options.hpp:27
LoadedProblem load_problem(std::string_view type, const fs::path &dir, const fs::path &file, Options &opts)
Definition problem.cpp:152
vec initial_guess_y
Unknowns.
Definition problem.hpp:21
vec initial_guess_x
Definition problem.hpp:20
vec initial_guess_w
Multipliers g.
Definition problem.hpp:22
alpaqa::TypeErasedProblem< config_t > problem
Definition problem.hpp:15
Double-precision double configuration.
Definition config.hpp:135
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