5#include <IpIpoptApplication.hpp>
16 Ipopt::SmartPtr<Ipopt::IpoptApplication> &solver,
17 std::ostream &os,
unsigned N_exp) {
20 Ipopt::SmartPtr<Ipopt::TNLP> nlp =
new Problem(problem.problem);
21 auto *my_nlp =
dynamic_cast<Problem *
>(GetRawPtr(nlp));
26 length_t n = problem.problem.get_n(), m = problem.problem.get_m();
29 if (
auto sz = problem.initial_guess_x.size(); sz != n)
30 throw std::invalid_argument(
31 "Invalid size for initial_guess_x (expected " + std::to_string(n) +
32 ", but got " + std::to_string(sz) +
")");
33 if (
auto sz = problem.initial_guess_y.size(); sz != m)
34 throw std::invalid_argument(
35 "Invalid size for initial_guess_y (expected " + std::to_string(m) +
36 ", but got " + std::to_string(sz) +
")");
37 my_nlp->initial_guess = problem.initial_guess_x;
38 my_nlp->initial_guess_multipliers = problem.initial_guess_y;
39 if (
auto sz = problem.initial_guess_w.size(); sz > 0) {
41 throw std::invalid_argument(
42 "Invalid size for initial_guess_w (expected " +
43 std::to_string(n * 2) +
", but got " + std::to_string(sz) +
45 my_nlp->initial_guess_bounds_multipliers_l =
46 problem.initial_guess_w.bottomRows(n);
47 my_nlp->initial_guess_bounds_multipliers_u =
48 problem.initial_guess_w.topRows(n);
52 auto t0 = std::chrono::steady_clock::now();
53 auto status = solver->OptimizeTNLP(nlp);
54 auto t1 = std::chrono::steady_clock::now();
55 auto evals = *problem.evaluations;
58 using ns = std::chrono::nanoseconds;
59 auto avg_duration = duration_cast<ns>(t1 - t0);
60 os.setstate(std::ios_base::badbit);
61 for (
unsigned i = 0; i < N_exp; ++i) {
62 my_nlp->initial_guess = problem.initial_guess_x;
63 my_nlp->initial_guess_multipliers = problem.initial_guess_y;
65 auto t0 = std::chrono::steady_clock::now();
66 solver->OptimizeTNLP(nlp);
67 auto t1 = std::chrono::steady_clock::now();
68 avg_duration += duration_cast<ns>(t1 - t0);
71 avg_duration /= (N_exp + 1);
74 auto &nlp_res = my_nlp->results;
75 if (nlp_res.status == Ipopt::SolverReturn::UNASSIGNED) {
76 nlp_res.solution_x.resize(n);
77 nlp_res.solution_y.resize(m);
81 .success = status == Ipopt::Solve_Succeeded,
83 .duration = avg_duration,
86 .δ = nlp_res.infeasibility,
87 .ε = nlp_res.nlp_error,
90 .solution = nlp_res.solution_x,
91 .multipliers = nlp_res.solution_y,
92 .multipliers_bounds =
vec(n * 2),
93 .penalties = vec::Zero(n),
94 .outer_iter = nlp_res.iter_count,
95 .inner_iter = nlp_res.iter_count,
98 if (nlp_res.status != Ipopt::SolverReturn::UNASSIGNED)
99 results.multipliers_bounds << nlp_res.solution_z_L,
100 nlp_res.solution_z_U;
104auto make_ipopt_solver(
Options &opts) {
105 using namespace Ipopt;
109 SmartPtr<IpoptApplication> app = IpoptApplicationFactory();
110 app->RethrowNonIpoptException(
true);
112 app->Options()->SetNumericValue(
"tol", 1e-8);
113 app->Options()->SetNumericValue(
"constr_viol_tol", 1e-8);
114 app->Options()->SetStringValue(
"linear_solver",
"mumps");
117 app->Options()->SetStringValue(
"hessian_approximation",
"exact");
122 ApplicationReturnStatus status = app->Initialize();
123 if (status != Solve_Succeeded)
124 throw std::runtime_error(
"Error during Ipopt initialization: " +
130template <
class LoadedProblem>
133 if (!direction.empty())
134 throw std::invalid_argument(
135 "Ipopt solver does not support any directions");
136 auto solver = make_ipopt_solver(opts);
139 return std::make_shared<SolverWrapper>(
140 [solver{std::move(solver)}, N_exp](
142 return run_ipopt_solver(problem, solver, os, N_exp);
150 static constexpr bool valid_config =
151 std::is_same_v<LoadedProblem::config_t, alpaqa::IpoptAdapter::config_t>;
152 if constexpr (valid_config)
153 return make_ipopt_drive_impl<LoadedProblem>(direction, opts);
155 throw std::invalid_argument(
156 "Ipopt solver only supports double precision");
164 throw std::invalid_argument(
165 "This version of alpaqa was compiled without Ipopt support.");
Based on https://coin-or.github.io/Ipopt/INTERFACES.html.
#define USING_ALPAQA_CONFIG(Conf)
SharedSolverWrapper make_ipopt_driver(std::string_view, Options &)
std::string_view enum_name(Ipopt::ApplicationReturnStatus s)
@ Ipopt
The stopping criterion used by Ipopt, see https://link.springer.com/article/10.1007/s10107-004-0559-y...
typename Conf::length_t length_t
decltype(auto) set_params(T &t, std::string_view prefix, Options &opts)
std::shared_ptr< SolverWrapper > SharedSolverWrapper