alpaqa pantr
Nonconvex constrained optimization
Loading...
Searching...
No Matches
problem.cpp
Go to the documentation of this file.
6#if ALPAQA_HAVE_CASADI
8#endif
9
10#include <filesystem>
11#include <fstream>
12#include <mutex>
13#include <optional>
14#include <span>
15#include <stdexcept>
16#include <string>
17
18#include "options.hpp"
19#include "problem.hpp"
20
21namespace fs = std::filesystem;
22
23namespace {
24
26
27std::string get_prefix_option(std::span<const std::string_view> prob_opts) {
28 std::string prefix = "benchmark_problem";
29 std::string_view prefix_key = "prefix=";
30 auto prefix_it = std::find_if(
31 prob_opts.rbegin(), prob_opts.rend(),
32 [&](std::string_view opt) { return opt.starts_with(prefix_key); });
33 if (prefix_it != prob_opts.rend())
34 prefix = prefix_it->substr(prefix_key.size());
35 return prefix;
36}
37
38struct FileVec {
39 length_t expected_size;
40 std::optional<vec> value = std::nullopt;
41};
42
43void load_file_vec_opt(FileVec &v, alpaqa::params::ParamString s) {
44 if (s.value.starts_with('@')) {
45 fs::path fpath = s.value.substr(1);
46 std::ifstream f(fpath);
47 if (!f)
48 throw std::invalid_argument("Unable to open file '" +
49 fpath.string() + "' in '" +
50 std::string(s.full_key) + '\'');
51 try {
52 alpaqa::csv::read_row(f, v.value.emplace(v.expected_size));
53 } catch (alpaqa::csv::read_error &e) {
54 throw std::invalid_argument(
55 "Unable to read from file '" + fpath.string() + "' in '" +
56 std::string(s.full_key) + "': " + e.what());
57 }
58 } else {
59 alpaqa::params::set_param(v.value.emplace(), s);
60 if (v.value->size() != v.expected_size) {
61 throw std::invalid_argument(
62 "Incorrect size in '" + std::string(s.full_key) + "' (got " +
63 std::to_string(v.value->size()) + ", expected " +
64 std::to_string(v.expected_size) + ')');
65 }
66 }
67}
68
69} // namespace
70
71namespace alpaqa::params {
72template <>
73void set_param(FileVec &v, ParamString s) {
74 if (!s.key.empty())
75 throw invalid_param("Invalid option indexing in '" +
76 std::string(s.full_key) + "'");
77 load_file_vec_opt(v, s);
78}
79} // namespace alpaqa::params
80
81namespace {
82void load_initial_guess(Options &opts, LoadedProblem &problem) {
83 const auto n = problem.problem.get_n(), m = problem.problem.get_m();
84 FileVec x0{n}, y0{m}, w0{2 * n};
85 set_params(x0, "x0", opts);
86 if (x0.value)
87 problem.initial_guess_x = std::move(*x0.value);
88 set_params(y0, "mul_g0", opts);
89 if (y0.value)
90 problem.initial_guess_y = std::move(*y0.value);
91 set_params(w0, "mul_x0", opts);
92 if (w0.value)
93 problem.initial_guess_w = std::move(*w0.value);
94}
95} // namespace
96
97LoadedProblem load_problem(std::string_view type, const fs::path &dir,
98 const fs::path &file, Options &opts) {
100 // Isolate problem-specific options
101 std::vector<std::string_view> prob_opts;
102 std::string_view prob_prefix = "problem.";
103 auto options = opts.options();
104 auto used = opts.used();
105 for (auto opt = options.begin(); opt != options.end(); ++opt) {
106 if (opt->starts_with(prob_prefix)) {
107 prob_opts.push_back(opt->substr(prob_prefix.size()));
108 used.begin()[opt - options.begin()] = true;
109 }
110 }
111 // Load problem
112 auto full_path = dir / file;
113 if (type == "dl" || type.empty()) {
114 using TEProblem = alpaqa::TypeErasedProblem<config_t>;
115 using DLProblem = alpaqa::dl::DLProblem;
117 auto prefix = get_prefix_option(prob_opts);
118 std::any dl_opt = std::span{prob_opts};
119 LoadedProblem problem{
120 .problem = TEProblem::make<CntProblem>(
121 std::in_place, full_path.c_str(), prefix, &dl_opt),
122 .abs_path = fs::absolute(full_path),
123 .path = full_path,
124 };
125 auto &cnt_problem = problem.problem.as<CntProblem>();
126 problem.evaluations = cnt_problem.evaluations;
127 load_initial_guess(opts, problem);
128 return problem;
129 } else if (type == "cs") {
130#if ALPAQA_HAVE_CASADI
131 static std::mutex mtx;
132 std::unique_lock lck{mtx};
133 using TEProblem = alpaqa::TypeErasedProblem<config_t>;
134 using CsProblem = alpaqa::CasADiProblem<config_t>;
136 LoadedProblem problem{
137 .problem =
138 TEProblem::make<CntProblem>(std::in_place, full_path.c_str()),
139 .abs_path = fs::absolute(full_path),
140 .path = full_path,
141 };
142 lck.unlock();
143 auto &cnt_problem = problem.problem.as<CntProblem>();
144 auto &cs_problem = cnt_problem.problem;
145 problem.evaluations = cnt_problem.evaluations;
146 auto param_size = cs_problem.param.size();
147 alpaqa::params::set_params(cs_problem.param, "param", prob_opts);
148 if (cs_problem.param.size() != param_size)
150 "Incorrect problem parameter size: got " +
151 std::to_string(cs_problem.param.size()) + ", should be " +
152 std::to_string(param_size));
153 load_initial_guess(opts, problem);
154 return problem;
155#else
156 throw std::logic_error(
157 "This version of alpaqa was compiled without CasADi support");
158#endif
159 }
160 throw std::invalid_argument("Unknown problem type '" + std::string(type) +
161 "'");
162}
std::span< const std::string_view > options() const
Definition: options.hpp:20
std::span< bool > used()
Definition: options.hpp:23
Problem definition for a CasADi problem, loaded from a DLL.
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.
Definition: dl-problem.hpp:107
T & as() &
Convert the type-erased object to the given type.
#define USING_ALPAQA_CONFIG(Conf)
Definition: config.hpp:42
void read_row(std::istream &is, Eigen::Ref< Eigen::VectorX< float > > v, char sep)
Definition: csv.hpp:34
void set_param(bool &b, ParamString s)
Definition: params.cpp:21
void set_params(T &t, std::string_view prefix, std::span< const std::string_view > options, std::optional< std::span< bool > > used=std::nullopt)
Overwrites t based on the options that start with prefix.
Definition: params.hpp:48
std::string_view key
The subkey to resolve next.
Definition: params.hpp:19
std::string_view full_key
Full key string, used for diagnostics.
Definition: params.hpp:17
std::string_view value
The value of the parameter to store.
Definition: params.hpp:21
Represents a parameter value encoded as a string in the format abc.def.key=value.
Definition: params.hpp:15
typename Conf::length_t length_t
Definition: config.hpp:62
decltype(auto) set_params(T &t, std::string_view prefix, Options &opts)
Definition: options.hpp:29
LoadedProblem load_problem(std::string_view type, const fs::path &dir, const fs::path &file, Options &opts)
Definition: problem.cpp:97
vec initial_guess_y
Unknowns.
Definition: problem.hpp:20
vec initial_guess_x
Definition: problem.hpp:19
vec initial_guess_w
Multipliers g.
Definition: problem.hpp:21
alpaqa::TypeErasedProblem< config_t > problem
Definition: problem.hpp:15
std::shared_ptr< alpaqa::EvalCounter > evaluations
Definition: problem.hpp:18
Problem wrapper that keeps track of the number of evaluations and the run time of each function.
Custom parameter parsing exception.
Definition: params.hpp:25