alpaqa pantr
Nonconvex constrained optimization
Loading...
Searching...
No Matches
ipopt-adapter.cpp
Go to the documentation of this file.
2
3#include <IpIpoptCalculatedQuantities.hpp>
4
5namespace alpaqa {
6
7IpoptAdapter::IpoptAdapter(const Problem &problem) : problem(problem) {
8 const length_t n = problem.get_n();
10 sparsity_H.inner_idx.resize(nnz_H);
11 sparsity_H.outer_ptr.resize(n + 1);
12 mvec null{nullptr, 0};
14 sparsity_H.outer_ptr, null);
15 }
17 sparsity_J.inner_idx.resize(nnz_J);
18 sparsity_J.outer_ptr.resize(n + 1);
19 mvec null{nullptr, 0};
21 null);
22 }
23}
24
26 Index &nnz_h_lag, IndexStyleEnum &index_style) {
27 n = static_cast<Index>(problem.get_n());
28 m = static_cast<Index>(problem.get_m());
29 nnz_jac_g = static_cast<Index>(sparsity_J.inner_idx.size());
30 if (nnz_jac_g == 0)
31 nnz_jac_g = n * m;
32 nnz_h_lag = static_cast<Index>(sparsity_H.inner_idx.size());
33 if (nnz_h_lag == 0)
34 nnz_h_lag = n * n;
35 // use the C style indexing (0-based)
36 index_style = TNLP::C_STYLE;
37 return true;
38}
39
41 Number *g_l, Number *g_u) {
42 const auto &C = problem.get_box_C();
43 mvec{x_l, n} = C.lowerbound;
44 mvec{x_u, n} = C.upperbound;
45 const auto &D = problem.get_box_D();
46 mvec{g_l, m} = D.lowerbound;
47 mvec{g_u, m} = D.upperbound;
48 return true;
49}
50
52 bool init_z, Number *z_L, Number *z_U,
53 Index m, bool init_lambda,
54 Number *lambda) {
55 if (init_x) {
56 if (initial_guess.size() > 0)
57 mvec{x, n} = initial_guess;
58 else
59 mvec{x, n}.setZero();
60 }
61 if (init_z) {
64 else
65 mvec{z_L, n}.setZero();
68 else
69 mvec{z_U, n}.setZero();
70 }
71 if (init_lambda) {
72 if (initial_guess_multipliers.size() > 0)
74 else
75 mvec{lambda, m}.setZero();
76 }
77 return true;
78}
79
80bool IpoptAdapter::eval_f(Index n, const Number *x, [[maybe_unused]] bool new_x,
81 Number &obj_value) {
82 obj_value = problem.eval_f(cmvec{x, n});
83 return true;
84}
85
87 [[maybe_unused]] bool new_x, Number *grad_f) {
88 problem.eval_grad_f(cmvec{x, n}, mvec{grad_f, n});
89 return true;
90}
91
92bool IpoptAdapter::eval_g(Index n, const Number *x, [[maybe_unused]] bool new_x,
93 Index m, Number *g) {
94 problem.eval_g(cmvec{x, n}, mvec{g, m});
95 return true;
96}
97
99 [[maybe_unused]] bool new_x, Index m,
100 Index nele_jac, Index *iRow, Index *jCol,
101 Number *values) {
103 throw std::logic_error("Missing required function: eval_jac_g");
104 if (values == nullptr) // Initialize sparsity
105 set_sparsity(n, m, nele_jac, iRow, jCol, sparsity_J);
106 else // Evaluate values
108 sparsity_J.outer_ptr, mvec{values, nele_jac});
109 return true;
110}
111
112bool IpoptAdapter::eval_h(Index n, const Number *x, [[maybe_unused]] bool new_x,
113 Number obj_factor, Index m, const Number *lambda,
114 [[maybe_unused]] bool new_lambda, Index nele_hess,
115 Index *iRow, Index *jCol, Number *values) {
117 throw std::logic_error("Missing required function: eval_hess_L");
118 // Initialize sparsity
119 if (values == nullptr) {
120 set_sparsity(n, n, nele_hess, iRow, jCol, sparsity_H);
121 }
122 // Evaluate values
123 else {
124 problem.eval_hess_L(cmvec{x, n}, cmvec{lambda, m}, obj_factor,
126 mvec{values, nele_hess});
127 // For dense matrices, set lower triangle to zero
128 // TODO: make this more efficient in alpaqa problem interface
129 if (sparsity_H.inner_idx.size() == 0) {
130 mmat H{values, n, n};
131 for (Index c = 0; c < n; ++c)
132 for (Index r = c + 1; r < n; ++r)
133 H(r, c) = 0;
134 }
135 }
136 return true;
137}
138void IpoptAdapter::finalize_solution(Ipopt::SolverReturn status, Index n,
139 const Number *x, const Number *z_L,
140 const Number *z_U, Index m,
141 const Number *g, const Number *lambda,
142 Number obj_value,
143 const Ipopt::IpoptData *ip_data,
144 Ipopt::IpoptCalculatedQuantities *ip_cq) {
145 results.status = status;
146 results.solution_x = cmvec{x, n};
147 results.solution_z_L = cmvec{z_L, n};
148 results.solution_z_U = cmvec{z_U, n};
149 results.solution_y = cmvec{lambda, m};
150 results.solution_g = cmvec{g, m};
151 results.solution_f = obj_value;
152 results.infeasibility = ip_cq->curr_constraint_violation();
153 results.nlp_error = ip_cq->unscaled_curr_nlp_error();
154 results.iter_count = ip_data->iter_count();
155}
156
157void IpoptAdapter::set_sparsity(Index n, Index m, [[maybe_unused]] Index nele,
158 Index *iRow, Index *jCol, const Sparsity &sp) {
159 // sparse
160 if (sp.inner_idx.size() > 0) {
161 Index l = 0; // column major, jacobian is m×n, hessian is n×n
162 for (Index c = 0; c < n; ++c) {
163 auto inner_start = static_cast<Index>(sp.outer_ptr(c));
164 auto inner_end = static_cast<Index>(sp.outer_ptr(c + 1));
165 for (Index i = inner_start; i < inner_end; ++i) {
166 assert(l < nele);
167 jCol[l] = c;
168 iRow[l] = static_cast<Index>(sp.inner_idx(i));
169 ++l;
170 }
171 }
172 assert(l == nele);
173 }
174 // dense
175 else {
176 Index l = 0; // column major, jacobian is m×n, hessian is n×n
177 for (Index c = 0; c < n; ++c) {
178 for (Index r = 0; r < m; ++r) {
179 assert(l < nele);
180 iRow[l] = r;
181 jCol[l] = c;
182 ++l;
183 }
184 }
185 assert(l == nele);
186 }
187}
188
189} // namespace alpaqa
IpoptAdapter(const Problem &problem)
Ipopt::Number Number
static void set_sparsity(Index n, Index m, Index nele, Index *iRow, Index *jCol, const Sparsity &sp)
const Problem & problem
bool eval_g(Index n, const Number *x, bool new_x, Index m, Number *g) override
bool eval_grad_f(Index n, const Number *x, bool new_x, Number *grad_f) override
bool eval_h(Index n, const Number *x, bool new_x, Number obj_factor, Index m, const Number *lambda, bool new_lambda, Index nele_hess, Index *iRow, Index *jCol, Number *values) override
bool get_starting_point(Index n, bool init_x, Number *x, bool init_z, Number *z_L, Number *z_U, Index m, bool init_lambda, Number *lambda) override
bool get_bounds_info(Index n, Number *x_l, Number *x_u, Index m, Number *g_l, Number *g_u) override
struct alpaqa::IpoptAdapter::Results results
struct alpaqa::IpoptAdapter::Sparsity sparsity_J
bool eval_f(Index n, const Number *x, bool new_x, Number &obj_value) override
bool get_nlp_info(Index &n, Index &m, Index &nnz_jac_g, Index &nnz_h_lag, IndexStyleEnum &index_style) override
bool eval_jac_g(Index n, const Number *x, bool new_x, Index m, Index nele_jac, Index *iRow, Index *jCol, Number *values) override
Ipopt::SolverReturn status
void finalize_solution(Ipopt::SolverReturn status, Index n, const Number *x, const Number *z_L, const Number *z_U, Index m, const Number *g, const Number *lambda, Number obj_value, const Ipopt::IpoptData *ip_data, Ipopt::IpoptCalculatedQuantities *ip_cq) override
struct alpaqa::IpoptAdapter::Sparsity sparsity_H
bool provides_eval_hess_L() const
Returns true if the problem provides an implementation of eval_hess_L.
const Box & get_box_D() const
[Optional] Get the rectangular constraint set of the general constraint function, .
bool provides_eval_jac_g() const
Returns true if the problem provides an implementation of eval_jac_g.
length_t get_n() const
[Required] Number of decision variables.
length_t get_m() const
[Required] Number of constraints.
void eval_hess_L(crvec x, crvec y, real_t scale, rindexvec inner_idx, rindexvec outer_ptr, rvec H_values) const
[Optional] Function that evaluates the Hessian of the Lagrangian as a sparse matrix,
void eval_grad_f(crvec x, rvec grad_fx) const
[Required] Function that evaluates the gradient of the cost,
real_t eval_f(crvec x) const
[Required] Function that evaluates the cost,
void eval_g(crvec x, rvec gx) const
[Required] Function that evaluates the constraints,
length_t get_jac_g_num_nonzeros() const
[Optional] Function that gets the number of nonzeros of the Jacobian of the constraints.
const Box & get_box_C() const
[Optional] Get the rectangular constraint set of the decision variables, .
void eval_jac_g(crvec x, rindexvec inner_idx, rindexvec outer_ptr, rvec J_values) const
[Optional] Function that evaluates the Jacobian of the constraints as a sparse matrix,
length_t get_hess_L_num_nonzeros() const
[Optional] Function that gets the number of nonzeros of the Hessian of the Lagrangian.
typename Conf::mvec mvec
Definition: config.hpp:53
typename Conf::mmat mmat
Definition: config.hpp:58
typename Conf::length_t length_t
Definition: config.hpp:62
typename Conf::cmvec cmvec
Definition: config.hpp:54
vec lowerbound
Definition: box.hpp:25