qpoasesCutest.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-2015 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 
34 /* Choose one or more methods to solve the QP */
35 #define SOLVE_DENSE 0 /* Standard qpOASES, matrices passed dense */
36 #define SOLVE_SPARSE 0 /* Standard qpOASES, matrices passed sparse */
37 #define SOLVE_SCHUR 1 /* Schur complement qpOASES */
38 
39 
40 #include <qpOASES.hpp>
41 #include <sys/time.h>
42 
43 extern "C" { /* To prevent C++ compilers from mangling symbols */
44 #include <cutest.h>
45 }
46 
47 
48 int convertTripletToHbf( int m, int n, int nnz,
49  double *vals, int *iRow, int *jCol,
50  double *vals_hbf, int *iRow_hbf, int *jCol_hbf )
51 {
52  int i, ii, j, k;
53 
54  /* Initialize output arrays */
55  for( k=0; k<n+1; k++ )
56  jCol_hbf[k] = 0;
57  for( k=0; k<nnz; k++ )
58  {
59  iRow_hbf[k] = 0;
60  vals_hbf[k] = 0.0;
61  }
62 
63  /* Count elements for each column */
64  for( k=0; k<nnz; k++ )
65  {
66  j = jCol[k]-1; // Convert Fortran to C indices!
67  jCol_hbf[j]++;
68  }
69 
70  /* Set the column pointers */
71  jCol_hbf[n] = nnz;
72  for( k=n-1; k>-1; k-- )
73  jCol_hbf[k] = jCol_hbf[k+1] - jCol_hbf[k];
74 
75  /* Put row indices and values at the right places, use jCol_hbf[j] to track elements of the jth column */
76  for( k=0; k<nnz; k++ )
77  {
78  i = iRow[k]-1; // Convert Fortran to C indices!
79  j = jCol[k]-1;
80  ii = jCol_hbf[j];
81 
82  vals_hbf[ii] = vals[k];
83  iRow_hbf[ii] = i;
84  jCol_hbf[j] = ii + 1;
85  }
86 
87  /* Shift all column pointers back again */
88  for( k=n-1; k>0; k-- )
89  jCol_hbf[k] = jCol_hbf[k-1];
90  jCol_hbf[0] = 0;
91 
92  return 0;
93 }
94 
95 
96 
97 int main( )
98 {
99  /*
100  * PART I: Extract CUTEst problemdata:
101  *
102  * - problem dimension
103  * - variable and constraint bounds
104  * - objective gradient
105  * - sparse and dense Jacobian
106  * - sparse and dense Hessian
107  * - initial values for x and y
108  */
109 
110  /* From CUTEst generic c package */
111  char *fname = "prob/OUTSDIF.d"; /* CUTEst data file */
112  int funit = 42; /* FORTRAN unit number for OUTSDIF.d */
113  int iout = 6; /* FORTRAN unit number for error output */
114  int io_buffer = 11; /* FORTRAN unit internal input/output */
115  int ierr; /* Exit flag from OPEN and CLOSE */
116  int status; /* Exit flag from CUTEst tools */
117  int e_order = 0, l_order = 0, v_order = 0;
118 
119 
120  /* Problem description: the following variables will be set for qpOASES call */
121  int nVar; /* number of variables */
122  int nCon; /* number of constraints */
123  double *lb, *ub; /* lower and upper bounds for variables */
124  double *lbA, *ubA; /* lower and upper bounds for constraints */
125  double *g; /* objective gradient */
126 #if SOLVE_DENSE
127  double *hesDense, *jacDense; /* dense Hessian and Jacobian */
128 #endif
129 #if SOLVE_SCHUR || SOLVE_SPARSE
130  /* Sparse Hessian and Jacobian in Harwell-Boeing format: */
131  int nnzj, nnzh; /* number of nonzero elements in Jacobian and Hessian */
132  double *hesVal, *jacVal; /* nonzero elements of Hessian and Jacobian */
133  int *hesIndCol, *hesIndRow; /* column and row indices of Hessian */
134  int *jacIndCol, *jacIndRow; /* column and row indices of Jacobian */
135 #endif
136 
137  /* Additional problem description: these variables are set and may also be used by qpOASES */
138  double obj; /* constant objective offset */
139  double *xInit; /* initial values for primal variables */
140  double *yInit; /* initial values for dual variables */
141  logical *isEq; /* logical array to mark equality constraints */
142 
143 
144  /* Open problem description file OUTSDIF.d */
145  ierr = 0;
146  FORTRAN_open( &funit, fname, &ierr );
147  if( ierr ) {
148  printf("Error opening file OUTSDIF.d.\nAborting.\n");
149  exit(1);
150  }
151 
152  /* Determine problem size */
153  CUTEST_cdimen( &status, &funit, &nVar, &nCon );
154  if( status ) {
155  printf("** CUTEst error, status = %d, aborting\n", status);
156  exit(status);
157  }
158 
159  /* Reserve memory for variables, bounds, and multipliers */
160  /* and call appropriate initialization routine for CUTEst */
161  logical *isLinear;
162  xInit = new double[nVar];
163  yInit = new double[nCon];
164  lb = new double[nVar];
165  ub = new double[nVar];
166  lbA = new double[nCon];
167  ubA = new double[nCon];
168  isEq = new logical[nCon];
169  isLinear = new logical[nCon];
170 
171  CUTEST_csetup( &status, &funit, &iout, &io_buffer,
172  &nVar, &nCon, xInit, lb, ub,
173  yInit, lbA, ubA, isEq, isLinear,
174  &e_order, &l_order, &v_order );
175  if( status ) {
176  printf("** CUTEst_csetup: error, status = %d, aborting\n", status);
177  exit(status);
178  }
179 
180  /* Evaluate gradient and objective at x=0 to get g */
181  logical grad = 1;
182  g = new double[nVar];
183  double *xZero = new double[nVar];
184  for( int k=0; k<nVar; k++ ) xZero[k] = 0.0;
185  CUTEST_cofg( &status, &nVar, xZero, &obj, g, &grad );
186  if( status ) {
187  printf("** CUTEst_cofg: error, status = %d, aborting\n", status);
188  exit(status);
189  }
190 
191  double *cVal = new double[nCon];
192 #if SOLVE_SPARSE || SOLVE_SCHUR
193  /* Evaluate sparse Jacobian in triplet format */
194  int lj = nCon*nVar; // overestimate
195  double *J_val = new double[lj];
196  int *J_var = new int[lj];
197  int *J_fun = new int[lj];
198 
199  if( nCon > 0 )
200  {
201  /* Evaluate sparse constraints at x=0 to get the rhs of equality constraints (they are not set by csetup!) */
202  CUTEST_ccfsg( &status, &nVar, &nCon, xZero, cVal, &nnzj, &lj, J_val, J_var, J_fun, &grad );
203  if( status ) {
204  printf("** CUTEst_ccfsg: error, status = %d, aborting\n", status);
205  exit(status);
206  }
207 
208  for( int k=0; k<nCon; k++ )
209  if( isEq[k] )
210  lbA[k] = ubA[k] = -cVal[k];
211 
212  jacIndCol = new int[nVar+1];
213  jacIndRow = new int[nnzj];
214  jacVal = new double[nnzj];
215  convertTripletToHbf( nCon, nVar, nnzj, J_val, J_fun, J_var, jacVal, jacIndRow, jacIndCol );
216 
217  }
218  delete[] J_val;
219  delete[] J_fun;
220  delete[] J_var;
221 
222  /* Evaluate sparse Hessian in triplet format */
223  int lh = nVar*nVar; // overestimate
224  double *H_val = new double[lh];
225  int *H_col = new int[lh];
226  int *H_row = new int[lh];
227  CUTEST_csh( &status, &nVar, &nCon, xInit, yInit, &nnzh, &lh, H_val, H_row, H_col );
228  if( status ) {
229  printf("** CUTEst_csh: error, status = %d, aborting\n", status);
230  exit(status);
231  }
232  /* Only upper triangular matrix is returned by CUTEst, to be safe, set H to be the full matrix */
233  int count = 0;
234  for( int k=0; k<nnzh; k++ )
235  if( H_row[k] != H_col[k] )
236  {
237  H_val[nnzh+count] = H_val[k];
238  H_col[nnzh+count] = H_row[k];
239  H_row[nnzh+count] = H_col[k];
240  count++;
241  }
242  nnzh = nnzh + count;
243 
244  hesIndCol = new int[nVar+1];
245  hesIndRow = new int[nnzh];
246  hesVal = new double[nnzh];
247  convertTripletToHbf( nVar, nVar, nnzh, H_val, H_row, H_col, hesVal, hesIndRow, hesIndCol );
248 
249  delete[] H_val;
250  delete[] H_row;
251  delete[] H_col;
252 #endif
253 
254 #if SOLVE_DENSE
255  if( nCon > 0 )
256  {
257  /* Evaluate dense constraints at x=0 to get the rhs of equality constraints (they are not set by csetup!) */
258  logical trans = 1;
259  jacDense = new double[nCon*nVar];
260  CUTEST_ccfg( &status, &nVar, &nCon, xZero, cVal, &trans, &nVar, &nCon, jacDense, &grad );
261  }
262 
263  /* Evaluate dense Hessian */
264  hesDense = new double[nVar*nVar];
265  CUTEST_cdh( &status, &nVar, &nCon, xInit, yInit, &nVar, hesDense );
266  if( status ) {
267  printf("** CUTEst_cdh: error, status = %d, aborting\n", status);
268  exit(status);
269  }
270 #endif
271  delete[] xZero;
272 
273  /*
274  * End of CUTEst stuff
275  */
276 
277 
278  /*
279  * PART II: qpOASES
280  */
281 
283 
284  Options opts;
285 #if SOLVE_DENSE
286  SymDenseMat *H_d;
287  DenseMatrix *A_d;
288 #endif
289 #if SOLVE_SCHUR || SOLVE_SPARSE
290  SymSparseMat *H_s;
291  SparseMatrix *A_s;
292 #endif
293  Bounds bInit( nVar );
294  Constraints cInit( nCon );
295  double *xOpt = new double[nVar];
296  double *yOpt = new double[nVar+nCon];
297  Bounds bOpt( nVar );
298  Constraints cOpt( nCon );
299 
300 #if SOLVE_DENSE
301  A_d = new DenseMatrix( nCon, nVar, nVar, jacDense );
302  H_d = new SymDenseMat( nVar, nVar, nVar, hesDense );
303 #endif
304 #if SOLVE_SCHUR || SOLVE_SPARSE
305  A_s = new SparseMatrix( nCon, nVar, jacIndRow, jacIndCol, jacVal );
306  H_s = new SymSparseMat( nVar, nVar, hesIndRow, hesIndCol, hesVal );
307  H_s->createDiagInfo();
308 #endif
309 
310  /* Set initial working set depending on initial values for x and y */
312  double eps = 2.0e-16;
313  for( int k=0; k<nVar; k++ )
314  {
315  if( getAbs( xInit[k] - lb[k] ) < eps )
316  bInit.setStatus( k, ST_LOWER );
317  else if( getAbs( xInit[k] - ub[k] ) < eps )
318  bInit.setStatus( k, ST_UPPER );
319  else
320  bInit.setStatus( k, ST_INACTIVE );
321 
322  bInit.setType( k, ST_UNKNOWN );
323  }
325  for( int k=0; k<nCon; k++ )
326  {
327  if( getAbs( cVal[k] - lbA[k] ) < eps )
328  cInit.setStatus( k, ST_LOWER );
329  else if( getAbs( cVal[k] - ubA[k] ) < eps )
330  cInit.setStatus( k, ST_UPPER );
331  else
332  cInit.setStatus( k, ST_INACTIVE );
333 
334  if( isEq[k] )
335  cInit.setType( k, ST_EQUALITY );
336  else
337  cInit.setType( k, ST_UNKNOWN );
338  }
339  delete[] cVal;
340 
341  /* Set up QProblem object(s). */
342 #if SOLVE_SCHUR
343  SQProblemSchur qpSchur( nVar, nCon, HST_UNKNOWN, 75 );
344 #endif
345 #if SOLVE_DENSE
346  SQProblem qpDense( nVar, nCon, HST_UNKNOWN );
347 #endif
348 #if SOLVE_SPARSE
349  SQProblem qpSparse( nVar, nCon, HST_UNKNOWN );
350 #endif
351 
352  /* Set options */
353  returnValue ret;
354  int maxIt = 10000;
355  double maxTime = 100000;
356 
357  //opts.setToReliable();
358  opts.setToDefault();
359 
360  //opts.printLevel = PL_HIGH;
361  //opts.enableRamping = BT_TRUE;
362  //opts.enableFarBounds = BT_TRUE;
363  //opts.enableFlippingBounds = BT_TRUE;
364  //opts.enableRegularisation = BT_FALSE;
365  //opts.enableFullLITests = BT_TRUE;
366  //opts.enableNZCTests = BT_TRUE;
367  //opts.enableDriftCorrection = 1;
368  //opts.enableCholeskyRefactorisation = 1;
369  opts.enableEqualities = BT_TRUE;
370  //opts.terminationTolerance = 2.2204e-09;
371  //opts.boundTolerance = 2.2204e-10;
372  //opts.boundRelaxation = 10000;
373  //opts.epsNum = -2.2204e-13;
374  //opts.epsDen = 2.2204e-13;
375  //opts.maxPrimalJump = 100000000;
376  //opts.maxDualJump = 100000000;
377  //opts.initialRamping = 0.50000;
378  //opts.finalRamping = 1;
379  //opts.initialFarBounds = 1000000;
380  //opts.growFarBounds = 1000;
381  opts.initialStatusBounds = ST_INACTIVE;
382  //opts.epsFlipping = 2.2204e-13;
383  //opts.numRegularisationSteps = 4;
384  //opts.epsRegularisation = 2.2204e-13;
385  opts.numRefinementSteps = 3;
386  //opts.epsIterRef = 2.2204e-14;
387  //opts.epsLITests = 2.2204e-09;
388  //opts.epsNZCTests = 6.6613e-13;
389  opts.enableInertiaCorrection = BT_TRUE;
390  opts.rcondSMin = 1.0e-14;
391 
392 
393  /* Solve QPs. */
394  int nWSR;
395  double time;
396  struct timeval startTime;
397  struct timeval endTime;
398  int elapsedTime;
399  gettimeofday(&startTime, NULL);
400 #if SOLVE_DENSE
401  printf( "\n----------Begin Standard version with dense matrices----------\n" );
402  qpDense.setOptions( opts );
403  nWSR = maxIt;
404  time = maxTime;
405 
406  for( int k=0; k<nVar; k++ )
407  {
408  xOpt[k] = xInit[k];
409  yOpt[k] = 0.0;
410  }
411  for( int k=0; k<nCon; k++ ) yOpt[k+nVar] = yInit[k]; // what about lambda for bound constraints?
412  bOpt = Bounds( bInit );
413  cOpt = Constraints( cInit );
414  ret = qpDense.init( H_d, g, A_d, lb, ub, lbA, ubA, nWSR, &time, xOpt, yOpt, &bOpt, &cOpt );
415 
416  if( ret == SUCCESSFUL_RETURN ) printf("Obj. = %23.16e\n", qpDense.getObjVal() + obj );
417  printf( "\n-----------End Standard version with dense matrices-----------\n" );
418 #endif
419 
420 #if SOLVE_SCHUR
421  printf( "\n----------Begin Schur complement version----------\n" );
422  qpSchur.setOptions( opts );
423  nWSR = maxIt;
424  time = maxTime;
425 
426  for( int k=0; k<nVar; k++ )
427  {
428  xOpt[k] = xInit[k];
429  yOpt[k] = 0.0;
430  }
431  for( int k=0; k<nCon; k++ ) yOpt[k+nVar] = yInit[k]; // what about lambda for bound constraints?
432  bOpt = Bounds( bInit );
433  cOpt = Constraints( cInit );
434  //ret = qpSchur.init( H_s, g, A_s, lb, ub, lbA, ubA, nWSR, &time, xOpt, yOpt, &bOpt, &cOpt );
435  ret = qpSchur.init( H_s, g, A_s, lb, ub, lbA, ubA, nWSR, &time );
436 
437  if( ret == SUCCESSFUL_RETURN ) printf("Obj. = %23.16e\n", qpSchur.getObjVal() + obj );
438  printf( "\n\n-----------End Schur complement version-----------\n" );
439 #endif
440 
441 #if SOLVE_SPARSE
442  printf( "\n----------Begin Standard version with sparse matrices----------\n" );
443  qpSparse.setOptions( opts );
444  nWSR = maxIt;
445  time = maxTime;
446 
447  for( int k=0; k<nVar; k++ )
448  {
449  xOpt[k] = xInit[k];
450  yOpt[k] = 0.0;
451  }
452  for( int k=0; k<nCon; k++ ) yOpt[k+nVar] = yInit[k]; // what about lambda for bound constraints?
453  bOpt = Bounds( bInit );
454  cOpt = Constraints( cInit );
455  ret = qpSparse.init( H_s, g, A_s, lb, ub, lbA, ubA, nWSR, &time, xOpt, yOpt, &bOpt, &cOpt );
456 
457  if( ret == SUCCESSFUL_RETURN ) printf("Obj. = %23.16e\n", qpSparse.getObjVal() + obj );
458  printf( "\n-----------End Standard version with sparse matrices-----------\n" );
459 #endif
460  gettimeofday(&endTime, NULL);
461 
462  elapsedTime = (endTime.tv_sec*1000000 + (endTime.tv_usec)) -
463  (startTime.tv_sec*1000000 + (startTime.tv_usec));
464  printf( "Took %g seconds.\n", elapsedTime/1000000.0 );
465 
466  /* Clean up */
467  delete[] g;
468  delete[] lb;
469  delete[] ub;
470  delete[] lbA;
471  delete[] ubA;
472  delete[] isEq;
473  delete[] isLinear;
474  delete[] xOpt;
475  delete[] yOpt;
476  delete[] xInit;
477  delete[] yInit;
478 
479 #if SOLVE_SCHUR || SOLVE_SPARSE
480  delete[] hesVal;
481  delete[] hesIndRow;
482  delete[] hesIndCol;
483  if( nCon > 0 )
484  {
485  delete[] jacVal;
486  delete[] jacIndRow;
487  delete[] jacIndCol;
488  }
489 #endif
490 #if SOLVE_DENSE
491  delete[] hesDense;
492  if( nCon > 0 )
493  delete[] jacDense;
494 #endif
495 
496  return ret;
497 }
498 
returnValue setType(int i, SubjectToType value)
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)
#define ST_LOWER
real_t getAbs(real_t x)
Implements the online active set strategy for QPs with varying matrices.
int main()
Allows to pass back messages to the calling function.
Interfaces matrix-vector operations tailored to symmetric dense matrices.
#define ST_INACTIVE
returnValue setOptions(const Options &_options)
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
int convertTripletToHbf(int m, int n, int nnz, double *vals, int *iRow, int *jCol, double *vals_hbf, int *iRow_hbf, int *jCol_hbf)
#define BT_TRUE
Definition: acado_types.hpp:47
#define HST_UNKNOWN
returnValue setStatus(int i, SubjectToStatus value)
Manages working sets of bounds (= box constraints).
Implements the online active set strategy for QPs with varying, sparse matrices.
#define ST_UPPER


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