qpOASES-3.0beta/src/extras/OQPinterface.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of qpOASES.
3  *
4  * qpOASES -- An Implementation of the Online Active Set Strategy.
5  * Copyright (C) 2007-2011 by Hans Joachim Ferreau, Andreas Potschka,
6  * Christian Kirches et al. All rights reserved.
7  *
8  * qpOASES is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * qpOASES is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with qpOASES; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23 
24 
38 #include <qpOASES/extras/OQPinterface.hpp>
39 #include <qpOASES/QProblem.hpp>
40 
41 
43 
44 
45 /*
46  * r e a d O Q P d i m e n s i o n s
47  */
48 returnValue readOQPdimensions( const char* path,
49  int& nQP, int& nV, int& nC, int& nEC
50  )
51 {
52  /* 1) Setup file name where dimensions are stored. */
53  char filename[160];
54  snprintf( filename,160,"%sdims.oqp",path );
55 
56  /* 2) Load dimensions from file. */
57  int dims[4];
58  if ( readFromFile( dims,4,filename ) != SUCCESSFUL_RETURN )
60 
61  nQP = dims[0];
62  nV = dims[1];
63  nC = dims[2];
64  nEC = dims[3];
65 
66 
67  /* consistency check */
68  if ( ( nQP <= 0 ) || ( nV <= 0 ) || ( nC < 0 ) || ( nEC < 0 ) )
70 
71  return SUCCESSFUL_RETURN;
72 }
73 
74 
75 /*
76  * r e a d O Q P d a t a
77  */
78 returnValue readOQPdata( const char* path,
79  int& nQP, int& nV, int& nC, int& nEC,
80  real_t** H, real_t** g, real_t** A, real_t** lb, real_t** ub, real_t** lbA, real_t** ubA,
81  real_t** xOpt, real_t** yOpt, real_t** objOpt
82  )
83 {
84  char filename[160];
85 
86  /* consistency check */
87  if ( ( H == 0 ) || ( g == 0 ) || ( lb == 0 ) || ( ub == 0 ) )
89 
90 
91  /* 1) Obtain OQP dimensions. */
92  if ( readOQPdimensions( path, nQP,nV,nC,nEC ) != SUCCESSFUL_RETURN )
94 
95 
96  /* another consistency check */
97  if ( ( nC > 0 ) && ( ( A == 0 ) || ( lbA == 0 ) || ( ubA == 0 ) ) )
99 
100 
101  /* 2) Allocate memory and load OQP data: */
102  /* Hessian matrix */
103  *H = new real_t[nV*nV];
104  snprintf( filename,160,"%sH.oqp",path );
105  if ( readFromFile( *H,nV,nV,filename ) != SUCCESSFUL_RETURN )
106  {
107  delete[] *H;
109  }
110 
111  /* gradient vector sequence */
112  *g = new real_t[nQP*nV];
113  snprintf( filename,160,"%sg.oqp",path );
114  if ( readFromFile( *g,nQP,nV,filename ) != SUCCESSFUL_RETURN )
115  {
116  delete[] *g; delete[] *H;
118  }
119 
120  /* lower bound vector sequence */
121  *lb = new real_t[nQP*nV];
122  snprintf( filename,160,"%slb.oqp",path );
123  if ( readFromFile( *lb,nQP,nV,filename ) != SUCCESSFUL_RETURN )
124  {
125  delete[] *lb; delete[] *g; delete[] *H;
127  }
128 
129  /* upper bound vector sequence */
130  *ub = new real_t[nQP*nV];
131  snprintf( filename,160,"%sub.oqp",path );
132  if ( readFromFile( *ub,nQP,nV,filename ) != SUCCESSFUL_RETURN )
133  {
134  delete[] *ub; delete[] *lb; delete[] *g; delete[] *H;
136  }
137 
138  if ( nC > 0 )
139  {
140  /* Constraint matrix */
141  *A = new real_t[nC*nV];
142  snprintf( filename,160,"%sA.oqp",path );
143  if ( readFromFile( *A,nC,nV,filename ) != SUCCESSFUL_RETURN )
144  {
145  delete[] *A;
146  delete[] *ub; delete[] *lb; delete[] *g; delete[] *H;
148  }
149 
150  /* lower constraints' bound vector sequence */
151  *lbA = new real_t[nQP*nC];
152  snprintf( filename,160,"%slbA.oqp",path );
153  if ( readFromFile( *lbA,nQP,nC,filename ) != SUCCESSFUL_RETURN )
154  {
155  delete[] *lbA; delete[] *A;
156  delete[] *ub; delete[] *lb; delete[] *g; delete[] *H;
158  }
159 
160  /* upper constraints' bound vector sequence */
161  *ubA = new real_t[nQP*nC];
162  snprintf( filename,160,"%subA.oqp",path );
163  if ( readFromFile( *ubA,nQP,nC,filename ) != SUCCESSFUL_RETURN )
164  {
165  delete[] *ubA; delete[] *lbA; delete[] *A;
166  delete[] *ub; delete[] *lb; delete[] *g; delete[] *H;
168  }
169  }
170  else
171  {
172  *A = 0;
173  *lbA = 0;
174  *ubA = 0;
175  }
176 
177  if ( xOpt != 0 )
178  {
179  /* primal solution vector sequence */
180  *xOpt = new real_t[nQP*nV];
181  snprintf( filename,160,"%sx_opt.oqp",path );
182  if ( readFromFile( *xOpt,nQP,nV,filename ) != SUCCESSFUL_RETURN )
183  {
184  delete[] xOpt;
185  if ( nC > 0 ) { delete[] *ubA; delete[] *lbA; delete[] *A; };
186  delete[] *ub; delete[] *lb; delete[] *g; delete[] *H;
188  }
189  }
190 
191  if ( yOpt != 0 )
192  {
193  /* dual solution vector sequence */
194  *yOpt = new real_t[nQP*(nV+nC)];
195  snprintf( filename,160,"%sy_opt.oqp",path );
196  if ( readFromFile( *yOpt,nQP,nV+nC,filename ) != SUCCESSFUL_RETURN )
197  {
198  delete[] yOpt;
199  if ( xOpt != 0 ) { delete[] xOpt; };
200  if ( nC > 0 ) { delete[] *ubA; delete[] *lbA; delete[] *A; };
201  delete[] *ub; delete[] *lb; delete[] *g; delete[] *H;
203  }
204  }
205 
206  if ( objOpt != 0 )
207  {
208  /* dual solution vector sequence */
209  *objOpt = new real_t[nQP];
210  snprintf( filename,160,"%sobj_opt.oqp",path );
211  if ( readFromFile( *objOpt,nQP,1,filename ) != SUCCESSFUL_RETURN )
212  {
213  delete[] objOpt;
214  if ( yOpt != 0 ) { delete[] yOpt; };
215  if ( xOpt != 0 ) { delete[] xOpt; };
216  if ( nC > 0 ) { delete[] *ubA; delete[] *lbA; delete[] *A; };
217  delete[] *ub; delete[] *lb; delete[] *g; delete[] *H;
219  }
220  }
221 
222  return SUCCESSFUL_RETURN;
223 }
224 
225 
226 /*
227  * s o l v e O Q P b e n c h m a r k
228  */
229 returnValue solveOQPbenchmark( int nQP, int nV, int nC, int nEC,
230  const real_t* const _H, const real_t* const g, const real_t* const _A,
231  const real_t* const lb, const real_t* const ub,
232  const real_t* const lbA, const real_t* const ubA,
233  BooleanType isSparse,
234  const Options& options, int& nWSR, real_t& maxCPUtime,
235  real_t& maxStationarity, real_t& maxFeasibility, real_t& maxComplementarity
236  )
237 {
238  int k;
239 
240  /* I) SETUP AUXILIARY VARIABLES: */
241  /* 1) Keep nWSR and store current and maximum number of
242  * working set recalculations in temporary variables */
243  int nWSRcur;
244  int maxNWSR = 0;
245 
246  real_t CPUtimeLimit = maxCPUtime;
247  real_t CPUtimeCur = CPUtimeLimit;
248  maxCPUtime = 0.0;
249  maxStationarity = 0.0;
250  maxFeasibility = 0.0;
251  maxComplementarity = 0.0;
252  real_t stat, feas, cmpl;
253 
254  /* 2) Pointers to data of current QP ... */
255  const real_t* gCur;
256  const real_t* lbCur;
257  const real_t* ubCur;
258  const real_t* lbACur;
259  const real_t* ubACur;
260 
261  /* 3) Vectors for solution obtained by qpOASES. */
262  real_t* x = new real_t[nV];
263  real_t* y = new real_t[nV+nC];
264 
265  /* 4) Prepare matrix objects */
266  SymmetricMatrix *H;
267  Matrix *A;
268  if ( isSparse == BT_TRUE)
269  {
270  SymSparseMat *Hs;
271  H = Hs = new SymSparseMat(nV, nV, nV, _H);
272  A = new SparseMatrix(nC, nV, nV, _A);
273  Hs->createDiagInfo();
274  }
275  else
276  {
277  H = new SymDenseMat(nV, nV, nV, const_cast<real_t *>(_H));
278  A = new DenseMatrix(nC, nV, nV, const_cast<real_t *>(_A));
279  }
280 
281 
282  /* II) SETUP QPROBLEM OBJECT */
283  QProblem qp( nV,nC );
284  qp.setOptions( options );
285  qp.setPrintLevel( PL_LOW );
286 
287  /* III) RUN BENCHMARK SEQUENCE: */
288  returnValue returnvalue;
289 
290  for( k=0; k<nQP; ++k )
291  {
292  /* 1) Update pointers to current QP data. */
293  gCur = &( g[k*nV] );
294  lbCur = &( lb[k*nV] );
295  ubCur = &( ub[k*nV] );
296  lbACur = &( lbA[k*nC] );
297  ubACur = &( ubA[k*nC] );
298 
299  /* 2) Set nWSR and maximum CPU time. */
300  nWSRcur = nWSR;
301  CPUtimeCur = CPUtimeLimit;
302 
303  /* 3) Solve current QP. */
304  if ( k == 0 )
305  {
306  /* initialise */
307  returnvalue = qp.init( H,gCur,A,lbCur,ubCur,lbACur,ubACur, nWSRcur,&CPUtimeCur );
308  if ( ( returnvalue != SUCCESSFUL_RETURN ) && ( returnvalue != RET_MAX_NWSR_REACHED ) )
309  {
310  delete A; delete H; delete[] y; delete[] x;
311  return THROWERROR( returnvalue );
312  }
313  }
314  else
315  {
316  /* hotstart */
317  returnvalue = qp.hotstart( gCur,lbCur,ubCur,lbACur,ubACur, nWSRcur,&CPUtimeCur );
318  if ( ( returnvalue != SUCCESSFUL_RETURN ) && ( returnvalue != RET_MAX_NWSR_REACHED ) )
319  {
320  delete A; delete H; delete[] y; delete[] x;
321  return THROWERROR( returnvalue );
322  }
323  }
324 
325  /* 4) Obtain solution vectors and objective function value */
326  qp.getPrimalSolution( x );
327  qp.getDualSolution( y );
328 
329  /* 5) Compute KKT residuals */
330  getKKTResidual( nV, nC, _H,gCur,_A,lbCur,ubCur,lbACur,ubACur, x, y, stat, feas, cmpl );
331 
332  /* 6) Update maximum values. */
333  if ( nWSRcur > maxNWSR )
334  maxNWSR = nWSRcur;
335  if (stat > maxStationarity) maxStationarity = stat;
336  if (feas > maxFeasibility) maxFeasibility = feas;
337  if (cmpl > maxComplementarity) maxComplementarity = cmpl;
338 
339  if ( CPUtimeCur > maxCPUtime )
340  maxCPUtime = CPUtimeCur;
341  }
342  nWSR = maxNWSR;
343 
344  delete A; delete H; delete[] y; delete[] x;
345 
346  return SUCCESSFUL_RETURN;
347 }
348 
349 
350 /*
351  * s o l v e O Q P b e n c h m a r k
352  */
354  const real_t* const _H, const real_t* const g,
355  const real_t* const lb, const real_t* const ub,
356  BooleanType isSparse,
357  const Options& options, int& nWSR, real_t& maxCPUtime,
358  real_t& maxStationarity, real_t& maxFeasibility, real_t& maxComplementarity
359  )
360 {
361  int k;
362 
363  /* I) SETUP AUXILIARY VARIABLES: */
364  /* 1) Keep nWSR and store current and maximum number of
365  * working set recalculations in temporary variables */
366  int nWSRcur;
367  int maxNWSR = 0;
368 
369  real_t CPUtimeLimit = maxCPUtime;
370  real_t CPUtimeCur = CPUtimeLimit;
371  real_t stat, feas, cmpl;
372  maxCPUtime = 0.0;
373  maxStationarity = 0.0;
374  maxFeasibility = 0.0;
375  maxComplementarity = 0.0;
376 
377  /* 2) Pointers to data of current QP ... */
378  const real_t* gCur;
379  const real_t* lbCur;
380  const real_t* ubCur;
381 
382  /* 3) Vectors for solution obtained by qpOASES. */
383  real_t* x = new real_t[nV];
384  real_t* y = new real_t[nV];
385 
386  /* 4) Prepare matrix objects */
387  SymmetricMatrix *H;
388  if ( isSparse == BT_TRUE )
389  {
390  SymSparseMat *Hs;
391  H = Hs = new SymSparseMat(nV, nV, nV, _H);
392  Hs->createDiagInfo();
393  }
394  else
395  {
396  H = new SymDenseMat(nV, nV, nV, const_cast<real_t *>(_H));
397  }
398 
399  /* II) SETUP QPROBLEM OBJECT */
400  QProblemB qp( nV );
401  qp.setOptions( options );
402  qp.setPrintLevel( PL_LOW );
403 
404 
405  /* III) RUN BENCHMARK SEQUENCE: */
406  returnValue returnvalue;
407 
408  for( k=0; k<nQP; ++k )
409  {
410  /* 1) Update pointers to current QP data. */
411  gCur = &( g[k*nV] );
412  lbCur = &( lb[k*nV] );
413  ubCur = &( ub[k*nV] );
414 
415  /* 2) Set nWSR and maximum CPU time. */
416  nWSRcur = nWSR;
417  CPUtimeCur = CPUtimeLimit;
418 
419  /* 3) Solve current QP. */
420  if ( k == 0 )
421  {
422  /* initialise */
423  returnvalue = qp.init( H,gCur,lbCur,ubCur, nWSRcur,&CPUtimeCur );
424  if ( ( returnvalue != SUCCESSFUL_RETURN ) && ( returnvalue != RET_MAX_NWSR_REACHED ) )
425  {
426  delete H; delete[] y; delete[] x;
427  return THROWERROR( returnvalue );
428  }
429  }
430  else
431  {
432  /* hotstart */
433  returnvalue = qp.hotstart( gCur,lbCur,ubCur, nWSRcur,&CPUtimeCur );
434  if ( ( returnvalue != SUCCESSFUL_RETURN ) && ( returnvalue != RET_MAX_NWSR_REACHED ) )
435  {
436  delete H; delete[] y; delete[] x;
437  return THROWERROR( returnvalue );
438  }
439  }
440 
441  /* 4) Obtain solution vectors and objective function value ... */
442  qp.getPrimalSolution( x );
443  qp.getDualSolution( y );
444 
445  /* 5) Compute KKT residuals */
446  getKKTResidual( nV,0, _H,gCur,0,lbCur,ubCur,0,0, x,y, stat,feas,cmpl );
447 
448  /* 6) update maximum values. */
449  if ( nWSRcur > maxNWSR )
450  maxNWSR = nWSRcur;
451  if (stat > maxStationarity) maxStationarity = stat;
452  if (feas > maxFeasibility) maxFeasibility = feas;
453  if (cmpl > maxComplementarity) maxComplementarity = cmpl;
454 
455  if ( CPUtimeCur > maxCPUtime )
456  maxCPUtime = CPUtimeCur;
457  }
458 
459  delete H; delete[] y; delete[] x;
460 
461  return SUCCESSFUL_RETURN;
462 }
463 
464 
465 /*
466  * r u n O Q P b e n c h m a r k
467  */
468 returnValue runOQPbenchmark( const char* path, BooleanType isSparse, const Options& options,
469  int& nWSR, real_t& maxCPUtime,
470  real_t& maxStationarity, real_t& maxFeasibility, real_t& maxComplementarity
471  )
472 {
473  int nQP=0, nV=0, nC=0, nEC=0;
474 
475  real_t *H=0, *g=0, *A=0, *lb=0, *ub=0, *lbA=0, *ubA=0;
476 
477 
478  returnValue returnvalue;
479 
480  /* I) SETUP BENCHMARK: */
481  /* 1) Obtain QP sequence dimensions. */
482  if ( readOQPdimensions( path, nQP,nV,nC,nEC ) != SUCCESSFUL_RETURN )
484 
485  /* 2) Read OQP benchmark data. */
486  if ( readOQPdata( path,
487  nQP,nV,nC,nEC,
488  &H,&g,&A,&lb,&ub,&lbA,&ubA,
489  0,0,0
490  ) != SUCCESSFUL_RETURN )
491  {
493  }
494 
495 
496  /* II) SOLVE BENCHMARK */
497  if ( nC > 0 )
498  {
499  returnvalue = solveOQPbenchmark( nQP,nV,nC,nEC,
500  H,g,A,lb,ub,lbA,ubA,
501  isSparse,options,
502  nWSR,maxCPUtime,
503  maxStationarity,maxFeasibility,maxComplementarity
504  );
505 
506  if ( returnvalue != SUCCESSFUL_RETURN )
507  {
508  delete[] H; delete[] A;
509  delete[] ubA; delete[] lbA; delete[] ub; delete[] lb; delete[] g;
510  return THROWERROR( returnvalue );
511  }
512  }
513  else
514  {
515  returnvalue = solveOQPbenchmark( nQP,nV,
516  H,g,lb,ub,
517  isSparse,options,
518  nWSR,maxCPUtime,
519  maxStationarity,maxFeasibility,maxComplementarity
520  );
521 
522  if ( returnvalue != SUCCESSFUL_RETURN )
523  {
524  delete[] H; delete[] A;
525  delete[] ub; delete[] lb; delete[] g;
526  return THROWERROR( returnvalue );
527  }
528  }
529 
530  delete[] H; delete[] A;
531  delete[] ubA; delete[] lbA; delete[] ub; delete[] lb; delete[] g;
532 
533  return SUCCESSFUL_RETURN;
534 }
535 
536 
538 
539 
540 /*
541  * end of file
542  */
Interfaces matrix-vector operations tailored to symmetric sparse matrices.
returnValue init(const real_t *const _H, const real_t *const _g, const real_t *const _A, const real_t *const _lb, const real_t *const _ub, const real_t *const _lbA, const real_t *const _ubA, int &nWSR, const real_t *const yOpt=0, real_t *const cputime=0)
Implements the online active set strategy for box-constrained QPs.
BEGIN_NAMESPACE_QPOASES returnValue readOQPdimensions(const char *path, int &nQP, int &nV, int &nC, int &nEC)
Allows to pass back messages to the calling function.
Interfaces matrix-vector operations tailored to symmetric dense matrices.
returnValue init(const real_t *const _H, const real_t *const _g, const real_t *const _lb, const real_t *const _ub, int &nWSR, const real_t *const yOpt=0, real_t *const cputime=0)
returnValue hotstart(const real_t *const g_new, const real_t *const lb_new, const real_t *const ub_new, const real_t *const lbA_new, const real_t *const ubA_new, int &nWSR, real_t *const cputime)
returnValue readFromFile(real_t *data, int nrow, int ncol, const char *datafilename)
returnValue setOptions(const Options &_options)
returnValue hotstart(const real_t *const g_new, const real_t *const lb_new, const real_t *const ub_new, int &nWSR, real_t *const cputime)
Interfaces matrix-vector operations tailored to general dense matrices.
Interfaces matrix-vector operations tailored to general sparse matrices.
Provides a generic way to set and pass user-specified options.
Definition: options.hpp:65
Abstract base class for interfacing tailored matrix-vector operations.
#define PL_LOW
#define BT_TRUE
Definition: acado_types.hpp:47
returnValue readOQPdata(const char *path, int &nQP, int &nV, int &nC, int &nEC, real_t **H, real_t **g, real_t **A, real_t **lb, real_t **ub, real_t **lbA, real_t **ubA, real_t **xOpt, real_t **yOpt, real_t **objOpt)
double real_t
Definition: AD_test.c:10
Implements the online active set strategy for QPs with general constraints.
returnValue runOQPbenchmark(const char *path, BooleanType isSparse, const Options &options, int &nWSR, real_t &maxCPUtime, real_t &maxStationarity, real_t &maxFeasibility, real_t &maxComplementarity)
Abstract base class for interfacing matrix-vector operations tailored to symmetric matrices...
void getKKTResidual(int nV, int nC, const real_t *const H, const real_t *const g, const real_t *const A, const real_t *const lb, const real_t *const ub, const real_t *const lbA, const real_t *const ubA, const real_t *const x, const real_t *const y, real_t &stat, real_t &feas, real_t &cmpl)
returnValue solveOQPbenchmark(int nQP, int nV, int nC, int nEC, const real_t *const _H, const real_t *const g, const real_t *const _A, const real_t *const lb, const real_t *const ub, const real_t *const lbA, const real_t *const ubA, BooleanType isSparse, const Options &options, int &nWSR, real_t &maxCPUtime, real_t &maxStationarity, real_t &maxFeasibility, real_t &maxComplementarity)


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Mon Jun 10 2019 12:34:55