daqp_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 "casadi_qp_prob<T1>" "struct casadi_qp_prob"
21 // C-REPLACE "casadi_qp_data<T1>" "struct casadi_qp_data"
22 
23 // C-REPLACE "reinterpret_cast<int**>" "(int**) "
24 // C-REPLACE "reinterpret_cast<int*>" "(int*) "
25 // C-REPLACE "const_cast<DAQPSettings*>" "(DAQPSettings*) "
26 // C-REPLACE "const_cast<T1*>" "(casadi_real*) "
27 
28 template<typename T1>
31 
32  DAQPSettings settings;
33  const int *integrality;
34 };
35 // C-REPLACE "casadi_daqp_prob<T1>" "struct casadi_daqp_prob"
36 
37 // SYMBOL "daqp_setup"
38 template<typename T1>
39 void casadi_daqp_setup(casadi_daqp_prob<T1>* p) {
40 
41 }
42 
43 
44 
45 // SYMBOL "daqp_data"
46 template<typename T1>
48  // Problem structure
50  // Problem structure
52 
53  DAQPWorkspace work;
54  DAQPProblem daqp;
55  DAQPResult res;
56 
58  int nodecount;
60 };
61 // C-REPLACE "casadi_daqp_data<T1>" "struct casadi_daqp_data"
62 
63 // SYMBOL "daqp_init_mem"
64 template<typename T1>
65 int casadi_daqp_init_mem(casadi_daqp_data<T1>* d) {
66  return 0;
67 }
68 
69 // SYMBOL "daqp_free_mem"
70 template<typename T1>
71 void casadi_daqp_free_mem(casadi_daqp_data<T1>* d) {
72 
73 }
74 
75 // SYMBOL "daqp_work"
76 template<typename T1>
77 void casadi_daqp_work(const casadi_daqp_prob<T1>* p, casadi_int* sz_arg, casadi_int* sz_res, casadi_int* sz_iw, casadi_int* sz_w) {
78  casadi_qp_work(p->qp, sz_arg, sz_res, sz_iw, sz_w);
79  // Local variables
80  casadi_int nx, na;
81  const casadi_qp_prob<T1>* p_qp = p->qp;
82  // Get matrix number of nonzeros
83  na = p_qp->na;
84  nx = p_qp->nx;
85 
86  // Reset sz_w, sz_iw
87  *sz_w = *sz_iw = 0;
88  // Temporary work vectors
89  // Persistent work vectors
90  *sz_w += nx*nx; // H
91  *sz_w += na*nx; // A
92  *sz_w += p->qp->nz; // lbz
93  *sz_w += p->qp->nz; // ubz
94  *sz_w += p->qp->nz; // lam
95  *sz_iw += p->qp->nz; // sense
96 }
97 
98 // SYMBOL "daqp_set_work"
99 template<typename T1>
100 void casadi_daqp_set_work(casadi_daqp_data<T1>* d, const T1*** arg, T1*** res, casadi_int** iw, T1** w) {
101  // Local variables
102  casadi_int nx, na;
103  const casadi_daqp_prob<T1>* p = d->prob;
104  const casadi_qp_prob<T1>* p_qp = p->qp;
105  // Get matrix number of nonzeros
106  na = p_qp->na;
107  nx = p_qp->nx;
108 
109  d->daqp.H = *w; *w += nx*nx;
110  d->daqp.A = *w; *w += na*nx;
111  d->daqp.blower = *w; *w += p->qp->nz;
112  d->daqp.bupper = *w; *w += p->qp->nz;
113  d->res.lam = *w; *w += p->qp->nz;
114  d->daqp.sense = (int*) *iw; *iw += p->qp->nz;
115 }
116 
117 // C-REPLACE "fabs" "casadi_fabs"
118 
119 // C-REPLACE "SOLVER_RET_SUCCESS" "0"
120 // C-REPLACE "SOLVER_RET_LIMITED" "2"
121 
122 // SYMBOL "daqp_solve"
123 template<typename T1>
124 int casadi_daqp_solve(casadi_daqp_data<T1>* d, const double** arg, double** res, casadi_int* iw, double* w) {
125  // Local variables
126  casadi_int i;
127  int flag;
128  const casadi_daqp_prob<T1>* p = d->prob;
129  const casadi_qp_prob<T1>* p_qp = p->qp;
130  casadi_qp_data<T1>* d_qp = d->qp;
131 
132  for (i=0;i<p_qp->nx;++i) {
133  d->daqp.sense[i] = d_qp->lbx[i]==d_qp->ubx[i] ? 5 : 0;
134  }
135  for (i=0;i<p_qp->na;++i) {
136  d->daqp.sense[p_qp->nx+i] = d_qp->lba[i]==d_qp->uba[i] ? 5 : 0;
137  }
138 
139  if (p->integrality) {
140  for (casadi_int j = 0; j < p_qp->nx; ++j) {
141  if (!p->integrality[j]) continue;
142 
143  double lb = d_qp->lbx[j];
144  double ub = d_qp->ubx[j];
145 
146  int binary = fabs(lb - 0.0) < 1e-9 && fabs(ub - 1.0) < 1e-9;
147 
148  casadi_assert(binary, "DAQP only supports binary variables with bounds [0,1], but variable " + str(j) + " has bounds [" + str(lb) + ", " + str(ub) + "]."); // NOLINT(whitespace/line_length)
149  if (!binary) return 1;
150 
151  d->daqp.sense[j] |= 16; // mark as binary
152  }
153  }
154 
155  d->daqp.n = p_qp->nx;
156  d->daqp.m = p_qp->nx + p_qp->na;
157  d->daqp.ms = p_qp->nx;
158  d->work.settings = const_cast<DAQPSettings*>(&p->settings);
159  d->res.x = d_qp->x;
160  casadi_densify(d->qp->h, d->prob->qp->sp_h, d->daqp.H, 0);
161  casadi_densify(d->qp->a, d->prob->qp->sp_a, d->daqp.A, 1);
162  casadi_copy(d_qp->lbx, p_qp->nx, d->daqp.blower);
163  casadi_copy(d_qp->lba, p_qp->na, d->daqp.blower+p_qp->nx);
164  casadi_copy(d_qp->ubx, p_qp->nx, d->daqp.bupper);
165  casadi_copy(d_qp->uba, p_qp->na, d->daqp.bupper+p_qp->nx);
166  d->daqp.f = const_cast<T1*>(d_qp->g);
167 
168  flag = setup_daqp(&d->daqp,&d->work,&(d->res.setup_time));
169  if (flag<0) return 1;
170 
171  if (d->work.bnb) {
172  casadi_message("DAQP BnB workspace detected - branch-and-bound will run.");
173  }
174 
175  daqp_solve(&d->res,&d->work);
176  casadi_copy(d->res.lam, p_qp->nx, d_qp->lam_x);
177  casadi_copy(d->res.lam+p_qp->nx, p_qp->na, d_qp->lam_a);
178  if (d->work.bnb) {
179  d->nodecount = d->work.bnb->nodecount;
180  d->bnb_itercount = d->work.bnb->itercount;
181  } else {
182  d->nodecount = 0;
183  d->bnb_itercount = 0;
184  }
185  if (d_qp->f) *d_qp->f = d->res.fval;
186  d->work.settings = 0;
187  free_daqp_workspace(&d->work);
188  free_daqp_ldp(&d->work);
189 
190  d->return_status = d->res.exitflag;
191  d_qp->success = d->res.exitflag==EXIT_OPTIMAL;
192 
204  return 0;
205 }
DAQPProblem daqp
DAQPWorkspace work
const casadi_daqp_prob< T1 > * prob
casadi_qp_data< T1 > * qp
const int * integrality
DAQPSettings settings
const casadi_qp_prob< T1 > * qp
const T1 * lba
Definition: casadi_qp.hpp:64
const T1 * lbx
Definition: casadi_qp.hpp:64
const T1 * uba
Definition: casadi_qp.hpp:64
const T1 * ubx
Definition: casadi_qp.hpp:64
const T1 * g
Definition: casadi_qp.hpp:64
casadi_int nx
Definition: casadi_qp.hpp:33
casadi_int na
Definition: casadi_qp.hpp:33