casadi_nlp.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 
21 // SYMBOL "nlpsol_detect_bounds_prob"
22 template<typename T1>
24  casadi_int sz_arg;
25  casadi_int sz_res;
26  casadi_int sz_iw;
27  casadi_int sz_w;
28  // Original number og constraints
29  casadi_int ng;
30  // Number of bounds
31  casadi_int nb;
32  const casadi_int *target_x;
33  const casadi_int *target_g;
34  const char *is_simple;
35 
36  int (*callback)(const T1** arg, T1** res, casadi_int* iw, T1* w, void* callback_data);
38 };
39 // C-REPLACE "casadi_nlpsol_detect_bounds_prob<T1>" "struct casadi_nlpsol_detect_bounds_prob"
40 
41 // SYMBOL "nlpsol_prob"
42 template<typename T1>
44  casadi_int nx, ng, np;
45 
47 };
48 // C-REPLACE "casadi_nlpsol_prob<T1>" "struct casadi_nlpsol_prob"
49 
50 // SYMBOL "nlpsol_detect_bounds_data"
51 template<typename T1>
53  // Work vectors
54  const T1** arg;
55  T1** res;
56  casadi_int* iw;
57  T1* w;
58 
59  // Simple bounds g(x)=A(b)x+b(p);
60  // a[i]*x[target_x[i]]+b[i]
61  T1* a;
62  T1* b;
63  casadi_int* target_l;
64  casadi_int* target_u;
65  T1* lam_xl;
66  T1* lam_xu;
67 };
68 // C-REPLACE "casadi_nlpsol_detect_bounds_data<T1>" "struct casadi_nlpsol_detect_bounds_data"
69 // C-REPLACE "casadi_oracle_data<T1>" "struct casadi_oracle_data"
70 
71 // SYMBOL "nlpsol_data"
72 template<typename T1>
74  // Problem structure
77  // Variable bounds
78  T1 *lbz, *ubz;
79  // Current primal solution
80  T1 *z;
81  // Current dual solution
82  T1 *lam;
83  // Storage for f when null pointer passed
85 
86  // NLP data, pointers to arg (no allocations needed)
87  const T1 *p, *lbx, *ubx, *lbg, *ubg, *x0, *lam_x0, *lam_g0;
88  // NLP results, pointers to res (no allocations needed)
89  T1 *f, *x, *g, *lam_x, *lam_g, *lam_p;
90 
92 };
93 // C-REPLACE "casadi_nlpsol_data<T1>" "struct casadi_nlpsol_data"
94 
95 // SYMBOL "nlpsol_work"
96 template<typename T1>
97 void casadi_nlpsol_work(const casadi_nlpsol_prob<T1>* p, casadi_int* sz_arg, casadi_int* sz_res,
98  casadi_int* sz_iw, casadi_int* sz_w) {
99  // Reset sz_arg, sz_res
100  *sz_arg = *sz_res = 0;
101  // Reset sz_w, sz_iw
102  *sz_w = *sz_iw = 0;
103  *sz_w += p->nx + p->ng; // z
104  *sz_w += p->nx + p->ng; // lbz
105  *sz_w += p->nx + p->ng; // ubz
106  *sz_w += p->nx + p->ng; // lam
107 
108  if (p->detect_bounds.ng) {
109  *sz_arg += p->detect_bounds.sz_arg;
110  *sz_res += p->detect_bounds.sz_res;
111  *sz_iw += p->detect_bounds.sz_iw;
112  *sz_w += p->detect_bounds.sz_w;
113 
114  *sz_w += p->detect_bounds.nb; // a;
115  *sz_w += p->detect_bounds.nb; // b;
116  *sz_iw += p->nx; // target_l
117  *sz_iw += p->nx; // target_u
118  *sz_w += p->nx; // lam_xl;
119  *sz_w += p->nx; // lam_xu;
120  }
121 
122 }
123 
124 
125 // SYMBOL "nlpsol_init"
126 template<typename T1>
127 void casadi_nlpsol_init(casadi_nlpsol_data<T1>* d, const T1*** arg, T1*** res,
128  casadi_int** iw, T1** w) {
129  // Local variables
130  casadi_int nx, ng;
131  const casadi_nlpsol_prob<T1>* p = d->prob;
132  nx = p->nx;
133  ng = p->ng;
134  // Get matrix number of nonzeros
135  d->z = *w; *w += nx + ng;
136  d->lbz = *w; *w += nx + ng;
137  d->ubz = *w; *w += nx + ng;
138  d->lam = *w; *w += nx + ng;
139 
140  if (p->detect_bounds.ng) {
141  d->detect_bounds.arg = *arg; *arg += p->detect_bounds.sz_arg;
142  d->detect_bounds.res = *res; *res += p->detect_bounds.sz_res;
143  d->detect_bounds.iw = *iw; *iw += p->detect_bounds.sz_iw;
144  d->detect_bounds.w = *w; *w += p->detect_bounds.sz_w;
145 
146  d->detect_bounds.a = *w; *w += p->detect_bounds.nb;
147  d->detect_bounds.b = *w; *w += p->detect_bounds.nb;
148  d->detect_bounds.target_l = *iw; *iw += p->nx;
149  d->detect_bounds.target_u = *iw; *iw += p->nx;
150  d->detect_bounds.lam_xl = *w; *w += nx;
151  d->detect_bounds.lam_xu = *w; *w += nx;
152  }
153 
154 }
155 
156 // SYMBOL "nlpsol_detect_bounds_before"
157 template<typename T1>
158 int casadi_detect_bounds_before(casadi_nlpsol_data<T1>* d_nlp) {
159  const casadi_nlpsol_prob<T1>* p_nlp = d_nlp->prob;
161  const casadi_nlpsol_detect_bounds_prob<T1>* p_bounds = &p_nlp->detect_bounds;
162 
163  casadi_int nx = p_nlp->nx;
164  d_bounds->arg[0] = d_nlp->p;
165  d_bounds->res[0] = d_bounds->a;
166  d_bounds->res[1] = d_bounds->b;
167  p_bounds->callback(d_bounds->arg, d_bounds->res,
168  d_bounds->iw, d_bounds->w, p_bounds->callback_data);
169 
170  for (casadi_int i=0;i<p_bounds->nb;++i) {
171  if (d_bounds->a[i]==0) {
172  casadi_int k = p_bounds->target_g[i];
173  if (d_nlp->lbg[k]>d_bounds->b[i]) return 1;
174  if (d_nlp->ubg[k]<d_bounds->b[i]) return 1;
175  }
176  }
177 
178  T1* lbz = d_nlp->lbz+nx;
179  T1* ubz = d_nlp->ubz+nx;
180  T1* lam = d_nlp->lam+nx;
181 
182  for (casadi_int i=0;i<nx;++i) {
183  d_bounds->lam_xl[i] = d_nlp->lam_x0 ? (d_nlp->lam_x0[i]<0)*d_nlp->lam_x0[i] : 0.;
184  d_bounds->lam_xu[i] = d_nlp->lam_x0 ? (d_nlp->lam_x0[i]>0)*d_nlp->lam_x0[i] : 0.;
185  }
186 
187  for (casadi_int i=0;i<nx;++i) {
188  d_bounds->target_l[i] = i;
189  d_bounds->target_u[i] = i;
190  }
191 
192  // Update lbz/ubz
193  casadi_int k=0;
194  for (casadi_int i=0;i<p_bounds->ng;++i) {
195  if (p_bounds->is_simple[i]) {
196  // Update lbz/ubz
197 
198  T1 lb = (d_nlp->lbg[i]-d_bounds->b[k])/d_bounds->a[k];
199  T1 ub = (d_nlp->ubg[i]-d_bounds->b[k])/d_bounds->a[k];
200  if (d_bounds->a[k]<0) {
201  T1 tmp = lb;
202  lb = ub;
203  ub = tmp;
204  }
205  casadi_int j = p_bounds->target_x[k];
206 
207  if (lb==d_nlp->lbz[j]) {
208  if (d_nlp->lam_g0) d_bounds->lam_xl[j] += (d_nlp->lam_g0[i]<0)*d_nlp->lam_g0[i];
209  } else if (lb>d_nlp->lbz[j]) {
210  d_nlp->lbz[j] = lb;
211  d_bounds->target_l[j] = nx+i;
212  if (d_nlp->lam_g0) d_bounds->lam_xl[j] = (d_nlp->lam_g0[i]<0)*d_nlp->lam_g0[i];
213  }
214 
215  if (ub==d_nlp->ubz[j]) {
216  if (d_nlp->lam_g0) d_bounds->lam_xu[j] += (d_nlp->lam_g0[i]>0)*d_nlp->lam_g0[i];
217  } else if (ub<d_nlp->ubz[j]) {
218  d_nlp->ubz[j] = ub;
219  d_bounds->target_u[j] = nx+i;
220  if (d_nlp->lam_g0) d_bounds->lam_xu[j] = (d_nlp->lam_g0[i]>0)*d_nlp->lam_g0[i];
221  }
222 
223  k++;
224  } else {
225 
226  // Update lbz/ubz
227  *lbz++ = d_nlp->lbg[i];
228  *ubz++ = d_nlp->ubg[i];
229 
230  if (d_nlp->lam_g0) *lam++ = d_nlp->lam_g0[i];
231  }
232  }
233 
234  for (casadi_int i=0;i<nx;++i) {
235  d_nlp->lam[i] = d_bounds->lam_xl[i]+d_bounds->lam_xu[i];
236  }
237  return 0;
238 }
239 
240 // SYMBOL "nlpsol_detect_bounds_after"
241 template<typename T1>
242 int casadi_detect_bounds_after(casadi_nlpsol_data<T1>* d_nlp) {
243  const casadi_nlpsol_prob<T1>* p_nlp = d_nlp->prob;
245  const casadi_nlpsol_detect_bounds_prob<T1>* p_bounds = &p_nlp->detect_bounds;
246  casadi_int nx = p_nlp->nx;
247 
248  casadi_fill(d_nlp->lam_x, nx, 0.);
249  casadi_fill(d_nlp->lam_g, p_bounds->ng, 0.);
250 
251  casadi_int k = 0;
252  casadi_int k_normal = 0;
253  for (casadi_int i=0;i<p_bounds->ng;++i) {
254  if (p_bounds->is_simple[i]) {
255  casadi_int j = p_bounds->target_x[k];
256  if (d_nlp->g) d_nlp->g[i] = d_bounds->a[k]*d_nlp->z[j]+d_bounds->b[k];
257  k++;
258  } else {
259  if (d_nlp->g) d_nlp->g[i] = d_nlp->z[nx+k_normal];
260  if (d_nlp->lam_g) d_nlp->lam_g[i] = d_nlp->lam[nx+k_normal];
261  k_normal++;
262  }
263  }
264 
265  for (casadi_int i=0;i<nx;++i) {
266  if (d_bounds->target_l[i]<nx) {
267  if (d_nlp->lam_x) d_nlp->lam_x[i] += (d_nlp->lam[i]<0)*d_nlp->lam[i];
268  } else {
269  if (d_nlp->lam_g)
270  d_nlp->lam_g[d_bounds->target_l[i]-nx] += (d_nlp->lam[i]<0)*d_nlp->lam[i];
271  }
272  if (d_bounds->target_u[i]<nx) {
273  if (d_nlp->lam_x) d_nlp->lam_x[i] += (d_nlp->lam[i]>0)*d_nlp->lam[i];
274  } else {
275  if (d_nlp->lam_g)
276  d_nlp->lam_g[d_bounds->target_u[i]-nx] += (d_nlp->lam[i]>0)*d_nlp->lam[i];
277  }
278  }
279 
280  k = 0;
281  for (casadi_int i=0;i<p_bounds->ng;++i) {
282  if (p_bounds->is_simple[i]) {
283  if (d_nlp->lam_g) d_nlp->lam_g[i] /= d_bounds->a[k];
284  k++;
285  }
286  }
287 
288  return 0;
289 }
const T1 * lam_g0
Definition: casadi_nlp.hpp:87
const casadi_nlpsol_prob< T1 > * prob
Definition: casadi_nlp.hpp:75
casadi_oracle_data< T1 > * oracle
Definition: casadi_nlp.hpp:76
casadi_nlpsol_detect_bounds_data< T1 > detect_bounds
Definition: casadi_nlp.hpp:91
const T1 * lam_x0
Definition: casadi_nlp.hpp:87
int(* callback)(const T1 **arg, T1 **res, casadi_int *iw, T1 *w, void *callback_data)
Definition: casadi_nlp.hpp:36
casadi_nlpsol_detect_bounds_prob< T1 > detect_bounds
Definition: casadi_nlp.hpp:46