alpaqa 1.0.0a8
Nonconvex constrained optimization
Loading...
Searching...
No Matches
problem.cpp
Go to the documentation of this file.
6#if ALPAQA_HAVE_CASADI
8#endif
9#if ALPAQA_HAVE_CUTEST
11#endif
12
13#include <filesystem>
14#include <fstream>
15#include <mutex>
16#include <optional>
17#include <span>
18#include <stdexcept>
19#include <string>
20
21#include "options.hpp"
22#include "problem.hpp"
23
24namespace fs = std::filesystem;
25
26namespace {
27
29
30std::string get_prefix_option(std::span<const std::string_view> prob_opts) {
31 std::string prefix = "alpaqa_problem";
32 std::string_view prefix_key = "prefix=";
33 auto prefix_it = std::find_if(
34 prob_opts.rbegin(), prob_opts.rend(),
35 [&](std::string_view opt) { return opt.starts_with(prefix_key); });
36 if (prefix_it != prob_opts.rend())
37 prefix = prefix_it->substr(prefix_key.size());
38 return prefix;
39}
40
41} // namespace
42namespace {
43void load_initial_guess(Options &opts, LoadedProblem &problem) {
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} // namespace
57
58LoadedProblem load_problem(std::string_view type, const fs::path &dir,
59 const fs::path &file, Options &opts) {
61 // Isolate problem-specific options
62 std::vector<std::string_view> prob_opts;
63 std::string_view prob_prefix = "problem.";
64 auto options = opts.options();
65 auto used = opts.used();
66 for (auto opt = options.begin(); opt != options.end(); ++opt) {
67 if (opt->starts_with(prob_prefix)) {
68 prob_opts.push_back(opt->substr(prob_prefix.size()));
69 used.begin()[opt - options.begin()] = true;
70 }
71 }
72 // Load problem
73 auto full_path = dir / file;
74 if (type == "dl" || type.empty()) {
76 using DLProblem = alpaqa::dl::DLProblem;
78 auto prefix = get_prefix_option(prob_opts);
79 std::any dl_opt = std::span{prob_opts};
80 LoadedProblem problem{
81 .problem = TEProblem::make<CntProblem>(
82 std::in_place, full_path.c_str(), prefix, &dl_opt),
83 .abs_path = fs::absolute(full_path),
84 .path = full_path,
85 };
86 auto &cnt_problem = problem.problem.as<CntProblem>();
87 problem.evaluations = cnt_problem.evaluations;
88 load_initial_guess(opts, problem);
89 return problem;
90 } else if (type == "cs") {
91#if ALPAQA_HAVE_CASADI
92 static std::mutex mtx;
93 std::unique_lock lck{mtx};
95 using CsProblem = alpaqa::CasADiProblem<config_t>;
97 LoadedProblem problem{
98 .problem =
99 TEProblem::make<CntProblem>(std::in_place, full_path.c_str()),
100 .abs_path = fs::absolute(full_path),
101 .path = full_path,
102 };
103 lck.unlock();
104 auto &cnt_problem = problem.problem.as<CntProblem>();
105 auto &cs_problem = cnt_problem.problem;
106 problem.evaluations = cnt_problem.evaluations;
107 auto param_size = cs_problem.param.size();
108 alpaqa::params::set_params(cs_problem.param, "param", prob_opts);
109 if (cs_problem.param.size() != param_size)
111 "Incorrect problem parameter size: got " +
112 std::to_string(cs_problem.param.size()) + ", should be " +
113 std::to_string(param_size));
114 load_initial_guess(opts, problem);
115 return problem;
116#else
117 throw std::logic_error(
118 "This version of alpaqa was compiled without CasADi support");
119#endif
120 } else if (type == "cu") {
121#if ALPAQA_HAVE_CUTEST
122 std::string outsdif_path;
123 alpaqa::params::set_params(outsdif_path, "outsdif", prob_opts);
124 if (outsdif_path.empty())
125 outsdif_path = full_path.parent_path() / "OUTSDIF.d";
126 bool sparse = false;
127 alpaqa::params::set_params(sparse, "sparse", prob_opts);
128 static std::mutex mtx;
129 std::unique_lock lck{mtx};
130 using TEProblem = alpaqa::TypeErasedProblem<config_t>;
131 using CuProblem = alpaqa::CUTEstProblem;
133 LoadedProblem problem{
134 .problem = TEProblem::make<CntProblem>(
135 std::in_place, full_path.c_str(), outsdif_path.c_str(), sparse),
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 &cu_problem = cnt_problem.problem;
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#else
148 throw std::logic_error(
149 "This version of alpaqa was compiled without CUTEst support");
150#endif
151 }
152 throw std::invalid_argument("Unknown problem type '" + std::string(type) +
153 "'");
154}
std::span< const std::string_view > options() const
Definition: options.hpp:20
std::span< bool > used()
Definition: options.hpp:23
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.
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 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:49
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:58
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:26