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