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 // C-REPLACE "fabs" "casadi_fabs"
157 
158 // SYMBOL "nlpsol_detect_bounds_before"
159 template<typename T1>
160 int casadi_detect_bounds_before(casadi_nlpsol_data<T1>* d_nlp) {
161  const casadi_nlpsol_prob<T1>* p_nlp = d_nlp->prob;
163  const casadi_nlpsol_detect_bounds_prob<T1>* p_bounds = &p_nlp->detect_bounds;
164 
165  casadi_int nx = p_nlp->nx;
166  d_bounds->arg[0] = d_nlp->p;
167  d_bounds->res[0] = d_bounds->a;
168  d_bounds->res[1] = d_bounds->b;
169  p_bounds->callback(d_bounds->arg, d_bounds->res,
170  d_bounds->iw, d_bounds->w, p_bounds->callback_data);
171 
172  for (casadi_int i=0;i<p_bounds->nb;++i) {
173  if (d_bounds->a[i]==0) {
174  casadi_int k = p_bounds->target_g[i];
175  if (d_nlp->lbg[k]>d_bounds->b[i]) return 1;
176  if (d_nlp->ubg[k]<d_bounds->b[i]) return 1;
177  }
178  }
179 
180  T1* lbz = d_nlp->lbz+nx;
181  T1* ubz = d_nlp->ubz+nx;
182  T1* lam = d_nlp->lam+nx;
183 
184  for (casadi_int i=0;i<nx;++i) {
185  d_bounds->lam_xl[i] = d_nlp->lam_x0 ? (d_nlp->lam_x0[i]<0)*d_nlp->lam_x0[i] : 0.;
186  d_bounds->lam_xu[i] = d_nlp->lam_x0 ? (d_nlp->lam_x0[i]>0)*d_nlp->lam_x0[i] : 0.;
187  }
188 
189  for (casadi_int i=0;i<nx;++i) {
190  d_bounds->target_l[i] = i;
191  d_bounds->target_u[i] = i;
192  }
193 
194  // Update lbz/ubz
195  casadi_int k=0;
196  for (casadi_int i=0;i<p_bounds->ng;++i) {
197  if (p_bounds->is_simple[i]) {
198  // Update lbz/ubz
199  T1 lb = (d_nlp->lbg[i]-d_bounds->b[k])/fabs(d_bounds->a[k]);
200  T1 ub = (d_nlp->ubg[i]-d_bounds->b[k])/fabs(d_bounds->a[k]);
201  casadi_int j = p_bounds->target_x[k];
202 
203  if (lb==d_nlp->lbz[j]) {
204  if (d_nlp->lam_g0) d_bounds->lam_xl[j] += (d_nlp->lam_g0[i]<0)*d_nlp->lam_g0[i];
205  } else if (lb>d_nlp->lbz[j]) {
206  d_nlp->lbz[j] = lb;
207  d_bounds->target_l[j] = nx+i;
208  if (d_nlp->lam_g0) d_bounds->lam_xl[j] = (d_nlp->lam_g0[i]<0)*d_nlp->lam_g0[i];
209  }
210 
211  if (ub==d_nlp->ubz[j]) {
212  if (d_nlp->lam_g0) d_bounds->lam_xu[j] += (d_nlp->lam_g0[i]>0)*d_nlp->lam_g0[i];
213  } else if (ub<d_nlp->ubz[j]) {
214  d_nlp->ubz[j] = ub;
215  d_bounds->target_u[j] = nx+i;
216  if (d_nlp->lam_g0) d_bounds->lam_xu[j] = (d_nlp->lam_g0[i]>0)*d_nlp->lam_g0[i];
217  }
218 
219  k++;
220  } else {
221 
222  // Update lbz/ubz
223  *lbz++ = d_nlp->lbg[i];
224  *ubz++ = d_nlp->ubg[i];
225 
226  if (d_nlp->lam_g0) *lam++ = d_nlp->lam_g0[i];
227  }
228  }
229 
230  for (casadi_int i=0;i<nx;++i) {
231  d_nlp->lam[i] = d_bounds->lam_xl[i]+d_bounds->lam_xu[i];
232  }
233  return 0;
234 }
235 
236 // SYMBOL "nlpsol_detect_bounds_after"
237 template<typename T1>
238 int casadi_detect_bounds_after(casadi_nlpsol_data<T1>* d_nlp) {
239  const casadi_nlpsol_prob<T1>* p_nlp = d_nlp->prob;
241  const casadi_nlpsol_detect_bounds_prob<T1>* p_bounds = &p_nlp->detect_bounds;
242  casadi_int nx = p_nlp->nx;
243 
244  casadi_fill(d_nlp->lam_x, nx, 0.);
245  casadi_fill(d_nlp->lam_g, p_bounds->ng, 0.);
246 
247  casadi_int k = 0;
248  casadi_int k_normal = 0;
249  for (casadi_int i=0;i<p_bounds->ng;++i) {
250  if (p_bounds->is_simple[i]) {
251  casadi_int j = p_bounds->target_x[k];
252  if (d_nlp->g) d_nlp->g[i] = d_bounds->a[k]*d_nlp->z[j]+d_bounds->b[k];
253  k++;
254  } else {
255  if (d_nlp->g) d_nlp->g[i] = d_nlp->z[nx+k_normal];
256  if (d_nlp->lam_g) d_nlp->lam_g[i] = d_nlp->lam[nx+k_normal];
257  k_normal++;
258  }
259  }
260 
261  for (casadi_int i=0;i<nx;++i) {
262  if (d_bounds->target_l[i]<nx) {
263  if (d_nlp->lam_x) d_nlp->lam_x[i] += (d_nlp->lam[i]<0)*d_nlp->lam[i];
264  } else {
265  if (d_nlp->lam_g)
266  d_nlp->lam_g[d_bounds->target_l[i]-nx] += (d_nlp->lam[i]<0)*d_nlp->lam[i];
267  }
268  if (d_bounds->target_u[i]<nx) {
269  if (d_nlp->lam_x) d_nlp->lam_x[i] += (d_nlp->lam[i]>0)*d_nlp->lam[i];
270  } else {
271  if (d_nlp->lam_g)
272  d_nlp->lam_g[d_bounds->target_u[i]-nx] += (d_nlp->lam[i]>0)*d_nlp->lam[i];
273  }
274  }
275  return 0;
276 }
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