uno_runtime.hpp
1 //
2 // MIT No Attribution
3 //
4 // Copyright (C) 2010-2026 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 
13 // C-REPLACE "casadi_nlpsol_prob<T1>" "struct casadi_nlpsol_prob"
14 // C-REPLACE "casadi_nlpsol_data<T1>" "struct casadi_nlpsol_data"
15 // C-REPLACE "casadi_oracle_data<T1>" "struct casadi_oracle_data"
16 // C-REPLACE "OracleCallback" "struct casadi_oracle_callback"
17 // C-REPLACE "calc_function" "casadi_oracle_call"
18 // C-REPLACE "static_cast< struct casadi_uno_data* >" "(struct casadi_uno_data*)"
19 // C-REPLACE "static_cast<uno_int>" "(uno_int) "
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 // SYMBOL "uno_prob"
28 template<typename T1>
31  const casadi_int* sp_a;
32  const casadi_int* sp_h;
33  const uno_int* jac_row;
34  const uno_int* jac_col;
35  uno_int n_jac;
36  const uno_int* hess_row;
37  const uno_int* hess_col;
38  uno_int n_hess;
39  OracleCallback nlp_f;
40  OracleCallback nlp_g;
41  OracleCallback nlp_grad_f;
42  OracleCallback nlp_jac_g;
43  OracleCallback nlp_hess_l;
44  OracleCallback fwd1_nlp_grad_l;
45  uno_objective_callback obj_cb;
46  uno_objective_gradient_callback obj_grad_cb;
47  uno_constraints_callback constr_cb;
48  uno_constraints_jacobian_callback jac_cb;
49  uno_lagrangian_hessian_callback hess_cb;
50  uno_lagrangian_hessian_operator_callback hess_prod_cb;
51 };
52 // C-REPLACE "casadi_uno_prob<T1>" "struct casadi_uno_prob"
53 
54 // SYMBOL "uno_data"
55 template<typename T1>
58  void* solver;
59  void* model;
60  const T1** arg;
61  T1** res;
62  casadi_int* iw;
63  T1* w;
65  int success;
69  uno_int iter_count;
72 };
73 // C-REPLACE "casadi_uno_data<T1>" "struct casadi_uno_data"
74 
75 // SYMBOL "uno_obj_wrapper"
76 template<typename T1>
77 uno_int casadi_uno_obj_wrapper(uno_int n, const T1* x, T1* fval, void* user_data) {
78  casadi_uno_data<T1>* d = static_cast< casadi_uno_data<T1>* >(user_data);
79  casadi_oracle_data<T1>* d_oracle = d->nlp.oracle;
80  d_oracle->arg[0] = x;
81  d_oracle->arg[1] = d->nlp.p;
82  d_oracle->res[0] = fval;
83  return calc_function(&d->prob->nlp_f, d_oracle) == 0 ? 0 : 1;
84 }
85 // C-REPLACE "casadi_uno_obj_wrapper<T1>" "casadi_uno_obj_wrapper"
86 
87 // SYMBOL "uno_obj_grad_wrapper"
88 template<typename T1>
89 uno_int casadi_uno_obj_grad_wrapper(uno_int n, const T1* x, T1* grad, void* user_data) {
90  casadi_uno_data<T1>* d = static_cast< casadi_uno_data<T1>* >(user_data);
91  casadi_oracle_data<T1>* d_oracle = d->nlp.oracle;
92  d_oracle->arg[0] = x;
93  d_oracle->arg[1] = d->nlp.p;
94  d_oracle->res[0] = grad;
95  return calc_function(&d->prob->nlp_grad_f, d_oracle) == 0 ? 0 : 1;
96 }
97 // C-REPLACE "casadi_uno_obj_grad_wrapper<T1>" "casadi_uno_obj_grad_wrapper"
98 
99 // SYMBOL "uno_constr_wrapper"
100 template<typename T1>
101 uno_int casadi_uno_constr_wrapper(uno_int n, uno_int ng, const T1* x, T1* gval, void* user_data) {
102  casadi_uno_data<T1>* d = static_cast< casadi_uno_data<T1>* >(user_data);
103  casadi_oracle_data<T1>* d_oracle = d->nlp.oracle;
104  d_oracle->arg[0] = x;
105  d_oracle->arg[1] = d->nlp.p;
106  d_oracle->res[0] = gval;
107  return calc_function(&d->prob->nlp_g, d_oracle) == 0 ? 0 : 1;
108 }
109 // C-REPLACE "casadi_uno_constr_wrapper<T1>" "casadi_uno_constr_wrapper"
110 
111 // SYMBOL "uno_jac_wrapper"
112 template<typename T1>
113 uno_int casadi_uno_jac_wrapper(uno_int n, uno_int nnz, const T1* x, T1* jvals, void* user_data) {
114  casadi_uno_data<T1>* d = static_cast< casadi_uno_data<T1>* >(user_data);
115  casadi_oracle_data<T1>* d_oracle = d->nlp.oracle;
116  d_oracle->arg[0] = x;
117  d_oracle->arg[1] = d->nlp.p;
118  d_oracle->res[0] = jvals;
119  return calc_function(&d->prob->nlp_jac_g, d_oracle) == 0 ? 0 : 1;
120 }
121 // C-REPLACE "casadi_uno_jac_wrapper<T1>" "casadi_uno_jac_wrapper"
122 
123 // SYMBOL "uno_hess_wrapper"
124 template<typename T1>
125 uno_int casadi_uno_hess_wrapper(uno_int n, uno_int ng, uno_int nnz,
126  const T1* x, T1 obj_mult, const T1* mults, T1* hvals, void* user_data) {
127  casadi_uno_data<T1>* d = static_cast< casadi_uno_data<T1>* >(user_data);
128  casadi_oracle_data<T1>* d_oracle = d->nlp.oracle;
129  d_oracle->arg[0] = x;
130  d_oracle->arg[1] = d->nlp.p;
131  d_oracle->arg[2] = &obj_mult;
132  d_oracle->arg[3] = mults;
133  d_oracle->res[0] = hvals;
134  return calc_function(&d->prob->nlp_hess_l, d_oracle) == 0 ? 0 : 1;
135 }
136 // C-REPLACE "casadi_uno_hess_wrapper<T1>" "casadi_uno_hess_wrapper"
137 
138 // SYMBOL "uno_hess_prod_wrapper"
139 template<typename T1>
140 uno_int casadi_uno_hess_prod_wrapper(uno_int n, uno_int ng, const T1* x,
141  bool evaluate_at_x, T1 obj_mult, const T1* mults, const T1* vec,
142  T1* result, void* user_data) {
143  casadi_uno_data<T1>* d = static_cast< casadi_uno_data<T1>* >(user_data);
144  casadi_oracle_data<T1>* d_oracle = d->nlp.oracle;
145  d_oracle->arg[0] = x; // x
146  d_oracle->arg[1] = d->nlp.p; // p
147  d_oracle->arg[2] = &obj_mult; // lam:f
148  d_oracle->arg[3] = mults; // lam:g
149  d_oracle->arg[4] = 0; // out:grad:gamma:x
150  d_oracle->arg[5] = vec; // fwd:x
151  d_oracle->arg[6] = 0; // fwd:p
152  d_oracle->arg[7] = 0; // fwd:lam:f
153  d_oracle->arg[8] = 0; // fwd:lam:g
154  d_oracle->res[0] = result; // fwd:grad:gamma:x
155  return calc_function(&d->prob->fwd1_nlp_grad_l, d_oracle) == 0 ? 0 : 1;
156 }
157 // C-REPLACE "casadi_uno_hess_prod_wrapper<T1>" "casadi_uno_hess_prod_wrapper"
158 
159 // SYMBOL "uno_term_cb"
160 template<typename T1>
161 uno_int casadi_uno_term_cb(uno_int n, uno_int ng, const T1* primals,
162  const T1* lower_mult, const T1* upper_mult, const T1* constr_mult,
163  T1 obj_mult, T1 inf_pr, T1 inf_du, T1 compl_res, void* user_data) {
164  return 1;
165 }
166 // C-REPLACE "casadi_uno_term_cb<T1>" "casadi_uno_term_cb"
167 
168 // SYMBOL "uno_init_mem"
169 template<typename T1>
170 int casadi_uno_init_mem(casadi_uno_data<T1>* d) {
171  d->solver = uno_create_solver();
172  uno_set_solver_callbacks(d->solver, 0, &casadi_uno_term_cb<T1>, d);
173  d->model = 0;
175  d->success = 0;
176  return 0;
177 }
178 
179 // SYMBOL "uno_init_model"
180 template<typename T1>
181 void casadi_uno_init_model(casadi_uno_data<T1>* d,
182  const T1* lb_g, const T1* ub_g) {
183  const casadi_uno_prob<T1>* p = d->prob;
184  uno_int nx = static_cast<uno_int>(p->nlp.nx);
185  uno_int ng = static_cast<uno_int>(p->nlp.ng);
186  // Variable bounds are set per-solve via uno_set_variables_*_bounds.
187  d->model = uno_create_unconstrained_model(UNO_PROBLEM_NONLINEAR, nx, UNO_ZERO_BASED_INDEXING);
188  uno_set_user_data(d->model, d);
189  uno_set_objective(d->model, UNO_MINIMIZE, p->obj_cb, p->obj_grad_cb);
190  if (ng > 0) {
191  uno_set_constraints(d->model, ng, p->constr_cb, lb_g, ub_g,
192  p->n_jac, p->jac_row, p->jac_col, p->jac_cb);
193  }
194  uno_set_lagrangian_hessian(d->model, p->n_hess, UNO_UPPER_TRIANGLE,
195  p->hess_row, p->hess_col, p->hess_cb);
196  uno_set_lagrangian_sign_convention(d->model, UNO_MULTIPLIER_POSITIVE);
197  uno_set_lagrangian_hessian_operator(d->model, p->hess_prod_cb);
198 }
199 
200 // SYMBOL "uno_free_mem"
201 template<typename T1>
202 void casadi_uno_free_mem(casadi_uno_data<T1>* d) {
203  if (d->model) uno_destroy_model(d->model);
204  if (d->solver) uno_destroy_solver(d->solver);
205  d->model = 0;
206  d->solver = 0;
207 }
208 
209 // SYMBOL "uno_set_work"
210 template<typename T1>
211 void casadi_uno_set_work(casadi_uno_data<T1>* d, const T1*** arg, T1*** res,
212  casadi_int** iw, T1** w) {
213  d->arg = *arg;
214  d->res = *res;
215  d->iw = *iw;
216  d->w = *w;
217 }
218 
219 // SYMBOL "uno_solve"
220 template<typename T1>
221 void casadi_uno_solve(casadi_uno_data<T1>* d) {
222  const casadi_uno_prob<T1>* p = d->prob;
223  casadi_nlpsol_data<T1>* d_nlp = &d->nlp;
224  uno_int nx = static_cast<uno_int>(p->nlp.nx);
225  uno_int ng = static_cast<uno_int>(p->nlp.ng);
226  casadi_int i;
227 
228  if (!d->model) {
229  // Codegen path: model wasn't built in init_mem (no p_nlp scope there);
230  // build it now using the real constraint bounds from this first call.
231  casadi_uno_init_model(d, d_nlp->lbz + nx, d_nlp->ubz + nx);
232  }
233  // Variable bounds aren't part of the (unconstrained) model -- set every solve.
234  uno_set_variables_lower_bounds(d->model, d_nlp->lbz);
235  uno_set_variables_upper_bounds(d->model, d_nlp->ubz);
236  if (ng > 0) {
237  uno_set_constraints_lower_bounds(d->model, d_nlp->lbz + nx);
238  uno_set_constraints_upper_bounds(d->model, d_nlp->ubz + nx);
239  }
240  uno_set_initial_primal_iterate(d->model, d_nlp->x0);
241 
242  uno_optimize(d->solver, d->model);
243 
244  uno_get_primal_solution(d->solver, d_nlp->z);
245  uno_get_constraint_dual_solution(d->solver, d_nlp->lam + nx);
246  for (i = 0; i < nx; ++i) {
247  // Negative sign convention: bound multipliers are added, not subtracted.
248  d_nlp->lam[i] = uno_get_lower_bound_dual_solution_component(d->solver, i)
249  + uno_get_upper_bound_dual_solution_component(d->solver, i);
250  }
251  d_nlp->objective = uno_get_solution_objective(d->solver);
252  d->primal_infeasibility = uno_get_solution_primal_feasibility(d->solver);
253  d->stationarity = uno_get_solution_stationarity(d->solver);
254  d->complementarity = uno_get_solution_complementarity(d->solver);
255  d->iter_count = uno_get_number_iterations(d->solver);
256 
257  uno_int opt = uno_get_optimization_status(d->solver);
258  uno_int sol = uno_get_solution_status(d->solver);
259  d->success = (opt == UNO_SUCCESS && sol == UNO_FEASIBLE_KKT_POINT) ? 1 : 0;
260  if (opt == UNO_EVALUATION_ERROR) d->unified_return_status = SOLVER_RET_NAN;
261  else if (opt == UNO_ITERATION_LIMIT) d->unified_return_status = SOLVER_RET_LIMITED;
262  else if (opt == UNO_TIME_LIMIT) d->unified_return_status = SOLVER_RET_LIMITED;
263  else if (opt == UNO_ALGORITHMIC_ERROR) d->unified_return_status = SOLVER_RET_EXCEPTION;
264  else if (opt == UNO_USER_TERMINATION) d->unified_return_status = SOLVER_RET_UNKNOWN;
265  else if (sol == UNO_FEASIBLE_KKT_POINT) d->unified_return_status = SOLVER_RET_SUCCESS;
266  else if (sol == UNO_FEASIBLE_FJ_POINT) d->unified_return_status = SOLVER_RET_SUCCESS;
267  else if (sol == UNO_INFEASIBLE_STATIONARY_POINT) d->unified_return_status = SOLVER_RET_INFEASIBLE;
268  else if (sol == UNO_INFEASIBLE_SMALL_STEP) d->unified_return_status = SOLVER_RET_INFEASIBLE;
269  else if (sol == UNO_FEASIBLE_SMALL_STEP) d->unified_return_status = SOLVER_RET_LIMITED;
271 }
@ SOLVER_RET_NAN
@ SOLVER_RET_INFEASIBLE
@ SOLVER_RET_LIMITED
@ SOLVER_RET_SUCCESS
@ SOLVER_RET_UNKNOWN
@ SOLVER_RET_EXCEPTION
const casadi_uno_prob< T1 > * prob
Definition: uno_runtime.hpp:57
casadi_nlpsol_data< T1 > nlp
Definition: uno_runtime.hpp:70
casadi_int * iw
Definition: uno_runtime.hpp:62
uno_int iter_count
Definition: uno_runtime.hpp:69
const T1 ** arg
Definition: uno_runtime.hpp:60
casadi_oracle_data< T1 > d_oracle
Definition: uno_runtime.hpp:71
const casadi_int * sp_a
Definition: uno_runtime.hpp:31
uno_lagrangian_hessian_operator_callback hess_prod_cb
Definition: uno_runtime.hpp:50
OracleCallback nlp_grad_f
Definition: uno_runtime.hpp:41
uno_lagrangian_hessian_callback hess_cb
Definition: uno_runtime.hpp:49
OracleCallback nlp_hess_l
Definition: uno_runtime.hpp:43
uno_constraints_callback constr_cb
Definition: uno_runtime.hpp:47
const uno_int * hess_row
Definition: uno_runtime.hpp:36
OracleCallback nlp_g
Definition: uno_runtime.hpp:40
const uno_int * hess_col
Definition: uno_runtime.hpp:37
casadi_nlpsol_prob< T1 > nlp
Definition: uno_runtime.hpp:30
const uno_int * jac_col
Definition: uno_runtime.hpp:34
uno_objective_callback obj_cb
Definition: uno_runtime.hpp:45
OracleCallback nlp_f
Definition: uno_runtime.hpp:39
const uno_int * jac_row
Definition: uno_runtime.hpp:33
OracleCallback fwd1_nlp_grad_l
Definition: uno_runtime.hpp:44
const casadi_int * sp_h
Definition: uno_runtime.hpp:32
uno_constraints_jacobian_callback jac_cb
Definition: uno_runtime.hpp:48
uno_objective_gradient_callback obj_grad_cb
Definition: uno_runtime.hpp:46
OracleCallback nlp_jac_g
Definition: uno_runtime.hpp:42