examples/code_generation/mpc_mhe/getting_started_export/qpoases/SRC/QProblemB.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-2008 by Hans Joachim Ferreau et al. All rights reserved.
6  *
7  * qpOASES is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * qpOASES is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with qpOASES; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  *
21  */
22 
23 
35 #include <QProblemB.hpp>
36 
37 #include <stdio.h>
38 
39 void printmatrix(char *name, double *A, int m, int n) {
40  int i, j;
41 
42  printf("%s = [...\n", name);
43  for (i = 0; i < m; i++) {
44  for (j = 0; j < n; j++)
45  printf(" % 9.4f", A[i*n+j]);
46  printf(",\n");
47  }
48  printf("];\n");
49 }
50 
51 
52 
53 /*****************************************************************************
54  * P U B L I C *
55  *****************************************************************************/
56 
57 
58 /*
59  * Q P r o b l e m B
60  */
62 {
63  /* reset global message handler */
65 
66  bounds.init( 0 );
67 
68  tau = 0.0;
69 
70  hessianType = HST_POSDEF_NULLSPACE; /* Hessian is assumed to be positive definite by default */
73 
75 
76  #ifdef PC_DEBUG
79  #else
80  printlevel = QPOASES_PRINTLEVEL;
81  #endif
82 
83  count = 0;
84 }
85 
86 
87 /*
88  * Q P r o b l e m B
89  */
91 {
92  /* consistency check */
93  if ( _nV <= 0 )
94  {
95  _nV = 1;
97  }
98 
99  /* reset global message handler */
101 
102  bounds.init( _nV );
103 
104  tau = 0.0;
105 
106  hessianType = HST_POSDEF_NULLSPACE; /* Hessian is assumed to be positive definite by default */
109 
111 
112  #ifdef PC_DEBUG
115  #else
116  printlevel = QPOASES_PRINTLEVEL;
117  #endif
118 
119  count = 0;
120 }
121 
122 
123 /*
124  * Q P r o b l e m B
125  */
127 {
128  int i, j;
129 
130  int _nV = rhs.bounds.getNV( );
131 
132  for( i=0; i<_nV; ++i )
133  for( j=0; j<_nV; ++j )
134  H[i*NVMAX + j] = rhs.H[i*NVMAX + j];
135 
136  for( i=0; i<_nV; ++i )
137  g[i] = rhs.g[i];
138 
139  for( i=0; i<_nV; ++i )
140  lb[i] = rhs.lb[i];
141 
142  for( i=0; i<_nV; ++i )
143  ub[i] = rhs.ub[i];
144 
145 
146  bounds = rhs.bounds;
147 
148  for( i=0; i<_nV; ++i )
149  for( j=0; j<_nV; ++j )
150  R[i*NVMAX + j] = rhs.R[i*NVMAX + j];
151 
152  for( i=0; i<_nV; ++i )
153  x[i] = rhs.x[i];
154 
155  for( i=0; i<_nV; ++i )
156  y[i] = rhs.y[i];
157 
158  tau = rhs.tau;
159 
160  hessianType = rhs.hessianType;
161  infeasible = rhs.infeasible;
162  unbounded = rhs.unbounded;
163 
164  status = rhs.status;
165 
166  printlevel = rhs.printlevel;
167 
168  count = rhs.count;
169 }
170 
171 
172 /*
173  * ~ Q P r o b l e m B
174  */
176 {
177 }
178 
179 
180 /*
181  * o p e r a t o r =
182  */
184 {
185  int i, j;
186 
187  if ( this != &rhs )
188  {
189  int _nV = rhs.bounds.getNV( );
190 
191  for( i=0; i<_nV; ++i )
192  for( j=0; j<_nV; ++j )
193  H[i*NVMAX + j] = rhs.H[i*NVMAX + j];
194 
195  for( i=0; i<_nV; ++i )
196  g[i] = rhs.g[i];
197 
198  for( i=0; i<_nV; ++i )
199  lb[i] = rhs.lb[i];
200 
201  for( i=0; i<_nV; ++i )
202  ub[i] = rhs.ub[i];
203 
204  bounds = rhs.bounds;
205 
206  for( i=0; i<_nV; ++i )
207  for( j=0; j<_nV; ++j )
208  R[i*NVMAX + j] = rhs.R[i*NVMAX + j];
209 
210 
211  for( i=0; i<_nV; ++i )
212  x[i] = rhs.x[i];
213 
214  for( i=0; i<_nV; ++i )
215  y[i] = rhs.y[i];
216 
217  tau = rhs.tau;
218 
219  hessianType = rhs.hessianType;
220  infeasible = rhs.infeasible;
221  unbounded = rhs.unbounded;
222 
223  status = rhs.status;
224 
225  printlevel = rhs.printlevel;
226  setPrintLevel( rhs.printlevel );
227 
228  count = rhs.count;
229  }
230 
231  return *this;
232 }
233 
234 
235 /*
236  * r e s e t
237  */
239 {
240  int i, j;
241  int nV = getNV( );
242 
243 
244  /* 1) Reset bounds. */
245  bounds.init( nV );
246 
247  /* 2) Reset Cholesky decomposition. */
248  for( i=0; i<nV; ++i )
249  for( j=0; j<nV; ++j )
250  R[i*NVMAX + j] = 0.0;
251 
252  /* 3) Reset steplength and status flags. */
253  tau = 0.0;
254 
255  hessianType = HST_POSDEF_NULLSPACE; /* Hessian is assumed to be positive definite by default */
258 
260 
261  return SUCCESSFUL_RETURN;
262 }
263 
264 
265 /*
266  * i n i t
267  */
268 returnValue QProblemB::init( const real_t* const _H, const real_t* const _g,
269  const real_t* const _lb, const real_t* const _ub,
270  int& nWSR, const real_t* const yOpt, real_t* const cputime
271  )
272 {
273  /* 1) Setup QP data. */
274  if ( setupQPdata( _H,_g,_lb,_ub ) != SUCCESSFUL_RETURN )
276 
277  /* 2) Call to main initialisation routine (without any additional information). */
278  return solveInitialQP( 0,yOpt,0, nWSR,cputime );
279 }
280 
281 
282 /*
283  * h o t s t a r t
284  */
285 returnValue QProblemB::hotstart( const real_t* const g_new, const real_t* const lb_new, const real_t* const ub_new,
286  int& nWSR, real_t* const cputime
287  )
288 {
289  int l;
290 
291  /* consistency check */
292  if ( ( getStatus( ) == QPS_NOTINITIALISED ) ||
295  {
297  }
298 
299  /* start runtime measurement */
300  real_t starttime = 0.0;
301  if ( cputime != 0 )
302  starttime = getCPUtime( );
303 
304 
305  /* I) PREPARATIONS */
306  /* 1) Reset status flags and increase QP counter. */
309 
310  ++count;
311 
312  /* 2) Allocate delta vectors of gradient and bounds. */
313  returnValue returnvalue;
314  BooleanType Delta_bB_isZero;
315 
316  int FR_idx[NVMAX];
317  int FX_idx[NVMAX];
318 
319  real_t delta_g[NVMAX];
320  real_t delta_lb[NVMAX];
321  real_t delta_ub[NVMAX];
322 
326 
327  int BC_idx;
328  SubjectToStatus BC_status;
329 
330  #ifdef PC_DEBUG
331  char messageString[80];
332  #endif
333 
334  /* II) MAIN HOMOTOPY LOOP */
335  for( l=0; l<nWSR; ++l )
336  {
338 
339  if ( printlevel == PL_HIGH )
340  {
341  #ifdef PC_DEBUG
342  sprintf( messageString,"%d ...",l );
344  #endif
345  }
346 
347  /* 1) Setup index arrays. */
348  if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
350 
351  if ( bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
353 
354  /* 2) Initialise shift direction of the gradient and the bounds. */
355  returnvalue = hotstart_determineDataShift( FX_idx,
356  g_new,lb_new,ub_new,
357  delta_g,delta_lb,delta_ub,
358  Delta_bB_isZero
359  );
360  if ( returnvalue != SUCCESSFUL_RETURN )
361  {
362  nWSR = l;
364  return returnvalue;
365  }
366 
367  /* 3) Determination of step direction of X and Y. */
368  returnvalue = hotstart_determineStepDirection( FR_idx,FX_idx,
369  delta_g,delta_lb,delta_ub,
370  Delta_bB_isZero,
371  delta_xFX,delta_xFR,delta_yFX
372  );
373  if ( returnvalue != SUCCESSFUL_RETURN )
374  {
375  nWSR = l;
377  return returnvalue;
378  }
379 
380 
381  /* 4) Determination of step length TAU. */
382  returnvalue = hotstart_determineStepLength( FR_idx,FX_idx,
383  delta_lb,delta_ub,
384  delta_xFR,delta_yFX,
385  BC_idx,BC_status );
386  if ( returnvalue != SUCCESSFUL_RETURN )
387  {
388  nWSR = l;
390  return returnvalue;
391  }
392 
393  /* 5) Realisation of the homotopy step. */
394  returnvalue = hotstart_performStep( FR_idx,FX_idx,
395  delta_g,delta_lb,delta_ub,
396  delta_xFX,delta_xFR,delta_yFX,
397  BC_idx,BC_status
398  );
399 
400 
401  if ( returnvalue != SUCCESSFUL_RETURN )
402  {
403  nWSR = l;
404 
405  /* stop runtime measurement */
406  if ( cputime != 0 )
407  *cputime = getCPUtime( ) - starttime;
408 
409  /* optimal solution found? */
410  if ( returnvalue == RET_OPTIMAL_SOLUTION_FOUND )
411  {
412  status = QPS_SOLVED;
413 
414  if ( printlevel == PL_HIGH )
416 
417  #ifdef PC_DEBUG
418  if ( printIteration( l,BC_idx,BC_status ) != SUCCESSFUL_RETURN )
419  THROWERROR( RET_PRINT_ITERATION_FAILED ); /* do not pass this as return value! */
420  #endif
421 
422  /* check KKT optimality conditions */
423  return checkKKTconditions( );
424  }
425  else
426  {
427  /* checks for infeasibility... */
428  if ( infeasible == BT_TRUE )
429  {
432  }
433 
434  /* ...unboundedness... */
435  if ( unbounded == BT_TRUE ) /* not necessary since objective function convex! */
437 
438  /* ... and throw unspecific error otherwise */
440  return returnvalue;
441  }
442  }
443 
444  /* 6) Output information of successful QP iteration. */
446 
447  #ifdef PC_DEBUG
448  if ( printIteration( l,BC_idx,BC_status ) != SUCCESSFUL_RETURN )
449  THROWERROR( RET_PRINT_ITERATION_FAILED ); /* do not pass this as return value! */
450  #endif
451  }
452 
453 
454  /* stop runtime measurement */
455  if ( cputime != 0 )
456  *cputime = getCPUtime( ) - starttime;
457 
458 
459  /* if programm gets to here, output information that QP could not be solved
460  * within the given maximum numbers of working set changes */
461  if ( printlevel == PL_HIGH )
462  {
463  #ifdef PC_DEBUG
464  sprintf( messageString,"(nWSR = %d)",nWSR );
466  #endif
467  }
468 
469  /* Finally check KKT optimality conditions. */
470  returnValue returnvalueKKTcheck = checkKKTconditions( );
471 
472  if ( returnvalueKKTcheck != SUCCESSFUL_RETURN )
473  return returnvalueKKTcheck;
474  else
475  return RET_MAX_NWSR_REACHED;
476 }
477 
478 
479 /*
480  * g e t N Z
481  */
483 {
484  /* if no constraints are present: nZ=nFR */
485  return bounds.getFree( )->getLength( );
486 }
487 
488 
489 /*
490  * g e t O b j V a l
491  */
493 {
494  real_t objVal;
495 
496  /* calculated optimal objective function value
497  * only if current QP has been solved */
498  if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
499  ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
500  ( getStatus( ) == QPS_SOLVED ) )
501  {
502  objVal = getObjVal( x );
503  }
504  else
505  {
506  objVal = INFTY;
507  }
508 
509  return objVal;
510 }
511 
512 
513 /*
514  * g e t O b j V a l
515  */
516 real_t QProblemB::getObjVal( const real_t* const _x ) const
517 {
518  int i, j;
519  int nV = getNV( );
520 
521  real_t obj_tmp = 0.0;
522 
523  for( i=0; i<nV; ++i )
524  {
525  obj_tmp += _x[i]*g[i];
526 
527  for( j=0; j<nV; ++j )
528  obj_tmp += 0.5*_x[i]*H[i*NVMAX + j]*_x[j];
529  }
530 
531  return obj_tmp;
532 }
533 
534 
535 /*
536  * g e t P r i m a l S o l u t i o n
537  */
539 {
540  int i;
541 
542  /* return optimal primal solution vector
543  * only if current QP has been solved */
544  if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
545  ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
546  ( getStatus( ) == QPS_SOLVED ) )
547  {
548  for( i=0; i<getNV( ); ++i )
549  xOpt[i] = x[i];
550 
551  return SUCCESSFUL_RETURN;
552  }
553  else
554  {
555  return RET_QP_NOT_SOLVED;
556  }
557 }
558 
559 
560 /*
561  * g e t D u a l S o l u t i o n
562  */
564 {
565  int i;
566 
567  /* return optimal dual solution vector
568  * only if current QP has been solved */
569  if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
570  ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
571  ( getStatus( ) == QPS_SOLVED ) )
572  {
573  for( i=0; i<getNV( ); ++i )
574  yOpt[i] = y[i];
575 
576  return SUCCESSFUL_RETURN;
577  }
578  else
579  {
580  return RET_QP_NOT_SOLVED;
581  }
582 }
583 
584 
585 /*
586  * s e t P r i n t L e v e l
587  */
589 {
590  #ifndef __MATLAB__
591  if ( ( printlevel >= PL_MEDIUM ) && ( printlevel != _printlevel ) )
593  #endif
594 
595  printlevel = _printlevel;
596 
597  /* update message handler preferences */
598  switch ( printlevel )
599  {
600  case PL_NONE:
604  break;
605 
606  case PL_LOW:
610  break;
611 
612  default: /* PL_MEDIUM, PL_HIGH */
616  break;
617  }
618 
619  return SUCCESSFUL_RETURN;
620 }
621 
622 
623 
624 /*****************************************************************************
625  * P R O T E C T E D *
626  *****************************************************************************/
627 
628 /*
629  * c h e c k F o r I d e n t i t y H e s s i a n
630  */
632 {
633  int i, j;
634  int nV = getNV( );
635 
636  /* nothing to do as status flag remains unaltered
637  * if Hessian differs from identity matrix */
638  if ( hessianType == HST_IDENTITY )
639  return SUCCESSFUL_RETURN;
640 
641  /* 1) If Hessian differs from identity matrix,
642  * return without changing the internal HessianType. */
643  for ( i=0; i<nV; ++i )
644  if ( getAbs( H[i*NVMAX + i] - 1.0 ) > EPS )
645  return SUCCESSFUL_RETURN;
646 
647  for ( i=0; i<nV; ++i )
648  {
649  for ( j=0; j<i; ++j )
650  if ( ( getAbs( H[i*NVMAX + j] ) > EPS ) || ( getAbs( H[j*NVMAX + i] ) > EPS ) )
651  return SUCCESSFUL_RETURN;
652  }
653 
654  /* 2) If this point is reached, Hessian equals the idetity matrix. */
656 
657  return SUCCESSFUL_RETURN;
658 }
659 
660 
661 /*
662  * s e t u p S u b j e c t T o T y p e
663  */
665 {
666  int i;
667  int nV = getNV( );
668 
669 
670  /* 1) Check if lower bounds are present. */
672  for( i=0; i<nV; ++i )
673  if ( lb[i] > -INFTY )
674  {
676  break;
677  }
678 
679  /* 2) Check if upper bounds are present. */
681  for( i=0; i<nV; ++i )
682  if ( ub[i] < INFTY )
683  {
685  break;
686  }
687 
688  /* 3) Determine implicitly fixed and unbounded variables. */
689  int nFV = 0;
690  int nUV = 0;
691 
692  for( i=0; i<nV; ++i )
693  if ( ( lb[i] < -INFTY + BOUNDTOL ) && ( ub[i] > INFTY - BOUNDTOL ) )
694  {
696  ++nUV;
697  }
698  else
699  {
700  if ( lb[i] > ub[i] - BOUNDTOL )
701  {
703  ++nFV;
704  }
705  else
706  {
708  }
709  }
710 
711  /* 4) Set dimensions of bounds structure. */
712  bounds.setNFV( nFV );
713  bounds.setNUV( nUV );
714  bounds.setNBV( nV - nFV - nUV );
715 
716  return SUCCESSFUL_RETURN;
717 }
718 
719 
720 /*
721  * c h o l e s k y D e c o m p o s i t i o n
722  */
724 {
725  int i, j, k, ii, jj;
726  int nV = getNV( );
727  int nFR = getNFR( );
728 
729  /* 1) Initialises R with all zeros. */
730  for( i=0; i<nV; ++i )
731  for( j=0; j<nV; ++j )
732  R[i*NVMAX + j] = 0.0;
733 
734  /* 2) Calculate Cholesky decomposition of H (projected to free variables). */
735  if ( hessianType == HST_IDENTITY )
736  {
737  /* if Hessian is identity, so is its Cholesky factor. */
738  for( i=0; i<nFR; ++i )
739  R[i*NVMAX + i] = 1.0;
740  }
741  else
742  {
743  if ( nFR > 0 )
744  {
745  int FR_idx[NVMAX];
746  if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
748 
749  /* R'*R = H */
750  real_t sum;
751 
752  for( i=0; i<nFR; ++i )
753  {
754  /* j == i */
755  ii = FR_idx[i];
756  sum = H[ii*NVMAX + ii];
757 
758  for( k=(i-1); k>=0; --k )
759  sum -= R[k*NVMAX + i] * R[k*NVMAX + i];
760 
761  if ( sum > 0.0 )
762  R[i*NVMAX + i] = sqrt( sum );
763  else
764  {
767  }
768 
769  /* j > i */
770  for( j=(i+1); j<nFR; ++j )
771  {
772  jj = FR_idx[j];
773  sum = H[jj*NVMAX + ii];
774 
775  for( k=(i-1); k>=0; --k )
776  sum -= R[k*NVMAX + i] * R[k*NVMAX + j];
777 
778  R[i*NVMAX + j] = sum / R[i*NVMAX + i];
779  }
780  }
781  }
782  }
783 
784  return SUCCESSFUL_RETURN;
785 }
786 
787 
788 /*
789  * s o l v e I n i t i a l Q P
790  */
791 returnValue QProblemB::solveInitialQP( const real_t* const xOpt, const real_t* const yOpt,
792  const Bounds* const guessedBounds,
793  int& nWSR, real_t* const cputime
794  )
795 {
796  int i;
797  int nV = getNV( );
798 
799 
800  /* start runtime measurement */
801  real_t starttime = 0.0;
802  if ( cputime != 0 )
803  starttime = getCPUtime( );
804 
805 
807 
808  /* I) ANALYSE QP DATA: */
809  /* 1) Check if Hessian happens to be the identity matrix. */
811  return THROWERROR( RET_INIT_FAILED );
812 
813  /* 2) Setup type of bounds (i.e. unbounded, implicitly fixed etc.). */
815  return THROWERROR( RET_INIT_FAILED );
816 
818 
819 
820  /* II) SETUP AUXILIARY QP WITH GIVEN OPTIMAL SOLUTION: */
821  /* 1) Setup bounds data structure. */
823  return THROWERROR( RET_INIT_FAILED );
824 
825  /* 2) Setup optimal primal/dual solution for auxiliary QP. */
826  if ( setupAuxiliaryQPsolution( xOpt,yOpt ) != SUCCESSFUL_RETURN )
827  return THROWERROR( RET_INIT_FAILED );
828 
829  /* 3) Obtain linear independent working set for auxiliary QP. */
830 
831  static Bounds auxiliaryBounds;
832 
833  auxiliaryBounds.init( nV );
834 
835  if ( obtainAuxiliaryWorkingSet( xOpt,yOpt,guessedBounds, &auxiliaryBounds ) != SUCCESSFUL_RETURN )
836  return THROWERROR( RET_INIT_FAILED );
837 
838  /* 4) Setup working set of auxiliary QP and setup cholesky decomposition. */
839  if ( setupAuxiliaryWorkingSet( &auxiliaryBounds,BT_TRUE ) != SUCCESSFUL_RETURN )
840  return THROWERROR( RET_INIT_FAILED );
841 
844 
845  /* 5) Store original QP formulation... */
846  real_t g_original[NVMAX];
847  real_t lb_original[NVMAX];
848  real_t ub_original[NVMAX];
849 
850  for( i=0; i<nV; ++i )
851  {
852  g_original[i] = g[i];
853  lb_original[i] = lb[i];
854  ub_original[i] = ub[i];
855  }
856 
857  /* ... and setup QP data of an auxiliary QP having an optimal solution
858  * as specified by the user (or xOpt = yOpt = 0, by default). */
860  return THROWERROR( RET_INIT_FAILED );
861 
863  return THROWERROR( RET_INIT_FAILED );
864 
866 
867 
868  /* III) SOLVE ACTUAL INITIAL QP: */
869  /* Use hotstart method to find the solution of the original initial QP,... */
870  returnValue returnvalue = hotstart( g_original,lb_original,ub_original, nWSR,0 );
871 
872 
873  /* ... check for infeasibility and unboundedness... */
874  if ( isInfeasible( ) == BT_TRUE )
876 
877  if ( isUnbounded( ) == BT_TRUE )
879 
880  /* ... and internal errors. */
881  if ( ( returnvalue != SUCCESSFUL_RETURN ) && ( returnvalue != RET_MAX_NWSR_REACHED ) &&
882  ( returnvalue != RET_INACCURATE_SOLUTION ) && ( returnvalue != RET_NO_SOLUTION ) )
884 
885 
886  /* stop runtime measurement */
887  if ( cputime != 0 )
888  *cputime = getCPUtime( ) - starttime;
889 
890  if ( printlevel == PL_HIGH )
892 
893  return returnvalue;
894 }
895 
896 
897 /*
898  * o b t a i n A u x i l i a r y W o r k i n g S e t
899  */
901  const Bounds* const guessedBounds, Bounds* auxiliaryBounds
902  ) const
903 {
904  int i = 0;
905  int nV = getNV( );
906 
907 
908  /* 1) Ensure that desiredBounds is allocated (and different from guessedBounds). */
909  if ( ( auxiliaryBounds == 0 ) || ( auxiliaryBounds == guessedBounds ) )
911 
912 
913  /* 2) Setup working set for auxiliary initial QP. */
914  if ( guessedBounds != 0 )
915  {
916  /* If an initial working set is specific, use it!
917  * Moreover, add all implictly fixed variables if specified. */
918  for( i=0; i<nV; ++i )
919  {
920  if ( bounds.getType( i ) == ST_EQUALITY )
921  {
922  if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
924  }
925  else
926  {
927  if ( auxiliaryBounds->setupBound( i,guessedBounds->getStatus( i ) ) != SUCCESSFUL_RETURN )
929  }
930  }
931  }
932  else /* No initial working set specified. */
933  {
934  if ( ( xOpt != 0 ) && ( yOpt == 0 ) )
935  {
936  /* Obtain initial working set by "clipping". */
937  for( i=0; i<nV; ++i )
938  {
939  if ( xOpt[i] <= lb[i] + BOUNDTOL )
940  {
941  if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
943  continue;
944  }
945 
946  if ( xOpt[i] >= ub[i] - BOUNDTOL )
947  {
948  if ( auxiliaryBounds->setupBound( i,ST_UPPER ) != SUCCESSFUL_RETURN )
950  continue;
951  }
952 
953  /* Moreover, add all implictly fixed variables if specified. */
954  if ( bounds.getType( i ) == ST_EQUALITY )
955  {
956  if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
958  }
959  else
960  {
961  if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
963  }
964  }
965  }
966 
967  if ( ( xOpt == 0 ) && ( yOpt != 0 ) )
968  {
969  /* Obtain initial working set in accordance to sign of dual solution vector. */
970  for( i=0; i<nV; ++i )
971  {
972  if ( yOpt[i] > ZERO )
973  {
974  if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
976  continue;
977  }
978 
979  if ( yOpt[i] < -ZERO )
980  {
981  if ( auxiliaryBounds->setupBound( i,ST_UPPER ) != SUCCESSFUL_RETURN )
983  continue;
984  }
985 
986  /* Moreover, add all implictly fixed variables if specified. */
987  if ( bounds.getType( i ) == ST_EQUALITY )
988  {
989  if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
991  }
992  else
993  {
994  if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
996  }
997  }
998  }
999 
1000  /* If xOpt and yOpt are null pointer and no initial working is specified,
1001  * start with empty working set (or implicitly fixed bounds only)
1002  * for auxiliary QP. */
1003  if ( ( xOpt == 0 ) && ( yOpt == 0 ) )
1004  {
1005  for( i=0; i<nV; ++i )
1006  {
1007  /* Only add all implictly fixed variables if specified. */
1008  if ( bounds.getType( i ) == ST_EQUALITY )
1009  {
1010  if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
1012  }
1013  else
1014  {
1015  if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
1017  }
1018  }
1019  }
1020  }
1021 
1022  return SUCCESSFUL_RETURN;
1023 }
1024 
1025 
1026 /*
1027  * s e t u p A u x i l i a r y W o r k i n g S e t
1028  */
1030  BooleanType setupAfresh
1031  )
1032 {
1033  int i;
1034  int nV = getNV( );
1035 
1036  /* consistency checks */
1037  if ( auxiliaryBounds != 0 )
1038  {
1039  for( i=0; i<nV; ++i )
1040  if ( ( bounds.getStatus( i ) == ST_UNDEFINED ) || ( auxiliaryBounds->getStatus( i ) == ST_UNDEFINED ) )
1041  return THROWERROR( RET_UNKNOWN_BUG );
1042  }
1043  else
1044  {
1046  }
1047 
1048 
1049  /* I) SETUP CHOLESKY FLAG:
1050  * Cholesky decomposition shall only be updated if working set
1051  * shall be updated (i.e. NOT setup afresh!) */
1052  BooleanType updateCholesky;
1053  if ( setupAfresh == BT_TRUE )
1054  updateCholesky = BT_FALSE;
1055  else
1056  updateCholesky = BT_TRUE;
1057 
1058 
1059  /* II) REMOVE FORMERLY ACTIVE BOUNDS (IF NECESSARY): */
1060  if ( setupAfresh == BT_FALSE )
1061  {
1062  /* Remove all active bounds that shall be inactive AND
1063  * all active bounds that are active at the wrong bound. */
1064  for( i=0; i<nV; ++i )
1065  {
1066  if ( ( bounds.getStatus( i ) == ST_LOWER ) && ( auxiliaryBounds->getStatus( i ) != ST_LOWER ) )
1067  if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
1069 
1070  if ( ( bounds.getStatus( i ) == ST_UPPER ) && ( auxiliaryBounds->getStatus( i ) != ST_UPPER ) )
1071  if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
1073  }
1074  }
1075 
1076 
1077  /* III) ADD NEWLY ACTIVE BOUNDS: */
1078  /* Add all inactive bounds that shall be active AND
1079  * all formerly active bounds that have been active at the wrong bound. */
1080  for( i=0; i<nV; ++i )
1081  {
1082  if ( ( bounds.getStatus( i ) == ST_INACTIVE ) && ( auxiliaryBounds->getStatus( i ) != ST_INACTIVE ) )
1083  {
1084  if ( addBound( i,auxiliaryBounds->getStatus( i ),updateCholesky ) != SUCCESSFUL_RETURN )
1086  }
1087  }
1088 
1089  return SUCCESSFUL_RETURN;
1090 }
1091 
1092 
1093 /*
1094  * s e t u p A u x i l i a r y Q P s o l u t i o n
1095  */
1097  )
1098 {
1099  int i;
1100  int nV = getNV( );
1101 
1102 
1103  /* Setup primal/dual solution vectors for auxiliary initial QP:
1104  * if a null pointer is passed, a zero vector is assigned;
1105  * old solution vector is kept if pointer to internal solution vector is passed. */
1106  if ( xOpt != 0 )
1107  {
1108  if ( xOpt != x )
1109  for( i=0; i<nV; ++i )
1110  x[i] = xOpt[i];
1111  }
1112  else
1113  {
1114  for( i=0; i<nV; ++i )
1115  x[i] = 0.0;
1116  }
1117 
1118  if ( yOpt != 0 )
1119  {
1120  if ( yOpt != y )
1121  for( i=0; i<nV; ++i )
1122  y[i] = yOpt[i];
1123  }
1124  else
1125  {
1126  for( i=0; i<nV; ++i )
1127  y[i] = 0.0;
1128  }
1129 
1130  return SUCCESSFUL_RETURN;
1131 }
1132 
1133 
1134 /*
1135  * s e t u p A u x i l i a r y Q P g r a d i e n t
1136  */
1138 {
1139  int i, j;
1140  int nV = getNV( );
1141 
1142 
1143  /* Setup gradient vector: g = -H*x + y'*Id. */
1144  for ( i=0; i<nV; ++i )
1145  {
1146  /* y'*Id */
1147  g[i] = y[i];
1148 
1149  /* -H*x */
1150  for ( j=0; j<nV; ++j )
1151  g[i] -= H[i*NVMAX + j] * x[j];
1152  }
1153 
1154  return SUCCESSFUL_RETURN;
1155 }
1156 
1157 
1158 /*
1159  * s e t u p A u x i l i a r y Q P b o u n d s
1160  */
1162 {
1163  int i;
1164  int nV = getNV( );
1165 
1166 
1167  /* Setup bound vectors. */
1168  for ( i=0; i<nV; ++i )
1169  {
1170  switch ( bounds.getStatus( i ) )
1171  {
1172  case ST_INACTIVE:
1173  if ( useRelaxation == BT_TRUE )
1174  {
1175  if ( bounds.getType( i ) == ST_EQUALITY )
1176  {
1177  lb[i] = x[i];
1178  ub[i] = x[i];
1179  }
1180  else
1181  {
1182  lb[i] = x[i] - BOUNDRELAXATION;
1183  ub[i] = x[i] + BOUNDRELAXATION;
1184  }
1185  }
1186  break;
1187 
1188  case ST_LOWER:
1189  lb[i] = x[i];
1190  if ( bounds.getType( i ) == ST_EQUALITY )
1191  {
1192  ub[i] = x[i];
1193  }
1194  else
1195  {
1196  if ( useRelaxation == BT_TRUE )
1197  ub[i] = x[i] + BOUNDRELAXATION;
1198  }
1199  break;
1200 
1201  case ST_UPPER:
1202  ub[i] = x[i];
1203  if ( bounds.getType( i ) == ST_EQUALITY )
1204  {
1205  lb[i] = x[i];
1206  }
1207  else
1208  {
1209  if ( useRelaxation == BT_TRUE )
1210  lb[i] = x[i] - BOUNDRELAXATION;
1211  }
1212  break;
1213 
1214  default:
1215  return THROWERROR( RET_UNKNOWN_BUG );
1216  }
1217  }
1218 
1219  return SUCCESSFUL_RETURN;
1220 }
1221 
1222 
1223 /*
1224  * a d d B o u n d
1225  */
1227  BooleanType updateCholesky
1228  )
1229 {
1230  int i, j;
1231  int nFR = getNFR( );
1232 
1233 
1234  /* consistency check */
1235  if ( ( getStatus( ) == QPS_NOTINITIALISED ) ||
1236  ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
1237  ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
1238  ( getStatus( ) == QPS_SOLVED ) )
1239  {
1240  return THROWERROR( RET_UNKNOWN_BUG );
1241  }
1242 
1243  /* Perform cholesky updates only if QProblemB has been initialised! */
1244  if ( ( getStatus( ) == QPS_PREPARINGAUXILIARYQP ) || ( updateCholesky == BT_FALSE ) )
1245  {
1246  /* UPDATE INDICES */
1247  if ( bounds.moveFreeToFixed( number,B_status ) != SUCCESSFUL_RETURN )
1248  return THROWERROR( RET_ADDBOUND_FAILED );
1249 
1250  return SUCCESSFUL_RETURN;
1251  }
1252 
1253 
1254  /* I) PERFORM CHOLESKY UPDATE: */
1255  /* 1) Index of variable to be added within the list of free variables. */
1256  int number_idx = bounds.getFree( )->getIndex( number );
1257 
1258  real_t c, s;
1259 
1260  /* 2) Use row-wise Givens rotations to restore upper triangular form of R. */
1261  for( i=number_idx+1; i<nFR; ++i )
1262  {
1263  computeGivens( R[(i-1)*NVMAX + i],R[i*NVMAX + i], R[(i-1)*NVMAX + i],R[i*NVMAX + i],c,s );
1264 
1265  for( j=(1+i); j<nFR; ++j ) /* last column of R is thrown away */
1266  applyGivens( c,s,R[(i-1)*NVMAX + j],R[i*NVMAX + j], R[(i-1)*NVMAX + j],R[i*NVMAX + j] );
1267  }
1268 
1269  /* 3) Delete <number_idx>th column and ... */
1270  for( i=0; i<nFR-1; ++i )
1271  for( j=number_idx+1; j<nFR; ++j )
1272  R[i*NVMAX + j-1] = R[i*NVMAX + j];
1273  /* ... last column of R. */
1274  for( i=0; i<nFR; ++i )
1275  R[i*NVMAX + nFR-1] = 0.0;
1276 
1277 
1278  /* II) UPDATE INDICES */
1279  if ( bounds.moveFreeToFixed( number,B_status ) != SUCCESSFUL_RETURN )
1280  return THROWERROR( RET_ADDBOUND_FAILED );
1281 
1282 
1283  return SUCCESSFUL_RETURN;
1284 }
1285 
1286 
1288  BooleanType updateCholesky
1289  )
1290 {
1291  int i, ii;
1292  int nFR = getNFR( );
1293 
1294 
1295  /* consistency check */
1296  if ( ( getStatus( ) == QPS_NOTINITIALISED ) ||
1297  ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
1298  ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
1299  ( getStatus( ) == QPS_SOLVED ) )
1300  {
1301  return THROWERROR( RET_UNKNOWN_BUG );
1302  }
1303 
1304 
1305  /* I) UPDATE INDICES */
1306  if ( bounds.moveFixedToFree( number ) != SUCCESSFUL_RETURN )
1308 
1309  /* Perform cholesky updates only if QProblemB has been initialised! */
1310  if ( ( getStatus( ) == QPS_PREPARINGAUXILIARYQP ) || ( updateCholesky == BT_FALSE ) )
1311  return SUCCESSFUL_RETURN;
1312 
1313 
1314  /* II) PERFORM CHOLESKY UPDATE */
1315  int FR_idx[NVMAX];
1316  if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
1318 
1319  /* 1) Calculate new column of cholesky decomposition. */
1320  real_t rhs[NVMAX];
1321  real_t r[NVMAX];
1322  real_t r0 = H[number*NVMAX + number];
1323 
1324  for( i=0; i<nFR; ++i )
1325  {
1326  ii = FR_idx[i];
1327  rhs[i] = H[number*NVMAX + ii];
1328  }
1329 
1330  if ( backsolveR( rhs,BT_TRUE,BT_TRUE,r ) != SUCCESSFUL_RETURN )
1332 
1333  for( i=0; i<nFR; ++i )
1334  r0 -= r[i]*r[i];
1335 
1336  /* 2) Store new column into R. */
1337  for( i=0; i<nFR; ++i )
1338  R[i*NVMAX + nFR] = r[i];
1339 
1340  if ( r0 > 0.0 )
1341  R[nFR*NVMAX + nFR] = sqrt( r0 );
1342  else
1343  {
1345  return THROWERROR( RET_HESSIAN_NOT_SPD );
1346  }
1347 
1348 
1349  return SUCCESSFUL_RETURN;
1350 }
1351 
1352 
1353 /*
1354  * b a c k s o l v e R (CODE DUPLICATED IN QProblem CLASS!!!)
1355  */
1357  real_t* const a
1358  )
1359 {
1360  /* Call standard backsolve procedure (i.e. removingBound == BT_FALSE). */
1361  return backsolveR( b,transposed,BT_FALSE,a );
1362 }
1363 
1364 
1365 /*
1366  * b a c k s o l v e R (CODE DUPLICATED IN QProblem CLASS!!!)
1367  */
1369  BooleanType removingBound,
1370  real_t* const a
1371  )
1372 {
1373  int i, j;
1374  int nR = getNZ( );
1375 
1376  real_t sum;
1377 
1378  /* if backsolve is called while removing a bound, reduce nZ by one. */
1379  if ( removingBound == BT_TRUE )
1380  --nR;
1381 
1382  /* nothing to do */
1383  if ( nR <= 0 )
1384  return SUCCESSFUL_RETURN;
1385 
1386 
1387  /* Solve Ra = b, where R might be transposed. */
1388  if ( transposed == BT_FALSE )
1389  {
1390  /* solve Ra = b */
1391  for( i=(nR-1); i>=0; --i )
1392  {
1393  sum = b[i];
1394  for( j=(i+1); j<nR; ++j )
1395  sum -= R[i*NVMAX + j] * a[j];
1396 
1397  if ( getAbs( R[i*NVMAX + i] ) > ZERO )
1398  a[i] = sum / R[i*NVMAX + i];
1399  else
1400  return THROWERROR( RET_DIV_BY_ZERO );
1401  }
1402  }
1403  else
1404  {
1405  /* solve R^T*a = b */
1406  for( i=0; i<nR; ++i )
1407  {
1408  sum = b[i];
1409 
1410  for( j=0; j<i; ++j )
1411  sum -= R[j*NVMAX + i] * a[j];
1412 
1413  if ( getAbs( R[i*NVMAX + i] ) > ZERO )
1414  a[i] = sum / R[i*NVMAX + i];
1415  else
1416  return THROWERROR( RET_DIV_BY_ZERO );
1417  }
1418  }
1419 
1420  return SUCCESSFUL_RETURN;
1421 }
1422 
1423 
1424 /*
1425  * h o t s t a r t _ d e t e r m i n e D a t a S h i f t
1426  */
1428  const real_t* const g_new, const real_t* const lb_new, const real_t* const ub_new,
1429  real_t* const delta_g, real_t* const delta_lb, real_t* const delta_ub,
1430  BooleanType& Delta_bB_isZero
1431  )
1432 {
1433  int i, ii;
1434  int nV = getNV( );
1435  int nFX = getNFX( );
1436 
1437 
1438  /* 1) Calculate shift directions. */
1439  for( i=0; i<nV; ++i )
1440  delta_g[i] = g_new[i] - g[i];
1441 
1442  if ( lb_new != 0 )
1443  {
1444  for( i=0; i<nV; ++i )
1445  delta_lb[i] = lb_new[i] - lb[i];
1446  }
1447  else
1448  {
1449  /* if no lower bounds exist, assume the new lower bounds to be -infinity */
1450  for( i=0; i<nV; ++i )
1451  delta_lb[i] = -INFTY - lb[i];
1452  }
1453 
1454  if ( ub_new != 0 )
1455  {
1456  for( i=0; i<nV; ++i )
1457  delta_ub[i] = ub_new[i] - ub[i];
1458  }
1459  else
1460  {
1461  /* if no upper bounds exist, assume the new upper bounds to be infinity */
1462  for( i=0; i<nV; ++i )
1463  delta_ub[i] = INFTY - ub[i];
1464  }
1465 
1466  /* 2) Determine if active bounds are to be shifted. */
1467  Delta_bB_isZero = BT_TRUE;
1468 
1469  for ( i=0; i<nFX; ++i )
1470  {
1471  ii = FX_idx[i];
1472 
1473  if ( ( getAbs( delta_lb[ii] ) > EPS ) || ( getAbs( delta_ub[ii] ) > EPS ) )
1474  {
1475  Delta_bB_isZero = BT_FALSE;
1476  break;
1477  }
1478  }
1479 
1480  return SUCCESSFUL_RETURN;
1481 }
1482 
1483 
1484 /*
1485  * a r e B o u n d s C o n s i s t e n t
1486  */
1487 BooleanType QProblemB::areBoundsConsistent( const real_t* const delta_lb, const real_t* const delta_ub
1488  ) const
1489 {
1490  int i;
1491 
1492  /* Check if delta_lb[i] is greater than delta_ub[i]
1493  * for a component i whose bounds are already (numerically) equal. */
1494  for( i=0; i<getNV( ); ++i )
1495  if ( ( lb[i] > ub[i] - BOUNDTOL ) && ( delta_lb[i] > delta_ub[i] + EPS ) )
1496  return BT_FALSE;
1497 
1498  return BT_TRUE;
1499 }
1500 
1501 
1502 /*
1503  * s e t u p Q P d a t a
1504  */
1505 returnValue QProblemB::setupQPdata( const real_t* const _H, const real_t* const _g,
1506  const real_t* const _lb, const real_t* const _ub
1507  )
1508 {
1509  int i, j;
1510  int nV = getNV( );
1511 
1512  /* 1) Setup Hessian matrix. */
1513  if ( _H == 0 )
1515 
1516  for( i=0; i<nV; ++i )
1517  for( j=0; j<nV; ++j )
1518  H[i*NVMAX + j] = _H[i*nV + j];
1519 
1520  /* 2) Setup gradient vector. */
1521  if ( _g == 0 )
1523 
1524  for( i=0; i<nV; ++i )
1525  g[i] = _g[i];
1526 
1527  /* 3) Setup lower bounds vector. */
1528  if ( _lb != 0 )
1529  {
1530  for( i=0; i<nV; ++i )
1531  lb[i] = _lb[i];
1532  }
1533  else
1534  {
1535  /* if no lower bounds are specified, set them to -infinity */
1536  for( i=0; i<nV; ++i )
1537  lb[i] = -INFTY;
1538  }
1539 
1540  /* 4) Setup upper bounds vector. */
1541  if ( _ub != 0 )
1542  {
1543  for( i=0; i<nV; ++i )
1544  ub[i] = _ub[i];
1545  }
1546  else
1547  {
1548  /* if no upper bounds are specified, set them to infinity */
1549  for( i=0; i<nV; ++i )
1550  ub[i] = INFTY;
1551  }
1552 
1553  //printmatrix( "H",H,nV,nV );
1554  //printmatrix( "g",g,1,nV );
1555  //printmatrix( "lb",lb,1,nV );
1556  //printmatrix( "ub",ub,1,nV );
1557 
1558  return SUCCESSFUL_RETURN;
1559 }
1560 
1561 
1562 
1563 /*****************************************************************************
1564  * P R I V A T E *
1565  *****************************************************************************/
1566 
1567 /*
1568  * h o t s t a r t _ d e t e r m i n e S t e p D i r e c t i o n
1569  */
1571  const real_t* const delta_g, const real_t* const delta_lb, const real_t* const delta_ub,
1572  BooleanType Delta_bB_isZero,
1573  real_t* const delta_xFX, real_t* const delta_xFR,
1574  real_t* const delta_yFX
1575  )
1576 {
1577  int i, j, ii, jj;
1578  int nFR = getNFR( );
1579  int nFX = getNFX( );
1580 
1581 
1582  /* initialise auxiliary vectors */
1583  real_t HMX_delta_xFX[NVMAX];
1584  for( i=0; i<nFR; ++i )
1585  HMX_delta_xFX[i] = 0.0;
1586 
1587 
1588  /* I) DETERMINE delta_xFX */
1589  if ( nFX > 0 )
1590  {
1591  for( i=0; i<nFX; ++i )
1592  {
1593  ii = FX_idx[i];
1594 
1595  if ( bounds.getStatus( ii ) == ST_LOWER )
1596  delta_xFX[i] = delta_lb[ii];
1597  else
1598  delta_xFX[i] = delta_ub[ii];
1599  }
1600  }
1601 
1602 
1603  /* II) DETERMINE delta_xFR */
1604  if ( nFR > 0 )
1605  {
1606  /* auxiliary variables */
1607  real_t delta_xFRz_TMP[NVMAX];
1608  real_t delta_xFRz_RHS[NVMAX];
1609 
1610  /* Determine delta_xFRz. */
1611  if ( Delta_bB_isZero == BT_FALSE )
1612  {
1613  for( i=0; i<nFR; ++i )
1614  {
1615  ii = FR_idx[i];
1616  for( j=0; j<nFX; ++j )
1617  {
1618  jj = FX_idx[j];
1619  HMX_delta_xFX[i] += H[ii*NVMAX + jj] * delta_xFX[j];
1620  }
1621  }
1622  }
1623 
1624  if ( Delta_bB_isZero == BT_TRUE )
1625  {
1626  for( j=0; j<nFR; ++j )
1627  {
1628  jj = FR_idx[j];
1629  delta_xFRz_RHS[j] = delta_g[jj];
1630  }
1631  }
1632  else
1633  {
1634  for( j=0; j<nFR; ++j )
1635  {
1636  jj = FR_idx[j];
1637  delta_xFRz_RHS[j] = delta_g[jj] + HMX_delta_xFX[j]; /* *ZFR */
1638  }
1639  }
1640 
1641  for( i=0; i<nFR; ++i )
1642  delta_xFR[i] = -delta_xFRz_RHS[i];
1643 
1644  if ( backsolveR( delta_xFR,BT_TRUE,delta_xFRz_TMP ) != SUCCESSFUL_RETURN )
1646 
1647  if ( backsolveR( delta_xFRz_TMP,BT_FALSE,delta_xFR ) != SUCCESSFUL_RETURN )
1649  }
1650 
1651 
1652  /* III) DETERMINE delta_yFX */
1653  if ( nFX > 0 )
1654  {
1655  for( i=0; i<nFX; ++i )
1656  {
1657  ii = FX_idx[i];
1658 
1659  delta_yFX[i] = 0.0;
1660  for( j=0; j<nFR; ++j )
1661  {
1662  jj = FR_idx[j];
1663  delta_yFX[i] += H[ii*NVMAX + jj] * delta_xFR[j];
1664  }
1665 
1666  if ( Delta_bB_isZero == BT_FALSE )
1667  {
1668  for( j=0; j<nFX; ++j )
1669  {
1670  jj = FX_idx[j];
1671  delta_yFX[i] += H[ii*NVMAX + jj] * delta_xFX[j];
1672  }
1673  }
1674 
1675  delta_yFX[i] += delta_g[ii];
1676  }
1677  }
1678 
1679  return SUCCESSFUL_RETURN;
1680 }
1681 
1682 
1683 /*
1684  * h o t s t a r t _ d e t e r m i n e S t e p L e n g t h
1685  */
1687  const real_t* const delta_lb, const real_t* const delta_ub,
1688  const real_t* const delta_xFR,
1689  const real_t* const delta_yFX,
1690  int& BC_idx, SubjectToStatus& BC_status
1691  )
1692 {
1693  int i, ii;
1694  int nFR = getNFR( );
1695  int nFX = getNFX( );
1696 
1697  real_t tau_tmp;
1698  real_t tau_new = 1.0;
1699 
1700  BC_idx = 0;
1701  BC_status = ST_UNDEFINED;
1702 
1703 
1704  /* I) DETERMINE MAXIMUM DUAL STEPLENGTH, i.e. ensure that
1705  * active dual bounds remain valid (ignoring implicitly fixed variables): */
1706  for( i=0; i<nFX; ++i )
1707  {
1708  ii = FX_idx[i];
1709 
1710  if ( bounds.getType( ii ) != ST_EQUALITY )
1711  {
1712  if ( bounds.getStatus( ii ) == ST_LOWER )
1713  {
1714  /* 1) Active lower bounds. */
1715  if ( ( delta_yFX[i] < -ZERO ) && ( y[ii] >= 0.0 ) )
1716  {
1717  tau_tmp = y[ii] / ( -delta_yFX[i] );
1718  if ( tau_tmp < tau_new )
1719  {
1720  if ( tau_tmp >= 0.0 )
1721  {
1722  tau_new = tau_tmp;
1723  BC_idx = ii;
1724  BC_status = ST_INACTIVE;
1725  }
1726  }
1727  }
1728  }
1729  else
1730  {
1731  /* 2) Active upper bounds. */
1732  if ( ( delta_yFX[i] > ZERO ) && ( y[ii] <= 0.0 ) )
1733  {
1734  tau_tmp = y[ii] / ( -delta_yFX[i] );
1735  if ( tau_tmp < tau_new )
1736  {
1737  if ( tau_tmp >= 0.0 )
1738  {
1739  tau_new = tau_tmp;
1740  BC_idx = ii;
1741  BC_status = ST_INACTIVE;
1742  }
1743  }
1744  }
1745  }
1746  }
1747  }
1748 
1749 
1750  /* II) DETERMINE MAXIMUM PRIMAL STEPLENGTH, i.e. ensure that
1751  * inactive bounds remain valid (ignoring unbounded variables). */
1752  /* 1) Inactive lower bounds. */
1753  if ( bounds.isNoLower( ) == BT_FALSE )
1754  {
1755  for( i=0; i<nFR; ++i )
1756  {
1757  ii = FR_idx[i];
1758 
1759  if ( bounds.getType( ii ) != ST_UNBOUNDED )
1760  {
1761  if ( delta_lb[ii] > delta_xFR[i] )
1762  {
1763  if ( x[ii] > lb[ii] )
1764  tau_tmp = ( x[ii] - lb[ii] ) / ( delta_lb[ii] - delta_xFR[i] );
1765  else
1766  tau_tmp = 0.0;
1767 
1768  if ( tau_tmp < tau_new )
1769  {
1770  if ( tau_tmp >= 0.0 )
1771  {
1772  tau_new = tau_tmp;
1773  BC_idx = ii;
1774  BC_status = ST_LOWER;
1775  }
1776  }
1777  }
1778  }
1779  }
1780  }
1781 
1782  /* 2) Inactive upper bounds. */
1783  if ( bounds.isNoUpper( ) == BT_FALSE )
1784  {
1785  for( i=0; i<nFR; ++i )
1786  {
1787  ii = FR_idx[i];
1788 
1789  if ( bounds.getType( ii ) != ST_UNBOUNDED )
1790  {
1791  if ( delta_ub[ii] < delta_xFR[i] )
1792  {
1793  if ( x[ii] < ub[ii] )
1794  tau_tmp = ( x[ii] - ub[ii] ) / ( delta_ub[ii] - delta_xFR[i] );
1795  else
1796  tau_tmp = 0.0;
1797 
1798  if ( tau_tmp < tau_new )
1799  {
1800  if ( tau_tmp >= 0.0 )
1801  {
1802  tau_new = tau_tmp;
1803  BC_idx = ii;
1804  BC_status = ST_UPPER;
1805  }
1806  }
1807  }
1808  }
1809  }
1810  }
1811 
1812 
1813  /* III) SET MAXIMUM HOMOTOPY STEPLENGTH */
1814  tau = tau_new;
1815 
1816  if ( printlevel == PL_HIGH )
1817  {
1818  #ifdef PC_DEBUG
1819  char messageString[80];
1820 
1821  if ( BC_status == ST_UNDEFINED )
1822  sprintf( messageString,"Stepsize is %.6e!",tau );
1823  else
1824  sprintf( messageString,"Stepsize is %.6e! (BC_idx = %d, BC_status = %d)",tau,BC_idx,BC_status );
1825 
1827  #endif
1828  }
1829 
1830  return SUCCESSFUL_RETURN;
1831 }
1832 
1833 
1834 /*
1835  * h o t s t a r t _ p e r f o r m S t e p
1836  */
1837 returnValue QProblemB::hotstart_performStep( const int* const FR_idx, const int* const FX_idx,
1838  const real_t* const delta_g, const real_t* const delta_lb, const real_t* const delta_ub,
1839  const real_t* const delta_xFX, const real_t* const delta_xFR,
1840  const real_t* const delta_yFX,
1841  int BC_idx, SubjectToStatus BC_status
1842  )
1843 {
1844  int i, ii;
1845  int nV = getNV( );
1846  int nFR = getNFR( );
1847  int nFX = getNFX( );
1848 
1849 
1850  /* I) CHECK BOUNDS' CONSISTENCY */
1851  if ( areBoundsConsistent( delta_lb,delta_ub ) == BT_FALSE )
1852  {
1853  infeasible = BT_TRUE;
1854  tau = 0.0;
1855 
1856  return THROWERROR( RET_QP_INFEASIBLE );
1857  }
1858 
1859 
1860  /* II) GO TO ACTIVE SET CHANGE */
1861  if ( tau > ZERO )
1862  {
1863  /* 1) Perform step in primal und dual space. */
1864  for( i=0; i<nFR; ++i )
1865  {
1866  ii = FR_idx[i];
1867  x[ii] += tau*delta_xFR[i];
1868  }
1869 
1870  for( i=0; i<nFX; ++i )
1871  {
1872  ii = FX_idx[i];
1873  x[ii] += tau*delta_xFX[i];
1874  y[ii] += tau*delta_yFX[i];
1875  }
1876 
1877  /* 2) Shift QP data. */
1878  for( i=0; i<nV; ++i )
1879  {
1880  g[i] += tau*delta_g[i];
1881  lb[i] += tau*delta_lb[i];
1882  ub[i] += tau*delta_ub[i];
1883  }
1884  }
1885  else
1886  {
1887  /* print a stepsize warning if stepsize is zero */
1888  #ifdef PC_DEBUG
1889  char messageString[80];
1890  sprintf( messageString,"Stepsize is %.6e",tau );
1892  #endif
1893  }
1894 
1895 
1896  /* setup output preferences */
1897  #ifdef PC_DEBUG
1898  char messageString[80];
1899  VisibilityStatus visibilityStatus;
1900 
1901  if ( printlevel == PL_HIGH )
1902  visibilityStatus = VS_VISIBLE;
1903  else
1904  visibilityStatus = VS_HIDDEN;
1905  #endif
1906 
1907 
1908  /* III) UPDATE ACTIVE SET */
1909  switch ( BC_status )
1910  {
1911  /* Optimal solution found as no working set change detected. */
1912  case ST_UNDEFINED:
1914 
1915 
1916  /* Remove one variable from active set. */
1917  case ST_INACTIVE:
1918  #ifdef PC_DEBUG
1919  sprintf( messageString,"bound no. %d.", BC_idx );
1921  #endif
1922 
1923  if ( removeBound( BC_idx,BT_TRUE ) != SUCCESSFUL_RETURN )
1925 
1926  y[BC_idx] = 0.0;
1927  break;
1928 
1929 
1930  /* Add one variable to active set. */
1931  default:
1932  #ifdef PC_DEBUG
1933  if ( BC_status == ST_LOWER )
1934  sprintf( messageString,"lower bound no. %d.", BC_idx );
1935  else
1936  sprintf( messageString,"upper bound no. %d.", BC_idx );
1938  #endif
1939 
1940  if ( addBound( BC_idx,BC_status,BT_TRUE ) != SUCCESSFUL_RETURN )
1942  break;
1943  }
1944 
1945  return SUCCESSFUL_RETURN;
1946 }
1947 
1948 
1949 #ifdef PC_DEBUG /* Define print functions only for debugging! */
1950 
1951 /*
1952  * p r i n t I t e r a t i o n
1953  */
1954 returnValue QProblemB::printIteration( int iteration,
1955  int BC_idx, SubjectToStatus BC_status
1956  )
1957 {
1958  char myPrintfString[160];
1959 
1960  /* consistency check */
1961  if ( iteration < 0 )
1963 
1964  /* nothing to do */
1965  if ( printlevel != PL_MEDIUM )
1966  return SUCCESSFUL_RETURN;
1967 
1968 
1969  /* 1) Print header at first iteration. */
1970  if ( iteration == 0 )
1971  {
1972  sprintf( myPrintfString,"\n############## qpOASES -- QP NO.%4.1d ###############\n", count );
1973  myPrintf( myPrintfString );
1974 
1975  sprintf( myPrintfString," Iter | StepLength | Info | nFX \n" );
1976  myPrintf( myPrintfString );
1977  }
1978 
1979  /* 2) Print iteration line. */
1980  if ( BC_status == ST_UNDEFINED )
1981  {
1982  sprintf( myPrintfString," %4.1d | %1.5e | QP SOLVED | %4.1d \n", iteration,tau,getNFX( ) );
1983  myPrintf( myPrintfString );
1984  }
1985  else
1986  {
1987  char info[8];
1988 
1989  if ( BC_status == ST_INACTIVE )
1990  sprintf( info,"REM BND" );
1991  else
1992  sprintf( info,"ADD BND" );
1993 
1994  sprintf( myPrintfString," %4.1d | %1.5e | %s%4.1d | %4.1d \n", iteration,tau,info,BC_idx,getNFX( ) );
1995  myPrintf( myPrintfString );
1996  }
1997 
1998  return SUCCESSFUL_RETURN;
1999 }
2000 
2001 #endif /* PC_DEBUG */
2002 
2003 
2004 
2005 /*
2006  * c h e c k K K T c o n d i t i o n s
2007  */
2009 {
2010  #ifdef __PERFORM_KKT_TEST__
2011 
2012  int i, j;
2013  int nV = getNV( );
2014 
2015  real_t tmp;
2016  real_t maxKKTviolation = 0.0;
2017 
2018 
2019  /* 1) Check for Hx + g - y*A' = 0 (here: A = Id). */
2020  for( i=0; i<nV; ++i )
2021  {
2022  tmp = g[i];
2023 
2024  for( j=0; j<nV; ++j )
2025  tmp += H[i*nV + j] * x[j];
2026 
2027  tmp -= y[i];
2028 
2029  if ( getAbs( tmp ) > maxKKTviolation )
2030  maxKKTviolation = getAbs( tmp );
2031  }
2032 
2033  /* 2) Check for lb <= x <= ub. */
2034  for( i=0; i<nV; ++i )
2035  {
2036  if ( lb[i] - x[i] > maxKKTviolation )
2037  maxKKTviolation = lb[i] - x[i];
2038 
2039  if ( x[i] - ub[i] > maxKKTviolation )
2040  maxKKTviolation = x[i] - ub[i];
2041  }
2042 
2043  /* 3) Check for correct sign of y and for complementary slackness. */
2044  for( i=0; i<nV; ++i )
2045  {
2046  switch ( bounds.getStatus( i ) )
2047  {
2048  case ST_LOWER:
2049  if ( -y[i] > maxKKTviolation )
2050  maxKKTviolation = -y[i];
2051  if ( getAbs( ( x[i] - lb[i] ) * y[i] ) > maxKKTviolation )
2052  maxKKTviolation = getAbs( ( x[i] - lb[i] ) * y[i] );
2053  break;
2054 
2055  case ST_UPPER:
2056  if ( y[i] > maxKKTviolation )
2057  maxKKTviolation = y[i];
2058  if ( getAbs( ( ub[i] - x[i] ) * y[i] ) > maxKKTviolation )
2059  maxKKTviolation = getAbs( ( ub[i] - x[i] ) * y[i] );
2060  break;
2061 
2062  default: /* inactive */
2063  if ( getAbs( y[i] ) > maxKKTviolation )
2064  maxKKTviolation = getAbs( y[i] );
2065  break;
2066  }
2067  }
2068 
2069  if ( maxKKTviolation > CRITICALACCURACY )
2070  return RET_NO_SOLUTION;
2071 
2072  if ( maxKKTviolation > DESIREDACCURACY )
2073  return RET_INACCURATE_SOLUTION;
2074 
2075  #endif /* __PERFORM_KKT_TEST__ */
2076 
2077  return SUCCESSFUL_RETURN;
2078 }
2079 
2080 
2081 
2082 /*
2083  * end of file
2084  */
void setNoLower(BooleanType _status)
returnValue setType(int i, SubjectToType value)
IntermediateState sqrt(const Expression &arg)
BooleanType isInfeasible() const
#define ST_LOWER
Indexlist * getFree()
real_t getAbs(real_t x)
#define __LINE__
BooleanType isNoLower() const
Implements the online active set strategy for box-constrained QPs.
BooleanType isUnbounded() const
const double INFTY
int getNFX()
void computeGivens(real_t xold, real_t yold, real_t &xnew, real_t &ynew, real_t &c, real_t &s) const
BEGIN_NAMESPACE_ACADO const double EPS
returnValue obtainAuxiliaryWorkingSet(const real_t *const xOpt, const real_t *const yOpt, const Bounds *const guessedBounds, Bounds *auxiliaryBounds) const
returnValue throwInfo(returnValue Inumber, const char *additionaltext, const char *functionname, const char *filename, const unsigned long linenumber, VisibilityStatus localVisibilityStatus)
Allows to pass back messages to the calling function.
const double ZERO
returnValue setupAuxiliaryWorkingSet(const Bounds *const auxiliaryBounds, BooleanType setupAfresh)
#define PL_MEDIUM
int getNV() const
returnValue setupAuxiliaryQPsolution(const real_t *const xOpt, const real_t *const yOpt)
returnValue backsolveR(const real_t *const b, BooleanType transposed, real_t *const a)
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)
#define __FUNCTION__
returnValue throwWarning(returnValue Wnumber, const char *additionaltext, const char *functionname, const char *filename, const unsigned long linenumber, VisibilityStatus localVisibilityStatus)
const double BOUNDTOL
#define HST_IDENTITY
#define PL_NONE
returnValue myPrintf(const char *s)
int getNV() const
#define ST_UNDEFINED
#define ST_INACTIVE
returnValue setupBound(int _number, SubjectToStatus _status)
#define PL_HIGH
returnValue setNUV(int n)
returnValue setNBV(int n)
SubjectToStatus getStatus(int i) const
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)
returnValue addBound(int number, SubjectToStatus B_status, BooleanType updateCholesky)
returnValue hotstart_determineStepLength(const int *const FR_idx, const int *const FX_idx, const real_t *const delta_lb, const real_t *const delta_ub, const real_t *const delta_xFR, const real_t *const delta_yFX, int &BC_idx, SubjectToStatus &BC_status)
returnValue setupQPdata(const real_t *const _H, const real_t *const _g, const real_t *const _lb, const real_t *const _ub)
returnValue setNFV(int n)
void setInfoVisibilityStatus(VisibilityStatus _infoVisibility)
returnValue printIteration(int iteration, int BC_idx, SubjectToStatus BC_status)
BooleanType areBoundsConsistent(const real_t *const delta_lb, const real_t *const delta_ub) const
returnValue hotstart_performStep(const int *const FR_idx, const int *const FX_idx, const real_t *const delta_g, const real_t *const delta_lb, const real_t *const delta_ub, const real_t *const delta_xFX, const real_t *const delta_xFR, const real_t *const delta_yFX, int BC_idx, SubjectToStatus BC_status)
int getLength()
int getNFR()
#define PL_LOW
void rhs(const real_t *x, real_t *f)
void printmatrix(char *name, double *A, int m, int n)
PrintLevel
SubjectToType getType(int i) const
BooleanType isNoUpper() const
#define HST_POSDEF_NULLSPACE
QProblemStatus getStatus() const
#define BT_TRUE
Definition: acado_types.hpp:47
void setErrorVisibilityStatus(VisibilityStatus _errorVisibility)
#define HST_SEMIDEF
returnValue hotstart_determineDataShift(const int *const FX_idx, const real_t *const g_new, const real_t *const lb_new, const real_t *const ub_new, real_t *const delta_g, real_t *const delta_lb, real_t *const delta_ub, BooleanType &Delta_bB_isZero)
returnValue removeBound(int number, BooleanType updateCholesky)
void setNoUpper(BooleanType _status)
#define __FILE__
#define BT_FALSE
Definition: acado_types.hpp:49
void setWarningVisibilityStatus(VisibilityStatus _warningVisibility)
Manages working sets of bounds (= box constraints).
returnValue hotstart_determineStepDirection(const int *const FR_idx, const int *const FX_idx, const real_t *const delta_g, const real_t *const delta_lb, const real_t *const delta_ub, BooleanType Delta_bB_isZero, real_t *const delta_xFX, real_t *const delta_xFR, real_t *const delta_yFX)
#define ST_UPPER
double real_t
Definition: AD_test.c:10
void applyGivens(real_t c, real_t s, real_t xold, real_t yold, real_t &xnew, real_t &ynew) const
returnValue solveInitialQP(const real_t *const xOpt, const real_t *const yOpt, const Bounds *const guessedBounds, int &nWSR, real_t *const cputime)
Indexlist * getFixed()
const double BOUNDRELAXATION
returnValue moveFreeToFixed(int _number, SubjectToStatus _status)


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