1#include <alpaqa/export.h>
6#include <guanaqo/dl-flags.hpp>
13#ifdef ALPAQA_WITH_CUTEST
22#ifndef ALPAQA_WITHOUT_MUTEX
25namespace fs = std::filesystem;
36 std::string name =
"register_alpaqa_problem";
37 std::string_view name_key =
"register=";
38 auto name_it = std::find_if(
39 prob_opts.rbegin(), prob_opts.rend(),
40 [&](std::string_view opt) { return opt.starts_with(name_key); });
41 if (name_it != prob_opts.rend())
42 name = name_it->substr(name_key.size());
48 guanaqo::DynamicLoadFlags flags;
49 set_params(flags,
"dl_flags", opts);
58 set_params(x0,
"x0", opts);
61 set_params(y0,
"mul_g0", opts);
64 set_params(w0,
"mul_x0", opts);
70 const auto n = C.
lower.size();
75 for (index_t i = 0; i < n; ++i) {
109 std::span<std::string_view> prob_opts,
114 auto register_name = get_reg_name_option(prob_opts);
115 auto flags = get_dl_flags(opts);
117 .problem = TEProblem::make<CntProblem>(std::in_place, full_path,
118 register_name, prob_opts, flags),
119 .abs_path = fs::absolute(full_path),
122 auto &cnt_problem = problem.
problem.as<CntProblem>();
123 problem.
name = cnt_problem.problem.get_name();
131#if ALPAQA_WITH_CASADI
132template <
bool = true>
133LoadedProblem load_cs_problem(
const fs::path &full_path,
134 std::span<std::string_view> prob_opts,
135 alpaqa::Options &opts) {
136#ifndef ALPAQA_WITHOUT_MUTEX
137 static std::mutex mtx;
138 std::unique_lock lck{mtx};
140 using TEProblem = alpaqa::TypeErasedProblem<config_t>;
141 using CsProblem = alpaqa::CasADiProblem<config_t>;
142 using CntProblem = alpaqa::ProblemWithCounters<CsProblem>;
144 LoadedProblem problem{
145 .problem = TEProblem::make<CntProblem>(
146 std::in_place, full_path.string().c_str(), flags),
147 .abs_path = fs::absolute(full_path),
150#ifndef ALPAQA_WITHOUT_MUTEX
153 auto &cnt_problem = problem.
problem.as<CntProblem>();
154 auto &cs_problem = cnt_problem.problem;
155 problem.
name = cs_problem.get_name();
157 auto param_size = cs_problem.param.size();
159 if (cs_problem.param.size() != param_size)
160 throw alpaqa::params::invalid_param(
161 "Incorrect problem parameter size (expected " +
162 std::to_string(param_size) +
", but got " +
163 std::to_string(cs_problem.param.size()) +
")");
170#ifdef ALPAQA_WITH_CUTEST
171template <
bool = true>
172LoadedProblem load_cu_problem(
const fs::path &full_path,
173 std::span<std::string_view> prob_opts,
174 alpaqa::Options &opts) {
175 std::string outsdif_path;
179#ifndef ALPAQA_WITHOUT_MUTEX
180 static std::mutex mtx;
181 std::unique_lock lck{mtx};
183 using TEProblem = alpaqa::TypeErasedProblem<config_t>;
184 using CuProblem = alpaqa::CUTEstProblem;
185 using CntProblem = alpaqa::ProblemWithCounters<CuProblem>;
187 LoadedProblem problem{
189 TEProblem::make<CntProblem>(std::in_place, full_path.c_str(),
190 outsdif_path.c_str(), sparse, flags),
191 .abs_path = fs::absolute(full_path),
194#ifndef ALPAQA_WITHOUT_MUTEX
197 auto &cnt_problem = problem.
problem.as<CntProblem>();
198 auto &cu_problem = cnt_problem.problem;
199 problem.
name = cu_problem.get_name();
217 std::vector<std::string_view> prob_opts;
218 std::string_view prob_prefix =
"problem.";
220 auto used = opts.
used();
221 for (
auto opt = options.begin(); opt != options.end(); ++opt) {
222 if (opt->starts_with(prob_prefix)) {
223 prob_opts.push_back(opt->substr(prob_prefix.size()));
224 ++used.begin()[opt - options.begin()];
228 if (type ==
"dl" || type.empty()) {
230 return load_dl_problem(file, prob_opts, opts);
233 throw std::logic_error(
"This version of alpaqa was compiled without "
234 "support for dynamic problem loading");
236 }
else if (type ==
"cs") {
237#if ALPAQA_WITH_CASADI
238 if constexpr (std::is_same_v<config_t, alpaqa::EigenConfigd>)
239 return load_cs_problem(file, prob_opts, opts);
241 throw std::logic_error(
"CasADi only supports double precision.");
243 throw std::logic_error(
244 "This version of alpaqa was compiled without CasADi support");
246 }
else if (type ==
"cu") {
247#ifdef ALPAQA_WITH_CUTEST
248 if constexpr (std::is_same_v<config_t, alpaqa::EigenConfigd>)
249 return load_cu_problem(file, prob_opts, opts);
251 throw std::logic_error(
"CUTEst only supports double precision.");
253 throw std::logic_error(
254 "This version of alpaqa was compiled without CUTEst support");
257 throw std::invalid_argument(
"Unknown problem type '" + std::string(type) +
263 os <<
"Loaded problem \"" << problem.
name <<
"\"\n"
269 os <<
"Nonzeros in Jg: " << *problem.
nnz_jac_g <<
"\n";
271 os <<
"Nonzeros in ∇²L: " << *problem.
nnz_hess_L <<
"\n";
273 os <<
"Nonzeros in ∇²ψ: " << *problem.
nnz_hess_ψ <<
"\n";
275 os <<
"Box constraints:"
282 os <<
"General constraints:"
289 os <<
"Provided functions:\n";
std::span< unsigned > used()
std::span< const std::string_view > options() const
The main polymorphic minimization problem interface.
Sparsity get_lagrangian_hessian_sparsity() const
[Optional] Function that returns (a view of) the sparsity pattern of the Hessian of the Lagrangian.
const Box & get_variable_bounds() const
[Optional] Get the rectangular constraint set of the decision variables, .
length_t get_num_constraints() const
[Required] Number of constraints.
bool provides_get_lagrangian_hessian_sparsity() const
Returns true if the problem provides an implementation of get_lagrangian_hessian_sparsity.
bool provides_get_constraints_jacobian_sparsity() const
Returns true if the problem provides an implementation of get_constraints_jacobian_sparsity.
length_t get_num_variables() const
[Required] Number of decision variables.
Sparsity get_constraints_jacobian_sparsity() const
[Optional] Function that returns (a view of) the sparsity pattern of the Jacobian of the constraints.
const Box & get_general_bounds() const
[Optional] Get the rectangular constraint set of the general constraint function, .
bool provides_get_variable_bounds() const
Returns true if the problem provides an implementation of get_variable_bounds.
bool provides_get_general_bounds() const
Returns true if the problem provides an implementation of get_general_bounds.
bool provides_get_augmented_lagrangian_hessian_sparsity() const
Returns true if the problem provides an implementation of get_augmented_lagrangian_hessian_sparsity.
Sparsity get_augmented_lagrangian_hessian_sparsity() const
[Optional] Function that returns (a view of) the sparsity pattern of the Hessian of the augmented Lag...
Class that loads a problem using dlopen.
#define USING_ALPAQA_CONFIG(Conf)
void print_provided_functions(std::ostream &os, const TypeErasedProblem< Conf > &problem)
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.
std::optional< vec > value
vec initial_guess_y
Multipliers g.
PROBLEM_LOADER_EXPORT LoadedProblem load_problem(std::string_view type, const fs::path &file, Options &opts)
vec initial_guess_x
Unknowns.
vec initial_guess_w
Multipliers bounds.
std::optional< length_t > nnz_hess_L
std::optional< ConstrCount > general_constr_count
EigenConfigd DefaultConfig
std::optional< length_t > nnz_hess_ψ
alpaqa::TypeErasedProblem< config_t > problem
std::optional< ConstrCount > box_constr_count
std::optional< length_t > nnz_jac_g
PROBLEM_LOADER_EXPORT void print_problem_description(std::ostream &os, LoadedProblem &problem, bool show_funcs=true)
guanaqo::DynamicLoadFlags get_dl_flags(alpaqa::Options &opts)
vec initial_guess_y
Multipliers g.
vec initial_guess_x
Unknowns.
std::string get_reg_name_option(std::span< const std::string_view > prob_opts)
void count_problem(LoadedProblem &p)
void load_initial_guess(alpaqa::Options &opts, LoadedProblem &problem)
alpaqa::TypeErasedProblem< config_t > problem
void count_constr(alpaqa::ConstrCount &cnt, const alpaqa::Box< config_t > &C)
std::shared_ptr< alpaqa::EvalCounter > evaluations
length_t ub
Number of variables with only upper bound.
length_t eq
Number of variables with equal bounds.
length_t lb
Number of variables with only lower bound.
length_t lbub
Number of variables with both bounds.
Problem wrapper that keeps track of the number of evaluations and the run time of each function.