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(
"Invalid size for initial_guess_x (got " +
 
   31                                    std::to_string(sz) + 
", expected " +
 
   32                                    std::to_string(n) + 
")");
 
   33    if (
auto sz = problem.initial_guess_y.size(); sz != m)
 
   34        throw std::invalid_argument(
"Invalid size for initial_guess_y (got " +
 
   35                                    std::to_string(sz) + 
", expected " +
 
   36                                    std::to_string(m) + 
")");
 
   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 (got " + std::to_string(sz) +
 
   43                ", expected " + std::to_string(n * 2) + 
")");
 
   44        my_nlp->initial_guess_bounds_multipliers_l =
 
   45            problem.initial_guess_w.bottomRows(n);
 
   46        my_nlp->initial_guess_bounds_multipliers_u =
 
   47            problem.initial_guess_w.topRows(n);
 
   51    auto t0     = std::chrono::steady_clock::now();
 
   52    auto status = solver->OptimizeTNLP(nlp);
 
   53    auto t1     = std::chrono::steady_clock::now();
 
   54    auto evals  = *problem.evaluations;
 
   57    using ns          = std::chrono::nanoseconds;
 
   58    auto avg_duration = duration_cast<ns>(t1 - t0);
 
   59    os.setstate(std::ios_base::badbit);
 
   60    for (
unsigned i = 0; i < N_exp; ++i) {
 
   61        my_nlp->initial_guess             = problem.initial_guess_x;
 
   62        my_nlp->initial_guess_multipliers = problem.initial_guess_y;
 
   64        auto t0 = std::chrono::steady_clock::now();
 
   65        solver->OptimizeTNLP(nlp);
 
   66        auto t1 = std::chrono::steady_clock::now();
 
   67        avg_duration += duration_cast<ns>(t1 - t0);
 
   70    avg_duration /= (N_exp + 1);
 
   73    auto &nlp_res = my_nlp->results;
 
   74    if (nlp_res.status == Ipopt::SolverReturn::UNASSIGNED) {
 
   75        nlp_res.solution_x.resize(n);
 
   76        nlp_res.solution_y.resize(m);
 
   80        .success            = status == Ipopt::Solve_Succeeded,
 
   82        .duration           = avg_duration,
 
   85        .δ                  = nlp_res.infeasibility,
 
   86        .ε                  = nlp_res.nlp_error,
 
   89        .solution           = nlp_res.solution_x,
 
   90        .multipliers        = nlp_res.solution_y,
 
   91        .multipliers_bounds = 
vec(n * 2), 
 
   92        .penalties          = vec::Zero(n),
 
   93        .outer_iter         = nlp_res.iter_count,
 
   94        .inner_iter         = nlp_res.iter_count,
 
   97    if (nlp_res.status != Ipopt::SolverReturn::UNASSIGNED)
 
   98        results.multipliers_bounds << nlp_res.solution_z_L,
 
  103auto make_ipopt_solver(
Options &opts) {
 
  104    using namespace Ipopt;
 
  108    SmartPtr<IpoptApplication> app = IpoptApplicationFactory();
 
  109    app->RethrowNonIpoptException(
true);
 
  111    app->Options()->SetNumericValue(
"tol", 1e-8);
 
  112    app->Options()->SetNumericValue(
"constr_viol_tol", 1e-8);
 
  113    app->Options()->SetStringValue(
"linear_solver", 
"mumps");
 
  116    app->Options()->SetStringValue(
"hessian_approximation", 
"exact");
 
  121    ApplicationReturnStatus status = app->Initialize();
 
  122    if (status != Solve_Succeeded)
 
  123        throw std::runtime_error(
"Error during Ipopt initialization: " +
 
  129template <
class LoadedProblem>
 
  131    if (!direction.empty())
 
  132        throw std::invalid_argument(
 
  133            "Ipopt solver does not support any directions");
 
  134    auto solver    = make_ipopt_solver(opts);
 
  137    return [solver{std::move(solver)},
 
  140        return run_ipopt_solver(problem, solver, os, N_exp);
 
  147    static constexpr bool valid_config =
 
  148        std::is_same_v<LoadedProblem::config_t, alpaqa::IpoptAdapter::config_t>;
 
  149    if constexpr (valid_config)
 
  150        return make_ipopt_drive_impl<LoadedProblem>(direction, opts);
 
  152        throw std::invalid_argument(
 
  153            "Ipopt solver only supports double precision");
 
  161    throw std::invalid_argument(
 
  162        "This version of alpaqa was compiled without Ipopt support.");
 
Based on https://coin-or.github.io/Ipopt/INTERFACES.html.
 
#define USING_ALPAQA_CONFIG(Conf)
 
solver_func_t 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::function< solver_free_func_t > solver_func_t