ccopt_runtime.hpp
1 //
2 // MIT No Attribution
3 //
4 // Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl, KU Leuven.
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy of this
7 // software and associated documentation files (the "Software"), to deal in the Software
8 // without restriction, including without limitation the rights to use, copy, modify,
9 // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13 // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
16 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
17 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 //
19 
20 // C-REPLACE "SOLVER_RET_SUCCESS" "0"
21 // C-REPLACE "SOLVER_RET_UNKNOWN" "1"
22 // C-REPLACE "SOLVER_RET_LIMITED" "2"
23 // C-REPLACE "SOLVER_RET_NAN" "3"
24 // C-REPLACE "SOLVER_RET_INFEASIBLE" "4"
25 // C-REPLACE "SOLVER_RET_EXCEPTION" "5"
26 
27 // C-REPLACE "casadi_nlpsol_prob<T1>" "struct casadi_nlpsol_prob"
28 // C-REPLACE "casadi_nlpsol_data<T1>" "struct casadi_nlpsol_data"
29 
30 // C-REPLACE "reinterpret_cast<int**>" "(int**) "
31 // C-REPLACE "reinterpret_cast<int*>" "(int*) "
32 // C-REPLACE "const_cast<int*>" "(int*) "
33 
34 // C-REPLACE "OracleCallback" "struct casadi_oracle_callback"
35 // C-REPLACE "nullptr" "0"
36 
37 // SYMBOL "ccopt_prob"
38 template<typename T1>
41 
42  // Sparsity patterns
43  const casadi_int *sp_h, *sp_a;
44 
45  casadi_int nnz_hess_l, nnz_jac_g, ncc;
46 
47  OracleCallback nlp_hess_l;
48  OracleCallback nlp_jac_g;
49  OracleCallback nlp_grad_f;
50  OracleCallback nlp_f;
51  OracleCallback nlp_g;
52 };
53 // C-REPLACE "casadi_ccopt_prob<T1>" "struct casadi_ccopt_prob"
54 
55 // SYMBOL "ccopt_data"
56 template<typename T1>
58  // Problem structure
60  // Problem structure
62 
63  const T1** arg;
64  T1** res;
65  casadi_int* iw;
66  T1 *w;
67 
68  // temporary data
69  T1 *x, *lam_g, *g, *f, *jac_g, *grad_f, *hess_l, *grad_l;
70 
72  int success;
73 
74  // complementarities, 1 indexed
75  const libmad_int *ind_cc1, *ind_cc2;
76  const libmad_int *cctypes;
77  libmad_int ncc;
78 
79  CMPCCModel* mpcc_model;
80  CNLPModel* nlp_model;
81  OptsDict* nlp_opts;
82  OptsDict* mpcc_opts;
83  CCOptExecutionStats* stats;
84  RelaxationSolver* solver;
85 };
86 // C-REPLACE "casadi_ccopt_data<T1>" "struct casadi_ccopt_data"
87 
88 // SYMBOL "ccopt_setup"
89 template<typename T1>
90 void casadi_ccopt_setup(casadi_ccopt_prob<T1>* p) {
91  if (p->sp_h) {
92  p->nnz_hess_l = p->sp_h[2+p->sp_h[1]];
93  } else {
94  p->nnz_hess_l = 0;
95  }
96  p->nnz_jac_g = p->sp_a[2+p->sp_a[1]];
97 }
98 
99 // C-REPLACE "static_cast< casadi_ccopt_data<T1>* >" "(struct casadi_ccopt_data*)"
100 // C-REPLACE "casadi_oracle_data<T1>" "struct casadi_oracle_data"
101 // C-REPLACE "calc_function" "casadi_oracle_call"
102 // C-REPLACE "casadi_error" "//casadi_error"
103 
104 // SYMBOL "ccopt_constr_jac_structure"
105 template<typename T1>
106 int casadi_ccopt_constr_jac_structure(libmad_int* I, libmad_int* J, void* user_data)
107 {
108  casadi_int cc, el;
109  const casadi_int *colind, *row;
110  casadi_ccopt_data<T1>* d = static_cast< casadi_ccopt_data<T1>* >(user_data);
111  const casadi_ccopt_prob<T1>* p = d->prob;
112 
113  // convert ccs to cco
114  casadi_int ncol = p->sp_a[1];
115  colind = p->sp_a+2;
116  row = colind+ncol+1;
117 
118  for (cc=0; cc<ncol; ++cc) {
119  for (el=colind[cc]; el<colind[cc+1]; ++el) {
120  *I++ = row[el]+1;
121  *J++ = cc+1;
122  }
123  }
124  return 0;
125 }
126 // C-REPLACE "casadi_ccopt_constr_jac_structure<T1>" "casadi_ccopt_constr_jac_structure"
127 
128 // SYMBOL "ccopt_lag_hess_structure"
129 template<typename T1>
130 int casadi_ccopt_lag_hess_structure(libmad_int* I, libmad_int* J, void* user_data)
131 {
132  casadi_int cc, el;
133  const casadi_int *colind, *row;
134  casadi_ccopt_data<T1>* d = static_cast< casadi_ccopt_data<T1>* >(user_data);
135  const casadi_ccopt_prob<T1>* p = d->prob;
136 
137  // convert ccs to cco
138  casadi_int ncol = p->sp_h[1];
139  colind = p->sp_h+2;
140  row = colind+ncol+1;
141 
142  for (cc=0; cc<ncol; ++cc) {
143  for (el=colind[cc]; el<colind[cc+1]; ++el) {
144  *I++ = row[el]+1;
145  *J++ = cc+1;
146  }
147  }
148  return 0;
149 }
150 // C-REPLACE "casadi_ccopt_lag_hess_structure<T1>" "casadi_ccopt_lag_hess_structure"
151 
152 // SYMBOL "ccopt_eval_constr_jac"
153 template<typename T1>
154 int casadi_ccopt_eval_constr_jac(const T1* w, T1* res, void* user_data) {
155  casadi_ccopt_data<T1>* d = static_cast< casadi_ccopt_data<T1>* >(user_data);
156  casadi_nlpsol_data<T1>* d_nlp = d->nlp;
157  casadi_oracle_data<T1>* d_oracle = d_nlp->oracle;
158 
159  d_oracle->arg[0] = w;
160  d_oracle->arg[1] = d_nlp->p;
161  d_oracle->res[0] = res;
162 
163  return calc_function(&d->prob->nlp_jac_g, d_oracle);
164 }
165 
166 // SYMBOL "ccopt_eval_constr"
167 template<typename T1>
168 int casadi_ccopt_eval_constr(const T1* w, T1* res, void* user_data) {
169  casadi_ccopt_data<T1>* d = static_cast< casadi_ccopt_data<T1>* >(user_data);
170  casadi_nlpsol_data<T1>* d_nlp = d->nlp;
171  casadi_oracle_data<T1>* d_oracle = d_nlp->oracle;
172 
173  d_oracle->arg[0] = w;
174  d_oracle->arg[1] = d_nlp->p;
175  d_oracle->res[0] = res;
176 
177  return calc_function(&d->prob->nlp_g, d_oracle);
178 }
179 
180 // SYMBOL "ccopt_eval_obj_grad"
181 template<typename T1>
182 int casadi_ccopt_eval_obj_grad(const T1* w, T1* res, void* user_data) {
183  casadi_ccopt_data<T1>* d = static_cast< casadi_ccopt_data<T1>* >(user_data);
184  casadi_nlpsol_data<T1>* d_nlp = d->nlp;
185  casadi_oracle_data<T1>* d_oracle = d_nlp->oracle;
186 
187  // TODO add argument
188  //T1 objective_scale = 1.0;
189 
190  d_oracle->arg[0] = w;
191  d_oracle->arg[1] = d_nlp->p;
192  d_oracle->res[0] = res;
193  return calc_function(&d->prob->nlp_grad_f, d_oracle);
194 }
195 
196 // SYMBOL "ccopt_eval_obj"
197 template<typename T1>
198 int casadi_ccopt_eval_obj(const T1* w, T1* res, void* user_data) {
199  casadi_ccopt_data<T1>* d = static_cast< casadi_ccopt_data<T1>* >(user_data);
200  casadi_nlpsol_data<T1>* d_nlp = d->nlp;
201  casadi_oracle_data<T1>* d_oracle = d_nlp->oracle;
202 
203  // TODO add argument
204  //T1 objective_scale = 1.0;
205 
206  d_oracle->arg[0] = w;
207  d_oracle->arg[1] = d_nlp->p;
208  d_oracle->res[0] = res;
209  return calc_function(&d->prob->nlp_f, d_oracle);
210 }
211 
212 // SYMBOL "ccopt_eval_lag_hess"
213 template<typename T1>
214 int casadi_ccopt_eval_lag_hess(T1 objective_scale, const T1* w, const T1* lam,
215  T1* res, void* user_data){
216  casadi_ccopt_data<T1>* d = static_cast< casadi_ccopt_data<T1>* >(user_data);
217  casadi_nlpsol_data<T1>* d_nlp = d->nlp;
218  casadi_oracle_data<T1>* d_oracle = d_nlp->oracle;
219 
220  // evaluate hessian with given parameters / inputs
221  d_oracle->arg[0] = w;
222  d_oracle->arg[1] = d_nlp->p;
223  d_oracle->arg[2] = &objective_scale;
224  d_oracle->arg[3] = lam;
225  d_oracle->res[0] = res;
226 
227  return calc_function(&d->prob->nlp_hess_l, d_oracle);
228 }
229 
230 // C-REPLACE "const_cast<T1*>" "(T1*)"
231 
232 // C-REPLACE "casadi_ccopt_eval_constr_jac<T1>" "casadi_ccopt_eval_constr_jac"
233 // C-REPLACE "casadi_ccopt_eval_obj_grad<T1>" "casadi_ccopt_eval_obj_grad"
234 // C-REPLACE "casadi_ccopt_eval_obj<T1>" "casadi_ccopt_eval_obj"
235 // C-REPLACE "casadi_ccopt_eval_constr<T1>" "casadi_ccopt_eval_constr"
236 // C-REPLACE "casadi_ccopt_eval_lag_hess<T1>" "casadi_ccopt_eval_lag_hess"
237 // C-REPLACE "std::numeric_limits<T1>::infinity()" "casadi_inf"
238 
239 // SYMBOL "ccopt_init_mem"
240 template<typename T1>
241 int casadi_ccopt_init_mem(casadi_ccopt_data<T1>* d) {
242  // Problem structure
243 
244  return 0;
245 }
246 
247 // SYMBOL "ccopt_free_mem"
248 template<typename T1>
249 void casadi_ccopt_free_mem(casadi_ccopt_data<T1>* d) {
250  ccopt_relaxation_delete_solver(d->solver);
251  d->solver = nullptr;
252  ccopt_relaxation_delete_stats(d->stats);
253  d->stats = nullptr;
254  libmad_delete_options_dict(d->nlp_opts);
255  libmad_delete_options_dict(d->mpcc_opts);
256 }
257 
258 // SYMBOL "ccopt_work"
259 template<typename T1>
260 void casadi_ccopt_work(const casadi_ccopt_prob<T1>* p, casadi_int* sz_arg, casadi_int* sz_res, casadi_int* sz_iw, casadi_int* sz_w) {
261  casadi_nlpsol_work(p->nlp, sz_arg, sz_res, sz_iw, sz_w);
262 
263  // Temporary work vectors
264  *sz_w = casadi_max(*sz_w, 2*(p->nlp->nx+p->nlp->ng)); // pv
265 }
266 
267 // SYMBOL "ccopt_set_work"
268 template<typename T1>
269 void casadi_ccopt_set_work(casadi_ccopt_data<T1>* d, const T1*** arg, T1*** res, casadi_int** iw, T1** w) {
270  // Problem structure
271  d->arg = *arg;
272  d->res = *res;
273  d->iw = *iw;
274  d->w = *w;
275 }
276 
277 // SYMBOL "ccopt_presolve"
278 template<typename T1>
279 int casadi_ccopt_presolve(casadi_ccopt_data<T1>* d) {
280  int ret = 0;
281  const casadi_ccopt_prob<T1>* p = d->prob;
282  const casadi_nlpsol_prob<T1>* p_nlp = p->nlp;
283  casadi_nlpsol_data<T1>* d_nlp = d->nlp;
285  d->success = 0;
286 
287  ret = libmad_nlpmodel_create(&(d->nlp_model),
288  "MadMPEC",
289  p_nlp->nx, p_nlp->ng,
290  p->nnz_jac_g, p->nnz_hess_l,
291  casadi_ccopt_constr_jac_structure<T1>,
292  casadi_ccopt_lag_hess_structure<T1>,
293  casadi_ccopt_eval_obj<T1>,
294  casadi_ccopt_eval_constr<T1>,
295  casadi_ccopt_eval_obj_grad<T1>,
296  casadi_ccopt_eval_constr_jac<T1>,
297  casadi_ccopt_eval_lag_hess<T1>,
298  d
299  );
300  if(ret) return ret; // TODO(@anton) think about what we need to clean up.
301 
302  // set initial guess
303  ret = libmad_nlpmodel_set_numerics(d->nlp_model,
304  d_nlp->z, d_nlp->lam + p_nlp->nx,
305  d_nlp->lbx, d_nlp->ubx,
306  d_nlp->lbg, d_nlp->ubg);
307  if(ret) return ret; // TODO(@anton) think about what we need to clean up.
308 
309  ret = libmad_mpccmodel_create(&(d->mpcc_model),
310  d->nlp_model,
311  d->ncc,
312  d->ind_cc1, d->ind_cc2,
313  d->cctypes
314  );
315  if(ret) return ret; // TODO(@anton) think about what we need to clean up.
316 
317  ret = ccopt_relaxation_create_solver(&(d->solver), d->mpcc_model, d->nlp_opts, d->mpcc_opts);
318 
319  return ret;
320 }
321 
322 // SYMBOL "ccopt_solve"
323 template<typename T1>
324 int casadi_ccopt_solve(casadi_ccopt_data<T1>* d) {
325  // Problem structure
326  casadi_nlpsol_data<T1>* d_nlp = d->nlp;
327  const casadi_ccopt_prob<T1>* p = d->prob;
328  const casadi_nlpsol_prob<T1>* p_nlp = p->nlp;
329  int ret = ccopt_relaxation_solve(d->solver, d->nlp_opts, &(d->stats));
330  if (ret!=0) {
331  // cleanup done in free_mem
332  return ret;
333  }
334  // get objective
335  ccopt_relaxation_get_obj(d->stats, &(d_nlp->objective));
336  // get primal solution for x
337  ccopt_relaxation_get_solution(d->stats, d_nlp->z);
338  // get the bound multipliers
339  ccopt_relaxation_get_bound_multipliers(d->stats, d_nlp->lam);
340  // get the nonlinear constraint function values
341  ccopt_relaxation_get_constraints(d->stats, d_nlp->z + p_nlp->nx);
342  // get the nonlinear constraint multipliers
343  ccopt_relaxation_get_multipliers(d->stats, d_nlp->lam + p_nlp->nx);
344 
345  bool success_b;
346  ccopt_relaxation_get_success(d->stats, &(success_b));
347  if(success_b){
348  d->success = 1;
349  }
350 
351  if(d->success) {
353  } else {
355  }
356 
357 
358  return 0;
359 }
@ SOLVER_RET_LIMITED
@ SOLVER_RET_SUCCESS
@ SOLVER_RET_UNKNOWN
CMPCCModel * mpcc_model
const casadi_ccopt_prob< T1 > * prob
CNLPModel * nlp_model
const libmad_int * cctypes
casadi_nlpsol_data< T1 > * nlp
OptsDict * mpcc_opts
RelaxationSolver * solver
const libmad_int * ind_cc2
CCOptExecutionStats * stats
const libmad_int * ind_cc1
const casadi_int * sp_h
OracleCallback nlp_grad_f
OracleCallback nlp_jac_g
casadi_int nnz_jac_g
casadi_int nnz_hess_l
OracleCallback nlp_g
OracleCallback nlp_hess_l
OracleCallback nlp_f
const casadi_int * sp_a
const casadi_nlpsol_prob< T1 > * nlp