sleqp_func.cpp
1 #include "sleqp_func.hpp"
2 
3 #include <sleqp.h>
4 
5 #include "sleqp_interface.hpp"
6 
7 namespace casadi {
8 
9  static SLEQP_RETCODE casadi_func_set(SleqpFunc* func,
10  SleqpVec* value,
11  SLEQP_VALUE_REASON reason,
12  bool* reject,
13  void* func_data)
14  {
15  SLEQPMemory* m = static_cast<SLEQPMemory*>(func_data);
16 
17  SLEQP_CALL(sleqp_vec_to_raw(value, m->xk));
18 
19  return SLEQP_OKAY;
20  }
21 
22  static SLEQP_RETCODE casadi_func_nonzeros(SleqpFunc* func,
23  int* obj_grad_nnz,
24  int* cons_val_nnz,
25  int* cons_jac_nnz,
26  int* hess_prod_nnz,
27  void* func_data)
28  {
29  SLEQPMemory* m = static_cast<SLEQPMemory*>(func_data);
30  return SLEQP_OKAY;
31  }
32 
33  static SLEQP_RETCODE casadi_func_obj_val(SleqpFunc* func,
34  double* obj_val,
35  void* func_data)
36  {
37  SLEQPMemory* m = static_cast<SLEQPMemory*>(func_data);
38 
39  m->arg[0] = m->xk;
40  m->arg[1] = m->d_nlp.p;
41  m->res[0] = obj_val;
42 
43  try {
44 
45  if(m->interface->calc_function(m, "nlp_f") == 0) {
46  return SLEQP_OKAY;
47  }
48 
49  } catch (std::exception& ex) {
50  uerr() << "Error \""
51  << ex.what()
52  << "\" evaluating objective value"
53  << std::endl;
54 
55  sleqp_raise(SLEQP_FUNC_EVAL_ERROR, "%s", ex.what());
56  }
57 
58  return SLEQP_ERROR;
59  }
60 
61  static SLEQP_RETCODE casadi_func_obj_grad(SleqpFunc* func,
62  SleqpVec* obj_grad,
63  void* func_data)
64  {
65  SLEQPMemory* m = static_cast<SLEQPMemory*>(func_data);
66 
67  m->arg[0] = m->xk;
68  m->arg[1] = m->d_nlp.p;
69  m->res[0] = nullptr;
70  m->res[1] = m->grad_fk;
71 
72  try {
73 
74  if(m->interface->calc_function(m, "nlp_grad_f") != 0) {
75  return SLEQP_ERROR;
76  }
77 
78  const int num_vars = sleqp_func_num_vars(func);
79 
80  SLEQP_CALL(sleqp_vec_set_from_raw(obj_grad,
81  m->grad_fk,
82  num_vars,
83  0.));
84 
85  } catch (std::exception& ex) {
86  uerr() << "Error \""
87  << ex.what()
88  << "\" evaluating objective gradient"
89  << std::endl;
90 
91  sleqp_raise(SLEQP_FUNC_EVAL_ERROR, "%s", ex.what());
92  }
93 
94  return SLEQP_OKAY;
95  }
96 
97  static SLEQP_RETCODE casadi_func_cons_val(SleqpFunc* func,
98  SleqpVec* cons_val,
99  void* func_data)
100  {
101  SLEQPMemory* m = static_cast<SLEQPMemory*>(func_data);
102 
103  m->arg[0] = m->xk;
104  m->arg[1] = m->d_nlp.p;
105  m->res[0] = m->gk;
106 
107  try {
108 
109  if(m->interface->calc_function(m, "nlp_g") != 0) {
110  return SLEQP_ERROR;
111  }
112 
113  const int num_cons = sleqp_func_num_cons(func);
114 
115  SLEQP_CALL(sleqp_vec_set_from_raw(cons_val,
116  m->gk,
117  num_cons,
118  0.));
119 
120  } catch (std::exception& ex) {
121  uerr() << "Error \""
122  << ex.what()
123  << "\" evaluating constraint value"
124  << std::endl;
125 
126  sleqp_raise(SLEQP_FUNC_EVAL_ERROR, "%s", ex.what());
127  }
128 
129  return SLEQP_OKAY;
130  }
131 
132  static SLEQP_RETCODE casadi_func_cons_jac(SleqpFunc* func,
133  SleqpMat* cons_jac,
134  void* func_data)
135  {
136  SLEQPMemory* m = static_cast<SLEQPMemory*>(func_data);
137 
138  m->arg[0] = m->xk;
139  m->arg[1] = m->d_nlp.p;
140  m->res[0] = nullptr;
141  m->res[1] = m->jac_gk;
142 
143  try {
144 
145  if(m->interface->calc_function(m, "nlp_jac_g") != 0) {
146  return SLEQP_ERROR;
147  }
148 
149  } catch (std::exception& ex) {
150  uerr() << "Error \""
151  << ex.what()
152  << "\" evaluating constraint Jacobian"
153  << std::endl;
154 
155  sleqp_raise(SLEQP_FUNC_EVAL_ERROR, "%s", ex.what());
156  }
157 
158  casadi_int ncol = m->interface->jac_sparsity().size2();
159  const casadi_int* colind = m->interface->jac_sparsity().colind();
160  const casadi_int* row = m->interface->jac_sparsity().row();
161 
162  const casadi_int nnz = colind[ncol];
163 
164  SLEQP_CALL(sleqp_mat_reserve(cons_jac, nnz));
165 
166  double* cons_jac_data = sleqp_mat_data(cons_jac);
167  int* cons_jac_rows = sleqp_mat_rows(cons_jac);
168  int* cons_jac_cols = sleqp_mat_cols(cons_jac);
169 
170  for(int k = 0; k < nnz; ++k) {
171  cons_jac_data[k] = m->jac_gk[k];
172  cons_jac_rows[k] = row[k];
173  }
174 
175  for(int k = 0; k <= ncol; ++k) {
176  cons_jac_cols[k] = colind[k];
177  }
178 
179  SLEQP_CALL(sleqp_mat_set_nnz(cons_jac, nnz));
180 
181  return SLEQP_OKAY;
182  }
183 
184  static SLEQP_RETCODE casadi_func_hess_prod(SleqpFunc* func,
185  const SleqpVec* direction,
186  const SleqpVec* cons_duals,
187  SleqpVec* product,
188  void* func_data)
189  {
190  SLEQPMemory* m = static_cast<SLEQPMemory*>(func_data);
191 
192  SLEQP_CALL(sleqp_vec_to_raw(direction, m->h_dk));
193  SLEQP_CALL(sleqp_vec_to_raw(cons_duals, m->h_mk));
194 
195  double one = 1.;
196 
197  m->arg[0] = m->xk; // x
198  m->arg[1] = m->d_nlp.p; // p
199  m->arg[2] = &one; // lam:f
200  m->arg[3] = m->h_mk; // lam:g
201  m->arg[4] = nullptr; // out:grad:gamma:x
202  m->arg[5] = m->h_dk; // fwd:x
203  m->arg[6] = nullptr; // fwd:p
204  m->arg[7] = nullptr; // fwd:lam:x
205  m->arg[8] = nullptr; // fwd:lam:g
206 
207  m->res[0] = m->h_pk; // fwd:grad:gamma:x
208 
209  try {
210 
211  if(m->interface->calc_function(m, "fwd1_nlp_grad_l") != 0) {
212  return SLEQP_ERROR;
213  }
214 
215  } catch (std::exception& ex) {
216  uerr() << "Error \""
217  << ex.what()
218  << "\" evaluating constraint Hessian product"
219  << std::endl;
220 
221  sleqp_raise(SLEQP_FUNC_EVAL_ERROR, "%s", ex.what());
222  }
223 
224  const int num_vars = sleqp_func_num_vars(func);
225 
226  SLEQP_CALL(sleqp_vec_set_from_raw(product, m->h_pk, num_vars, 0.));
227 
228  return SLEQP_OKAY;
229  }
230 
231  static SLEQP_RETCODE casadi_func_free(void* func_data)
232  {
233  SLEQPMemory* m = static_cast<SLEQPMemory*>(func_data);
234  return SLEQP_OKAY;
235  }
236 
237  void casadi_sleqp_func_create(SleqpFunc** star,
238  int num_vars,
239  int num_cons,
240  SLEQPMemory* m)
241  {
242  SleqpFuncCallbacks callbacks{};
243 
244  callbacks.set_value = casadi_func_set;
245  callbacks.nonzeros = casadi_func_nonzeros;
246  callbacks.obj_val = casadi_func_obj_val;
247  callbacks.obj_grad = casadi_func_obj_grad;
248  callbacks.cons_val = casadi_func_cons_val;
249  callbacks.cons_jac = casadi_func_cons_jac;
250  callbacks.hess_prod = casadi_func_hess_prod;
251  callbacks.func_free = casadi_func_free;
252 
253 
254  SLEQP_CALL_EXC(sleqp_func_create(star,
255  &callbacks,
256  num_vars,
257  num_cons,
258  static_cast<void*>(m)));
259  }
260 
261 } // namespace casadi
int calc_function(OracleMemory *m, const std::string &fcn, const double *const *arg=nullptr, int thread_id=0) const
const Sparsity & jac_sparsity() const
casadi_int size2() const
Get the number of columns.
Definition: sparsity.cpp:128
const casadi_int * row() const
Get a reference to row-vector,.
Definition: sparsity.cpp:164
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
Definition: sparsity.cpp:168
The casadi namespace.
Definition: archiver.cpp:28
T product(const std::vector< T > &values)
product
std::ostream & uerr()
static SLEQP_RETCODE casadi_func_cons_val(SleqpFunc *func, SleqpVec *cons_val, void *func_data)
Definition: sleqp_func.cpp:97
void casadi_sleqp_func_create(SleqpFunc **star, int num_vars, int num_cons, SLEQPMemory *m)
Definition: sleqp_func.cpp:237
static SLEQP_RETCODE casadi_func_free(void *func_data)
Definition: sleqp_func.cpp:231
static SLEQP_RETCODE casadi_func_nonzeros(SleqpFunc *func, int *obj_grad_nnz, int *cons_val_nnz, int *cons_jac_nnz, int *hess_prod_nnz, void *func_data)
Definition: sleqp_func.cpp:22
static SLEQP_RETCODE casadi_func_obj_val(SleqpFunc *func, double *obj_val, void *func_data)
Definition: sleqp_func.cpp:33
static SLEQP_RETCODE casadi_func_hess_prod(SleqpFunc *func, const SleqpVec *direction, const SleqpVec *cons_duals, SleqpVec *product, void *func_data)
Definition: sleqp_func.cpp:184
static SLEQP_RETCODE casadi_func_obj_grad(SleqpFunc *func, SleqpVec *obj_grad, void *func_data)
Definition: sleqp_func.cpp:61
static SLEQP_RETCODE casadi_func_cons_jac(SleqpFunc *func, SleqpMat *cons_jac, void *func_data)
Definition: sleqp_func.cpp:132
static SLEQP_RETCODE casadi_func_set(SleqpFunc *func, SleqpVec *value, SLEQP_VALUE_REASON reason, bool *reject, void *func_data)
Definition: sleqp_func.cpp:9
casadi_nlpsol_data< double > d_nlp
Definition: nlpsol_impl.hpp:42
const SLEQPInterface * interface