00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00035 #include <QProblemB.hpp>
00036
00037 #include <stdio.h>
00038
00039 void printmatrix(char *name, double *A, int m, int n) {
00040 int i, j;
00041
00042 printf("%s = [...\n", name);
00043 for (i = 0; i < m; i++) {
00044 for (j = 0; j < n; j++)
00045 printf(" % 9.4f", A[i*n+j]);
00046 printf(",\n");
00047 }
00048 printf("];\n");
00049 }
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 QProblemB::QProblemB( )
00062 {
00063
00064 getGlobalMessageHandler( )->reset( );
00065
00066 bounds.init( 0 );
00067
00068 tau = 0.0;
00069
00070 hessianType = HST_POSDEF_NULLSPACE;
00071 infeasible = BT_FALSE;
00072 unbounded = BT_FALSE;
00073
00074 status = QPS_NOTINITIALISED;
00075
00076 #ifdef PC_DEBUG
00077 printlevel = PL_MEDIUM;
00078 setPrintLevel( PL_MEDIUM );
00079 #else
00080 printlevel = QPOASES_PRINTLEVEL;
00081 #endif
00082
00083 count = 0;
00084 }
00085
00086
00087
00088
00089
00090 QProblemB::QProblemB( int _nV )
00091 {
00092
00093 if ( _nV <= 0 )
00094 {
00095 _nV = 1;
00096 THROWERROR( RET_INVALID_ARGUMENTS );
00097 }
00098
00099
00100 getGlobalMessageHandler( )->reset( );
00101
00102 bounds.init( _nV );
00103
00104 tau = 0.0;
00105
00106 hessianType = HST_POSDEF_NULLSPACE;
00107 infeasible = BT_FALSE;
00108 unbounded = BT_FALSE;
00109
00110 status = QPS_NOTINITIALISED;
00111
00112 #ifdef PC_DEBUG
00113 printlevel = PL_MEDIUM;
00114 setPrintLevel( PL_MEDIUM );
00115 #else
00116 printlevel = QPOASES_PRINTLEVEL;
00117 #endif
00118
00119 count = 0;
00120 }
00121
00122
00123
00124
00125
00126 QProblemB::QProblemB( const QProblemB& rhs )
00127 {
00128 int i, j;
00129
00130 int _nV = rhs.bounds.getNV( );
00131
00132 for( i=0; i<_nV; ++i )
00133 for( j=0; j<_nV; ++j )
00134 H[i*NVMAX + j] = rhs.H[i*NVMAX + j];
00135
00136 for( i=0; i<_nV; ++i )
00137 g[i] = rhs.g[i];
00138
00139 for( i=0; i<_nV; ++i )
00140 lb[i] = rhs.lb[i];
00141
00142 for( i=0; i<_nV; ++i )
00143 ub[i] = rhs.ub[i];
00144
00145
00146 bounds = rhs.bounds;
00147
00148 for( i=0; i<_nV; ++i )
00149 for( j=0; j<_nV; ++j )
00150 R[i*NVMAX + j] = rhs.R[i*NVMAX + j];
00151
00152 for( i=0; i<_nV; ++i )
00153 x[i] = rhs.x[i];
00154
00155 for( i=0; i<_nV; ++i )
00156 y[i] = rhs.y[i];
00157
00158 tau = rhs.tau;
00159
00160 hessianType = rhs.hessianType;
00161 infeasible = rhs.infeasible;
00162 unbounded = rhs.unbounded;
00163
00164 status = rhs.status;
00165
00166 printlevel = rhs.printlevel;
00167
00168 count = rhs.count;
00169 }
00170
00171
00172
00173
00174
00175 QProblemB::~QProblemB( )
00176 {
00177 }
00178
00179
00180
00181
00182
00183 QProblemB& QProblemB::operator=( const QProblemB& rhs )
00184 {
00185 int i, j;
00186
00187 if ( this != &rhs )
00188 {
00189 int _nV = rhs.bounds.getNV( );
00190
00191 for( i=0; i<_nV; ++i )
00192 for( j=0; j<_nV; ++j )
00193 H[i*NVMAX + j] = rhs.H[i*NVMAX + j];
00194
00195 for( i=0; i<_nV; ++i )
00196 g[i] = rhs.g[i];
00197
00198 for( i=0; i<_nV; ++i )
00199 lb[i] = rhs.lb[i];
00200
00201 for( i=0; i<_nV; ++i )
00202 ub[i] = rhs.ub[i];
00203
00204 bounds = rhs.bounds;
00205
00206 for( i=0; i<_nV; ++i )
00207 for( j=0; j<_nV; ++j )
00208 R[i*NVMAX + j] = rhs.R[i*NVMAX + j];
00209
00210
00211 for( i=0; i<_nV; ++i )
00212 x[i] = rhs.x[i];
00213
00214 for( i=0; i<_nV; ++i )
00215 y[i] = rhs.y[i];
00216
00217 tau = rhs.tau;
00218
00219 hessianType = rhs.hessianType;
00220 infeasible = rhs.infeasible;
00221 unbounded = rhs.unbounded;
00222
00223 status = rhs.status;
00224
00225 printlevel = rhs.printlevel;
00226 setPrintLevel( rhs.printlevel );
00227
00228 count = rhs.count;
00229 }
00230
00231 return *this;
00232 }
00233
00234
00235
00236
00237
00238 returnValue QProblemB::reset( )
00239 {
00240 int i, j;
00241 int nV = getNV( );
00242
00243
00244
00245 bounds.init( nV );
00246
00247
00248 for( i=0; i<nV; ++i )
00249 for( j=0; j<nV; ++j )
00250 R[i*NVMAX + j] = 0.0;
00251
00252
00253 tau = 0.0;
00254
00255 hessianType = HST_POSDEF_NULLSPACE;
00256 infeasible = BT_FALSE;
00257 unbounded = BT_FALSE;
00258
00259 status = QPS_NOTINITIALISED;
00260
00261 return SUCCESSFUL_RETURN;
00262 }
00263
00264
00265
00266
00267
00268 returnValue QProblemB::init( const real_t* const _H, const real_t* const _g,
00269 const real_t* const _lb, const real_t* const _ub,
00270 int& nWSR, const real_t* const yOpt, real_t* const cputime
00271 )
00272 {
00273
00274 if ( setupQPdata( _H,_g,_lb,_ub ) != SUCCESSFUL_RETURN )
00275 return THROWERROR( RET_INVALID_ARGUMENTS );
00276
00277
00278 return solveInitialQP( 0,yOpt,0, nWSR,cputime );
00279 }
00280
00281
00282
00283
00284
00285 returnValue QProblemB::hotstart( const real_t* const g_new, const real_t* const lb_new, const real_t* const ub_new,
00286 int& nWSR, real_t* const cputime
00287 )
00288 {
00289 int l;
00290
00291
00292 if ( ( getStatus( ) == QPS_NOTINITIALISED ) ||
00293 ( getStatus( ) == QPS_PREPARINGAUXILIARYQP ) ||
00294 ( getStatus( ) == QPS_PERFORMINGHOMOTOPY ) )
00295 {
00296 return THROWERROR( RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED );
00297 }
00298
00299
00300 real_t starttime = 0.0;
00301 if ( cputime != 0 )
00302 starttime = getCPUtime( );
00303
00304
00305
00306
00307 infeasible = BT_FALSE;
00308 unbounded = BT_FALSE;
00309
00310 ++count;
00311
00312
00313 returnValue returnvalue;
00314 BooleanType Delta_bB_isZero;
00315
00316 int FR_idx[NVMAX];
00317 int FX_idx[NVMAX];
00318
00319 real_t delta_g[NVMAX];
00320 real_t delta_lb[NVMAX];
00321 real_t delta_ub[NVMAX];
00322
00323 real_t delta_xFR[NVMAX];
00324 real_t delta_xFX[NVMAX];
00325 real_t delta_yFX[NVMAX];
00326
00327 int BC_idx;
00328 SubjectToStatus BC_status;
00329
00330 #ifdef PC_DEBUG
00331 char messageString[80];
00332 #endif
00333
00334
00335 for( l=0; l<nWSR; ++l )
00336 {
00337 status = QPS_PERFORMINGHOMOTOPY;
00338
00339 if ( printlevel == PL_HIGH )
00340 {
00341 #ifdef PC_DEBUG
00342 sprintf( messageString,"%d ...",l );
00343 getGlobalMessageHandler( )->throwInfo( RET_ITERATION_STARTED,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
00344 #endif
00345 }
00346
00347
00348 if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
00349 return THROWERROR( RET_HOTSTART_FAILED );
00350
00351 if ( bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
00352 return THROWERROR( RET_HOTSTART_FAILED );
00353
00354
00355 returnvalue = hotstart_determineDataShift( FX_idx,
00356 g_new,lb_new,ub_new,
00357 delta_g,delta_lb,delta_ub,
00358 Delta_bB_isZero
00359 );
00360 if ( returnvalue != SUCCESSFUL_RETURN )
00361 {
00362 nWSR = l;
00363 THROWERROR( RET_SHIFT_DETERMINATION_FAILED );
00364 return returnvalue;
00365 }
00366
00367
00368 returnvalue = hotstart_determineStepDirection( FR_idx,FX_idx,
00369 delta_g,delta_lb,delta_ub,
00370 Delta_bB_isZero,
00371 delta_xFX,delta_xFR,delta_yFX
00372 );
00373 if ( returnvalue != SUCCESSFUL_RETURN )
00374 {
00375 nWSR = l;
00376 THROWERROR( RET_STEPDIRECTION_DETERMINATION_FAILED );
00377 return returnvalue;
00378 }
00379
00380
00381
00382 returnvalue = hotstart_determineStepLength( FR_idx,FX_idx,
00383 delta_lb,delta_ub,
00384 delta_xFR,delta_yFX,
00385 BC_idx,BC_status );
00386 if ( returnvalue != SUCCESSFUL_RETURN )
00387 {
00388 nWSR = l;
00389 THROWERROR( RET_STEPLENGTH_DETERMINATION_FAILED );
00390 return returnvalue;
00391 }
00392
00393
00394 returnvalue = hotstart_performStep( FR_idx,FX_idx,
00395 delta_g,delta_lb,delta_ub,
00396 delta_xFX,delta_xFR,delta_yFX,
00397 BC_idx,BC_status
00398 );
00399
00400
00401 if ( returnvalue != SUCCESSFUL_RETURN )
00402 {
00403 nWSR = l;
00404
00405
00406 if ( cputime != 0 )
00407 *cputime = getCPUtime( ) - starttime;
00408
00409
00410 if ( returnvalue == RET_OPTIMAL_SOLUTION_FOUND )
00411 {
00412 status = QPS_SOLVED;
00413
00414 if ( printlevel == PL_HIGH )
00415 THROWINFO( RET_OPTIMAL_SOLUTION_FOUND );
00416
00417 #ifdef PC_DEBUG
00418 if ( printIteration( l,BC_idx,BC_status ) != SUCCESSFUL_RETURN )
00419 THROWERROR( RET_PRINT_ITERATION_FAILED );
00420 #endif
00421
00422
00423 return checkKKTconditions( );
00424 }
00425 else
00426 {
00427
00428 if ( infeasible == BT_TRUE )
00429 {
00430 status = QPS_HOMOTOPYQPSOLVED;
00431 return THROWERROR( RET_HOTSTART_STOPPED_INFEASIBILITY );
00432 }
00433
00434
00435 if ( unbounded == BT_TRUE )
00436 return THROWERROR( RET_HOTSTART_STOPPED_UNBOUNDEDNESS );
00437
00438
00439 THROWERROR( RET_HOMOTOPY_STEP_FAILED );
00440 return returnvalue;
00441 }
00442 }
00443
00444
00445 status = QPS_HOMOTOPYQPSOLVED;
00446
00447 #ifdef PC_DEBUG
00448 if ( printIteration( l,BC_idx,BC_status ) != SUCCESSFUL_RETURN )
00449 THROWERROR( RET_PRINT_ITERATION_FAILED );
00450 #endif
00451 }
00452
00453
00454
00455 if ( cputime != 0 )
00456 *cputime = getCPUtime( ) - starttime;
00457
00458
00459
00460
00461 if ( printlevel == PL_HIGH )
00462 {
00463 #ifdef PC_DEBUG
00464 sprintf( messageString,"(nWSR = %d)",nWSR );
00465 return getGlobalMessageHandler( )->throwWarning( RET_MAX_NWSR_REACHED,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
00466 #endif
00467 }
00468
00469
00470 returnValue returnvalueKKTcheck = checkKKTconditions( );
00471
00472 if ( returnvalueKKTcheck != SUCCESSFUL_RETURN )
00473 return returnvalueKKTcheck;
00474 else
00475 return RET_MAX_NWSR_REACHED;
00476 }
00477
00478
00479
00480
00481
00482 int QProblemB::getNZ( )
00483 {
00484
00485 return bounds.getFree( )->getLength( );
00486 }
00487
00488
00489
00490
00491
00492 real_t QProblemB::getObjVal( ) const
00493 {
00494 real_t objVal;
00495
00496
00497
00498 if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
00499 ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
00500 ( getStatus( ) == QPS_SOLVED ) )
00501 {
00502 objVal = getObjVal( x );
00503 }
00504 else
00505 {
00506 objVal = INFTY;
00507 }
00508
00509 return objVal;
00510 }
00511
00512
00513
00514
00515
00516 real_t QProblemB::getObjVal( const real_t* const _x ) const
00517 {
00518 int i, j;
00519 int nV = getNV( );
00520
00521 real_t obj_tmp = 0.0;
00522
00523 for( i=0; i<nV; ++i )
00524 {
00525 obj_tmp += _x[i]*g[i];
00526
00527 for( j=0; j<nV; ++j )
00528 obj_tmp += 0.5*_x[i]*H[i*NVMAX + j]*_x[j];
00529 }
00530
00531 return obj_tmp;
00532 }
00533
00534
00535
00536
00537
00538 returnValue QProblemB::getPrimalSolution( real_t* const xOpt ) const
00539 {
00540 int i;
00541
00542
00543
00544 if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
00545 ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
00546 ( getStatus( ) == QPS_SOLVED ) )
00547 {
00548 for( i=0; i<getNV( ); ++i )
00549 xOpt[i] = x[i];
00550
00551 return SUCCESSFUL_RETURN;
00552 }
00553 else
00554 {
00555 return RET_QP_NOT_SOLVED;
00556 }
00557 }
00558
00559
00560
00561
00562
00563 returnValue QProblemB::getDualSolution( real_t* const yOpt ) const
00564 {
00565 int i;
00566
00567
00568
00569 if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
00570 ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
00571 ( getStatus( ) == QPS_SOLVED ) )
00572 {
00573 for( i=0; i<getNV( ); ++i )
00574 yOpt[i] = y[i];
00575
00576 return SUCCESSFUL_RETURN;
00577 }
00578 else
00579 {
00580 return RET_QP_NOT_SOLVED;
00581 }
00582 }
00583
00584
00585
00586
00587
00588 returnValue QProblemB::setPrintLevel( PrintLevel _printlevel )
00589 {
00590 #ifndef __MATLAB__
00591 if ( ( printlevel >= PL_MEDIUM ) && ( printlevel != _printlevel ) )
00592 THROWINFO( RET_PRINTLEVEL_CHANGED );
00593 #endif
00594
00595 printlevel = _printlevel;
00596
00597
00598 switch ( printlevel )
00599 {
00600 case PL_NONE:
00601 getGlobalMessageHandler( )->setErrorVisibilityStatus( VS_HIDDEN );
00602 getGlobalMessageHandler( )->setWarningVisibilityStatus( VS_HIDDEN );
00603 getGlobalMessageHandler( )->setInfoVisibilityStatus( VS_HIDDEN );
00604 break;
00605
00606 case PL_LOW:
00607 getGlobalMessageHandler( )->setErrorVisibilityStatus( VS_VISIBLE );
00608 getGlobalMessageHandler( )->setWarningVisibilityStatus( VS_HIDDEN );
00609 getGlobalMessageHandler( )->setInfoVisibilityStatus( VS_HIDDEN );
00610 break;
00611
00612 default:
00613 getGlobalMessageHandler( )->setErrorVisibilityStatus( VS_VISIBLE );
00614 getGlobalMessageHandler( )->setWarningVisibilityStatus( VS_VISIBLE );
00615 getGlobalMessageHandler( )->setInfoVisibilityStatus( VS_VISIBLE );
00616 break;
00617 }
00618
00619 return SUCCESSFUL_RETURN;
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 returnValue QProblemB::checkForIdentityHessian( )
00632 {
00633 int i, j;
00634 int nV = getNV( );
00635
00636
00637
00638 if ( hessianType == HST_IDENTITY )
00639 return SUCCESSFUL_RETURN;
00640
00641
00642
00643 for ( i=0; i<nV; ++i )
00644 if ( getAbs( H[i*NVMAX + i] - 1.0 ) > EPS )
00645 return SUCCESSFUL_RETURN;
00646
00647 for ( i=0; i<nV; ++i )
00648 {
00649 for ( j=0; j<i; ++j )
00650 if ( ( getAbs( H[i*NVMAX + j] ) > EPS ) || ( getAbs( H[j*NVMAX + i] ) > EPS ) )
00651 return SUCCESSFUL_RETURN;
00652 }
00653
00654
00655 hessianType = HST_IDENTITY;
00656
00657 return SUCCESSFUL_RETURN;
00658 }
00659
00660
00661
00662
00663
00664 returnValue QProblemB::setupSubjectToType( )
00665 {
00666 int i;
00667 int nV = getNV( );
00668
00669
00670
00671 bounds.setNoLower( BT_TRUE );
00672 for( i=0; i<nV; ++i )
00673 if ( lb[i] > -INFTY )
00674 {
00675 bounds.setNoLower( BT_FALSE );
00676 break;
00677 }
00678
00679
00680 bounds.setNoUpper( BT_TRUE );
00681 for( i=0; i<nV; ++i )
00682 if ( ub[i] < INFTY )
00683 {
00684 bounds.setNoUpper( BT_FALSE );
00685 break;
00686 }
00687
00688
00689 int nFV = 0;
00690 int nUV = 0;
00691
00692 for( i=0; i<nV; ++i )
00693 if ( ( lb[i] < -INFTY + BOUNDTOL ) && ( ub[i] > INFTY - BOUNDTOL ) )
00694 {
00695 bounds.setType( i,ST_UNBOUNDED );
00696 ++nUV;
00697 }
00698 else
00699 {
00700 if ( lb[i] > ub[i] - BOUNDTOL )
00701 {
00702 bounds.setType( i,ST_EQUALITY );
00703 ++nFV;
00704 }
00705 else
00706 {
00707 bounds.setType( i,ST_BOUNDED );
00708 }
00709 }
00710
00711
00712 bounds.setNFV( nFV );
00713 bounds.setNUV( nUV );
00714 bounds.setNBV( nV - nFV - nUV );
00715
00716 return SUCCESSFUL_RETURN;
00717 }
00718
00719
00720
00721
00722
00723 returnValue QProblemB::setupCholeskyDecomposition( )
00724 {
00725 int i, j, k, ii, jj;
00726 int nV = getNV( );
00727 int nFR = getNFR( );
00728
00729
00730 for( i=0; i<nV; ++i )
00731 for( j=0; j<nV; ++j )
00732 R[i*NVMAX + j] = 0.0;
00733
00734
00735 if ( hessianType == HST_IDENTITY )
00736 {
00737
00738 for( i=0; i<nFR; ++i )
00739 R[i*NVMAX + i] = 1.0;
00740 }
00741 else
00742 {
00743 if ( nFR > 0 )
00744 {
00745 int FR_idx[NVMAX];
00746 if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
00747 return THROWERROR( RET_INDEXLIST_CORRUPTED );
00748
00749
00750 real_t sum;
00751
00752 for( i=0; i<nFR; ++i )
00753 {
00754
00755 ii = FR_idx[i];
00756 sum = H[ii*NVMAX + ii];
00757
00758 for( k=(i-1); k>=0; --k )
00759 sum -= R[k*NVMAX + i] * R[k*NVMAX + i];
00760
00761 if ( sum > 0.0 )
00762 R[i*NVMAX + i] = sqrt( sum );
00763 else
00764 {
00765 hessianType = HST_SEMIDEF;
00766 return THROWERROR( RET_HESSIAN_NOT_SPD );
00767 }
00768
00769
00770 for( j=(i+1); j<nFR; ++j )
00771 {
00772 jj = FR_idx[j];
00773 sum = H[jj*NVMAX + ii];
00774
00775 for( k=(i-1); k>=0; --k )
00776 sum -= R[k*NVMAX + i] * R[k*NVMAX + j];
00777
00778 R[i*NVMAX + j] = sum / R[i*NVMAX + i];
00779 }
00780 }
00781 }
00782 }
00783
00784 return SUCCESSFUL_RETURN;
00785 }
00786
00787
00788
00789
00790
00791 returnValue QProblemB::solveInitialQP( const real_t* const xOpt, const real_t* const yOpt,
00792 const Bounds* const guessedBounds,
00793 int& nWSR, real_t* const cputime
00794 )
00795 {
00796 int i;
00797 int nV = getNV( );
00798
00799
00800
00801 real_t starttime = 0.0;
00802 if ( cputime != 0 )
00803 starttime = getCPUtime( );
00804
00805
00806 status = QPS_NOTINITIALISED;
00807
00808
00809
00810 if ( checkForIdentityHessian( ) != SUCCESSFUL_RETURN )
00811 return THROWERROR( RET_INIT_FAILED );
00812
00813
00814 if ( setupSubjectToType( ) != SUCCESSFUL_RETURN )
00815 return THROWERROR( RET_INIT_FAILED );
00816
00817 status = QPS_PREPARINGAUXILIARYQP;
00818
00819
00820
00821
00822 if ( bounds.setupAllFree( ) != SUCCESSFUL_RETURN )
00823 return THROWERROR( RET_INIT_FAILED );
00824
00825
00826 if ( setupAuxiliaryQPsolution( xOpt,yOpt ) != SUCCESSFUL_RETURN )
00827 return THROWERROR( RET_INIT_FAILED );
00828
00829
00830
00831 static Bounds auxiliaryBounds;
00832
00833 auxiliaryBounds.init( nV );
00834
00835 if ( obtainAuxiliaryWorkingSet( xOpt,yOpt,guessedBounds, &auxiliaryBounds ) != SUCCESSFUL_RETURN )
00836 return THROWERROR( RET_INIT_FAILED );
00837
00838
00839 if ( setupAuxiliaryWorkingSet( &auxiliaryBounds,BT_TRUE ) != SUCCESSFUL_RETURN )
00840 return THROWERROR( RET_INIT_FAILED );
00841
00842 if ( setupCholeskyDecomposition( ) != SUCCESSFUL_RETURN )
00843 return THROWERROR( RET_INIT_FAILED_CHOLESKY );
00844
00845
00846 real_t g_original[NVMAX];
00847 real_t lb_original[NVMAX];
00848 real_t ub_original[NVMAX];
00849
00850 for( i=0; i<nV; ++i )
00851 {
00852 g_original[i] = g[i];
00853 lb_original[i] = lb[i];
00854 ub_original[i] = ub[i];
00855 }
00856
00857
00858
00859 if ( setupAuxiliaryQPgradient( ) != SUCCESSFUL_RETURN )
00860 return THROWERROR( RET_INIT_FAILED );
00861
00862 if ( setupAuxiliaryQPbounds( BT_TRUE ) != SUCCESSFUL_RETURN )
00863 return THROWERROR( RET_INIT_FAILED );
00864
00865 status = QPS_AUXILIARYQPSOLVED;
00866
00867
00868
00869
00870 returnValue returnvalue = hotstart( g_original,lb_original,ub_original, nWSR,0 );
00871
00872
00873
00874 if ( isInfeasible( ) == BT_TRUE )
00875 return THROWERROR( RET_INIT_FAILED_INFEASIBILITY );
00876
00877 if ( isUnbounded( ) == BT_TRUE )
00878 return THROWERROR( RET_INIT_FAILED_UNBOUNDEDNESS );
00879
00880
00881 if ( ( returnvalue != SUCCESSFUL_RETURN ) && ( returnvalue != RET_MAX_NWSR_REACHED ) &&
00882 ( returnvalue != RET_INACCURATE_SOLUTION ) && ( returnvalue != RET_NO_SOLUTION ) )
00883 return THROWERROR( RET_INIT_FAILED_HOTSTART );
00884
00885
00886
00887 if ( cputime != 0 )
00888 *cputime = getCPUtime( ) - starttime;
00889
00890 if ( printlevel == PL_HIGH )
00891 THROWINFO( RET_INIT_SUCCESSFUL );
00892
00893 return returnvalue;
00894 }
00895
00896
00897
00898
00899
00900 returnValue QProblemB::obtainAuxiliaryWorkingSet( const real_t* const xOpt, const real_t* const yOpt,
00901 const Bounds* const guessedBounds, Bounds* auxiliaryBounds
00902 ) const
00903 {
00904 int i = 0;
00905 int nV = getNV( );
00906
00907
00908
00909 if ( ( auxiliaryBounds == 0 ) || ( auxiliaryBounds == guessedBounds ) )
00910 return THROWERROR( RET_INVALID_ARGUMENTS );
00911
00912
00913
00914 if ( guessedBounds != 0 )
00915 {
00916
00917
00918 for( i=0; i<nV; ++i )
00919 {
00920 if ( bounds.getType( i ) == ST_EQUALITY )
00921 {
00922 if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00923 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00924 }
00925 else
00926 {
00927 if ( auxiliaryBounds->setupBound( i,guessedBounds->getStatus( i ) ) != SUCCESSFUL_RETURN )
00928 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00929 }
00930 }
00931 }
00932 else
00933 {
00934 if ( ( xOpt != 0 ) && ( yOpt == 0 ) )
00935 {
00936
00937 for( i=0; i<nV; ++i )
00938 {
00939 if ( xOpt[i] <= lb[i] + BOUNDTOL )
00940 {
00941 if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00942 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00943 continue;
00944 }
00945
00946 if ( xOpt[i] >= ub[i] - BOUNDTOL )
00947 {
00948 if ( auxiliaryBounds->setupBound( i,ST_UPPER ) != SUCCESSFUL_RETURN )
00949 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00950 continue;
00951 }
00952
00953
00954 if ( bounds.getType( i ) == ST_EQUALITY )
00955 {
00956 if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00957 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00958 }
00959 else
00960 {
00961 if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
00962 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00963 }
00964 }
00965 }
00966
00967 if ( ( xOpt == 0 ) && ( yOpt != 0 ) )
00968 {
00969
00970 for( i=0; i<nV; ++i )
00971 {
00972 if ( yOpt[i] > ZERO )
00973 {
00974 if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00975 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00976 continue;
00977 }
00978
00979 if ( yOpt[i] < -ZERO )
00980 {
00981 if ( auxiliaryBounds->setupBound( i,ST_UPPER ) != SUCCESSFUL_RETURN )
00982 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00983 continue;
00984 }
00985
00986
00987 if ( bounds.getType( i ) == ST_EQUALITY )
00988 {
00989 if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00990 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00991 }
00992 else
00993 {
00994 if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
00995 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00996 }
00997 }
00998 }
00999
01000
01001
01002
01003 if ( ( xOpt == 0 ) && ( yOpt == 0 ) )
01004 {
01005 for( i=0; i<nV; ++i )
01006 {
01007
01008 if ( bounds.getType( i ) == ST_EQUALITY )
01009 {
01010 if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
01011 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
01012 }
01013 else
01014 {
01015 if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
01016 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
01017 }
01018 }
01019 }
01020 }
01021
01022 return SUCCESSFUL_RETURN;
01023 }
01024
01025
01026
01027
01028
01029 returnValue QProblemB::setupAuxiliaryWorkingSet( const Bounds* const auxiliaryBounds,
01030 BooleanType setupAfresh
01031 )
01032 {
01033 int i;
01034 int nV = getNV( );
01035
01036
01037 if ( auxiliaryBounds != 0 )
01038 {
01039 for( i=0; i<nV; ++i )
01040 if ( ( bounds.getStatus( i ) == ST_UNDEFINED ) || ( auxiliaryBounds->getStatus( i ) == ST_UNDEFINED ) )
01041 return THROWERROR( RET_UNKNOWN_BUG );
01042 }
01043 else
01044 {
01045 return THROWERROR( RET_INVALID_ARGUMENTS );
01046 }
01047
01048
01049
01050
01051
01052 BooleanType updateCholesky;
01053 if ( setupAfresh == BT_TRUE )
01054 updateCholesky = BT_FALSE;
01055 else
01056 updateCholesky = BT_TRUE;
01057
01058
01059
01060 if ( setupAfresh == BT_FALSE )
01061 {
01062
01063
01064 for( i=0; i<nV; ++i )
01065 {
01066 if ( ( bounds.getStatus( i ) == ST_LOWER ) && ( auxiliaryBounds->getStatus( i ) != ST_LOWER ) )
01067 if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
01068 return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
01069
01070 if ( ( bounds.getStatus( i ) == ST_UPPER ) && ( auxiliaryBounds->getStatus( i ) != ST_UPPER ) )
01071 if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
01072 return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
01073 }
01074 }
01075
01076
01077
01078
01079
01080 for( i=0; i<nV; ++i )
01081 {
01082 if ( ( bounds.getStatus( i ) == ST_INACTIVE ) && ( auxiliaryBounds->getStatus( i ) != ST_INACTIVE ) )
01083 {
01084 if ( addBound( i,auxiliaryBounds->getStatus( i ),updateCholesky ) != SUCCESSFUL_RETURN )
01085 return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
01086 }
01087 }
01088
01089 return SUCCESSFUL_RETURN;
01090 }
01091
01092
01093
01094
01095
01096 returnValue QProblemB::setupAuxiliaryQPsolution( const real_t* const xOpt, const real_t* const yOpt
01097 )
01098 {
01099 int i;
01100 int nV = getNV( );
01101
01102
01103
01104
01105
01106 if ( xOpt != 0 )
01107 {
01108 if ( xOpt != x )
01109 for( i=0; i<nV; ++i )
01110 x[i] = xOpt[i];
01111 }
01112 else
01113 {
01114 for( i=0; i<nV; ++i )
01115 x[i] = 0.0;
01116 }
01117
01118 if ( yOpt != 0 )
01119 {
01120 if ( yOpt != y )
01121 for( i=0; i<nV; ++i )
01122 y[i] = yOpt[i];
01123 }
01124 else
01125 {
01126 for( i=0; i<nV; ++i )
01127 y[i] = 0.0;
01128 }
01129
01130 return SUCCESSFUL_RETURN;
01131 }
01132
01133
01134
01135
01136
01137 returnValue QProblemB::setupAuxiliaryQPgradient( )
01138 {
01139 int i, j;
01140 int nV = getNV( );
01141
01142
01143
01144 for ( i=0; i<nV; ++i )
01145 {
01146
01147 g[i] = y[i];
01148
01149
01150 for ( j=0; j<nV; ++j )
01151 g[i] -= H[i*NVMAX + j] * x[j];
01152 }
01153
01154 return SUCCESSFUL_RETURN;
01155 }
01156
01157
01158
01159
01160
01161 returnValue QProblemB::setupAuxiliaryQPbounds( BooleanType useRelaxation )
01162 {
01163 int i;
01164 int nV = getNV( );
01165
01166
01167
01168 for ( i=0; i<nV; ++i )
01169 {
01170 switch ( bounds.getStatus( i ) )
01171 {
01172 case ST_INACTIVE:
01173 if ( useRelaxation == BT_TRUE )
01174 {
01175 if ( bounds.getType( i ) == ST_EQUALITY )
01176 {
01177 lb[i] = x[i];
01178 ub[i] = x[i];
01179 }
01180 else
01181 {
01182 lb[i] = x[i] - BOUNDRELAXATION;
01183 ub[i] = x[i] + BOUNDRELAXATION;
01184 }
01185 }
01186 break;
01187
01188 case ST_LOWER:
01189 lb[i] = x[i];
01190 if ( bounds.getType( i ) == ST_EQUALITY )
01191 {
01192 ub[i] = x[i];
01193 }
01194 else
01195 {
01196 if ( useRelaxation == BT_TRUE )
01197 ub[i] = x[i] + BOUNDRELAXATION;
01198 }
01199 break;
01200
01201 case ST_UPPER:
01202 ub[i] = x[i];
01203 if ( bounds.getType( i ) == ST_EQUALITY )
01204 {
01205 lb[i] = x[i];
01206 }
01207 else
01208 {
01209 if ( useRelaxation == BT_TRUE )
01210 lb[i] = x[i] - BOUNDRELAXATION;
01211 }
01212 break;
01213
01214 default:
01215 return THROWERROR( RET_UNKNOWN_BUG );
01216 }
01217 }
01218
01219 return SUCCESSFUL_RETURN;
01220 }
01221
01222
01223
01224
01225
01226 returnValue QProblemB::addBound( int number, SubjectToStatus B_status,
01227 BooleanType updateCholesky
01228 )
01229 {
01230 int i, j;
01231 int nFR = getNFR( );
01232
01233
01234
01235 if ( ( getStatus( ) == QPS_NOTINITIALISED ) ||
01236 ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
01237 ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
01238 ( getStatus( ) == QPS_SOLVED ) )
01239 {
01240 return THROWERROR( RET_UNKNOWN_BUG );
01241 }
01242
01243
01244 if ( ( getStatus( ) == QPS_PREPARINGAUXILIARYQP ) || ( updateCholesky == BT_FALSE ) )
01245 {
01246
01247 if ( bounds.moveFreeToFixed( number,B_status ) != SUCCESSFUL_RETURN )
01248 return THROWERROR( RET_ADDBOUND_FAILED );
01249
01250 return SUCCESSFUL_RETURN;
01251 }
01252
01253
01254
01255
01256 int number_idx = bounds.getFree( )->getIndex( number );
01257
01258 real_t c, s;
01259
01260
01261 for( i=number_idx+1; i<nFR; ++i )
01262 {
01263 computeGivens( R[(i-1)*NVMAX + i],R[i*NVMAX + i], R[(i-1)*NVMAX + i],R[i*NVMAX + i],c,s );
01264
01265 for( j=(1+i); j<nFR; ++j )
01266 applyGivens( c,s,R[(i-1)*NVMAX + j],R[i*NVMAX + j], R[(i-1)*NVMAX + j],R[i*NVMAX + j] );
01267 }
01268
01269
01270 for( i=0; i<nFR-1; ++i )
01271 for( j=number_idx+1; j<nFR; ++j )
01272 R[i*NVMAX + j-1] = R[i*NVMAX + j];
01273
01274 for( i=0; i<nFR; ++i )
01275 R[i*NVMAX + nFR-1] = 0.0;
01276
01277
01278
01279 if ( bounds.moveFreeToFixed( number,B_status ) != SUCCESSFUL_RETURN )
01280 return THROWERROR( RET_ADDBOUND_FAILED );
01281
01282
01283 return SUCCESSFUL_RETURN;
01284 }
01285
01286
01287 returnValue QProblemB::removeBound( int number,
01288 BooleanType updateCholesky
01289 )
01290 {
01291 int i, ii;
01292 int nFR = getNFR( );
01293
01294
01295
01296 if ( ( getStatus( ) == QPS_NOTINITIALISED ) ||
01297 ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
01298 ( getStatus( ) == QPS_HOMOTOPYQPSOLVED ) ||
01299 ( getStatus( ) == QPS_SOLVED ) )
01300 {
01301 return THROWERROR( RET_UNKNOWN_BUG );
01302 }
01303
01304
01305
01306 if ( bounds.moveFixedToFree( number ) != SUCCESSFUL_RETURN )
01307 return THROWERROR( RET_REMOVEBOUND_FAILED );
01308
01309
01310 if ( ( getStatus( ) == QPS_PREPARINGAUXILIARYQP ) || ( updateCholesky == BT_FALSE ) )
01311 return SUCCESSFUL_RETURN;
01312
01313
01314
01315 int FR_idx[NVMAX];
01316 if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
01317 return THROWERROR( RET_REMOVEBOUND_FAILED );
01318
01319
01320 real_t rhs[NVMAX];
01321 real_t r[NVMAX];
01322 real_t r0 = H[number*NVMAX + number];
01323
01324 for( i=0; i<nFR; ++i )
01325 {
01326 ii = FR_idx[i];
01327 rhs[i] = H[number*NVMAX + ii];
01328 }
01329
01330 if ( backsolveR( rhs,BT_TRUE,BT_TRUE,r ) != SUCCESSFUL_RETURN )
01331 return THROWERROR( RET_REMOVEBOUND_FAILED );
01332
01333 for( i=0; i<nFR; ++i )
01334 r0 -= r[i]*r[i];
01335
01336
01337 for( i=0; i<nFR; ++i )
01338 R[i*NVMAX + nFR] = r[i];
01339
01340 if ( r0 > 0.0 )
01341 R[nFR*NVMAX + nFR] = sqrt( r0 );
01342 else
01343 {
01344 hessianType = HST_SEMIDEF;
01345 return THROWERROR( RET_HESSIAN_NOT_SPD );
01346 }
01347
01348
01349 return SUCCESSFUL_RETURN;
01350 }
01351
01352
01353
01354
01355
01356 returnValue QProblemB::backsolveR( const real_t* const b, BooleanType transposed,
01357 real_t* const a
01358 )
01359 {
01360
01361 return backsolveR( b,transposed,BT_FALSE,a );
01362 }
01363
01364
01365
01366
01367
01368 returnValue QProblemB::backsolveR( const real_t* const b, BooleanType transposed,
01369 BooleanType removingBound,
01370 real_t* const a
01371 )
01372 {
01373 int i, j;
01374 int nR = getNZ( );
01375
01376 real_t sum;
01377
01378
01379 if ( removingBound == BT_TRUE )
01380 --nR;
01381
01382
01383 if ( nR <= 0 )
01384 return SUCCESSFUL_RETURN;
01385
01386
01387
01388 if ( transposed == BT_FALSE )
01389 {
01390
01391 for( i=(nR-1); i>=0; --i )
01392 {
01393 sum = b[i];
01394 for( j=(i+1); j<nR; ++j )
01395 sum -= R[i*NVMAX + j] * a[j];
01396
01397 if ( getAbs( R[i*NVMAX + i] ) > ZERO )
01398 a[i] = sum / R[i*NVMAX + i];
01399 else
01400 return THROWERROR( RET_DIV_BY_ZERO );
01401 }
01402 }
01403 else
01404 {
01405
01406 for( i=0; i<nR; ++i )
01407 {
01408 sum = b[i];
01409
01410 for( j=0; j<i; ++j )
01411 sum -= R[j*NVMAX + i] * a[j];
01412
01413 if ( getAbs( R[i*NVMAX + i] ) > ZERO )
01414 a[i] = sum / R[i*NVMAX + i];
01415 else
01416 return THROWERROR( RET_DIV_BY_ZERO );
01417 }
01418 }
01419
01420 return SUCCESSFUL_RETURN;
01421 }
01422
01423
01424
01425
01426
01427 returnValue QProblemB::hotstart_determineDataShift( const int* const FX_idx,
01428 const real_t* const g_new, const real_t* const lb_new, const real_t* const ub_new,
01429 real_t* const delta_g, real_t* const delta_lb, real_t* const delta_ub,
01430 BooleanType& Delta_bB_isZero
01431 )
01432 {
01433 int i, ii;
01434 int nV = getNV( );
01435 int nFX = getNFX( );
01436
01437
01438
01439 for( i=0; i<nV; ++i )
01440 delta_g[i] = g_new[i] - g[i];
01441
01442 if ( lb_new != 0 )
01443 {
01444 for( i=0; i<nV; ++i )
01445 delta_lb[i] = lb_new[i] - lb[i];
01446 }
01447 else
01448 {
01449
01450 for( i=0; i<nV; ++i )
01451 delta_lb[i] = -INFTY - lb[i];
01452 }
01453
01454 if ( ub_new != 0 )
01455 {
01456 for( i=0; i<nV; ++i )
01457 delta_ub[i] = ub_new[i] - ub[i];
01458 }
01459 else
01460 {
01461
01462 for( i=0; i<nV; ++i )
01463 delta_ub[i] = INFTY - ub[i];
01464 }
01465
01466
01467 Delta_bB_isZero = BT_TRUE;
01468
01469 for ( i=0; i<nFX; ++i )
01470 {
01471 ii = FX_idx[i];
01472
01473 if ( ( getAbs( delta_lb[ii] ) > EPS ) || ( getAbs( delta_ub[ii] ) > EPS ) )
01474 {
01475 Delta_bB_isZero = BT_FALSE;
01476 break;
01477 }
01478 }
01479
01480 return SUCCESSFUL_RETURN;
01481 }
01482
01483
01484
01485
01486
01487 BooleanType QProblemB::areBoundsConsistent( const real_t* const delta_lb, const real_t* const delta_ub
01488 ) const
01489 {
01490 int i;
01491
01492
01493
01494 for( i=0; i<getNV( ); ++i )
01495 if ( ( lb[i] > ub[i] - BOUNDTOL ) && ( delta_lb[i] > delta_ub[i] + EPS ) )
01496 return BT_FALSE;
01497
01498 return BT_TRUE;
01499 }
01500
01501
01502
01503
01504
01505 returnValue QProblemB::setupQPdata( const real_t* const _H, const real_t* const _g,
01506 const real_t* const _lb, const real_t* const _ub
01507 )
01508 {
01509 int i, j;
01510 int nV = getNV( );
01511
01512
01513 if ( _H == 0 )
01514 return THROWERROR( RET_INVALID_ARGUMENTS );
01515
01516 for( i=0; i<nV; ++i )
01517 for( j=0; j<nV; ++j )
01518 H[i*NVMAX + j] = _H[i*nV + j];
01519
01520
01521 if ( _g == 0 )
01522 return THROWERROR( RET_INVALID_ARGUMENTS );
01523
01524 for( i=0; i<nV; ++i )
01525 g[i] = _g[i];
01526
01527
01528 if ( _lb != 0 )
01529 {
01530 for( i=0; i<nV; ++i )
01531 lb[i] = _lb[i];
01532 }
01533 else
01534 {
01535
01536 for( i=0; i<nV; ++i )
01537 lb[i] = -INFTY;
01538 }
01539
01540
01541 if ( _ub != 0 )
01542 {
01543 for( i=0; i<nV; ++i )
01544 ub[i] = _ub[i];
01545 }
01546 else
01547 {
01548
01549 for( i=0; i<nV; ++i )
01550 ub[i] = INFTY;
01551 }
01552
01553
01554
01555
01556
01557
01558 return SUCCESSFUL_RETURN;
01559 }
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570 returnValue QProblemB::hotstart_determineStepDirection( const int* const FR_idx, const int* const FX_idx,
01571 const real_t* const delta_g, const real_t* const delta_lb, const real_t* const delta_ub,
01572 BooleanType Delta_bB_isZero,
01573 real_t* const delta_xFX, real_t* const delta_xFR,
01574 real_t* const delta_yFX
01575 )
01576 {
01577 int i, j, ii, jj;
01578 int nFR = getNFR( );
01579 int nFX = getNFX( );
01580
01581
01582
01583 real_t HMX_delta_xFX[NVMAX];
01584 for( i=0; i<nFR; ++i )
01585 HMX_delta_xFX[i] = 0.0;
01586
01587
01588
01589 if ( nFX > 0 )
01590 {
01591 for( i=0; i<nFX; ++i )
01592 {
01593 ii = FX_idx[i];
01594
01595 if ( bounds.getStatus( ii ) == ST_LOWER )
01596 delta_xFX[i] = delta_lb[ii];
01597 else
01598 delta_xFX[i] = delta_ub[ii];
01599 }
01600 }
01601
01602
01603
01604 if ( nFR > 0 )
01605 {
01606
01607 real_t delta_xFRz_TMP[NVMAX];
01608 real_t delta_xFRz_RHS[NVMAX];
01609
01610
01611 if ( Delta_bB_isZero == BT_FALSE )
01612 {
01613 for( i=0; i<nFR; ++i )
01614 {
01615 ii = FR_idx[i];
01616 for( j=0; j<nFX; ++j )
01617 {
01618 jj = FX_idx[j];
01619 HMX_delta_xFX[i] += H[ii*NVMAX + jj] * delta_xFX[j];
01620 }
01621 }
01622 }
01623
01624 if ( Delta_bB_isZero == BT_TRUE )
01625 {
01626 for( j=0; j<nFR; ++j )
01627 {
01628 jj = FR_idx[j];
01629 delta_xFRz_RHS[j] = delta_g[jj];
01630 }
01631 }
01632 else
01633 {
01634 for( j=0; j<nFR; ++j )
01635 {
01636 jj = FR_idx[j];
01637 delta_xFRz_RHS[j] = delta_g[jj] + HMX_delta_xFX[j];
01638 }
01639 }
01640
01641 for( i=0; i<nFR; ++i )
01642 delta_xFR[i] = -delta_xFRz_RHS[i];
01643
01644 if ( backsolveR( delta_xFR,BT_TRUE,delta_xFRz_TMP ) != SUCCESSFUL_RETURN )
01645 return THROWERROR( RET_STEPDIRECTION_FAILED_CHOLESKY );
01646
01647 if ( backsolveR( delta_xFRz_TMP,BT_FALSE,delta_xFR ) != SUCCESSFUL_RETURN )
01648 return THROWERROR( RET_STEPDIRECTION_FAILED_CHOLESKY );
01649 }
01650
01651
01652
01653 if ( nFX > 0 )
01654 {
01655 for( i=0; i<nFX; ++i )
01656 {
01657 ii = FX_idx[i];
01658
01659 delta_yFX[i] = 0.0;
01660 for( j=0; j<nFR; ++j )
01661 {
01662 jj = FR_idx[j];
01663 delta_yFX[i] += H[ii*NVMAX + jj] * delta_xFR[j];
01664 }
01665
01666 if ( Delta_bB_isZero == BT_FALSE )
01667 {
01668 for( j=0; j<nFX; ++j )
01669 {
01670 jj = FX_idx[j];
01671 delta_yFX[i] += H[ii*NVMAX + jj] * delta_xFX[j];
01672 }
01673 }
01674
01675 delta_yFX[i] += delta_g[ii];
01676 }
01677 }
01678
01679 return SUCCESSFUL_RETURN;
01680 }
01681
01682
01683
01684
01685
01686 returnValue QProblemB::hotstart_determineStepLength( const int* const FR_idx, const int* const FX_idx,
01687 const real_t* const delta_lb, const real_t* const delta_ub,
01688 const real_t* const delta_xFR,
01689 const real_t* const delta_yFX,
01690 int& BC_idx, SubjectToStatus& BC_status
01691 )
01692 {
01693 int i, ii;
01694 int nFR = getNFR( );
01695 int nFX = getNFX( );
01696
01697 real_t tau_tmp;
01698 real_t tau_new = 1.0;
01699
01700 BC_idx = 0;
01701 BC_status = ST_UNDEFINED;
01702
01703
01704
01705
01706 for( i=0; i<nFX; ++i )
01707 {
01708 ii = FX_idx[i];
01709
01710 if ( bounds.getType( ii ) != ST_EQUALITY )
01711 {
01712 if ( bounds.getStatus( ii ) == ST_LOWER )
01713 {
01714
01715 if ( ( delta_yFX[i] < -ZERO ) && ( y[ii] >= 0.0 ) )
01716 {
01717 tau_tmp = y[ii] / ( -delta_yFX[i] );
01718 if ( tau_tmp < tau_new )
01719 {
01720 if ( tau_tmp >= 0.0 )
01721 {
01722 tau_new = tau_tmp;
01723 BC_idx = ii;
01724 BC_status = ST_INACTIVE;
01725 }
01726 }
01727 }
01728 }
01729 else
01730 {
01731
01732 if ( ( delta_yFX[i] > ZERO ) && ( y[ii] <= 0.0 ) )
01733 {
01734 tau_tmp = y[ii] / ( -delta_yFX[i] );
01735 if ( tau_tmp < tau_new )
01736 {
01737 if ( tau_tmp >= 0.0 )
01738 {
01739 tau_new = tau_tmp;
01740 BC_idx = ii;
01741 BC_status = ST_INACTIVE;
01742 }
01743 }
01744 }
01745 }
01746 }
01747 }
01748
01749
01750
01751
01752
01753 if ( bounds.isNoLower( ) == BT_FALSE )
01754 {
01755 for( i=0; i<nFR; ++i )
01756 {
01757 ii = FR_idx[i];
01758
01759 if ( bounds.getType( ii ) != ST_UNBOUNDED )
01760 {
01761 if ( delta_lb[ii] > delta_xFR[i] )
01762 {
01763 if ( x[ii] > lb[ii] )
01764 tau_tmp = ( x[ii] - lb[ii] ) / ( delta_lb[ii] - delta_xFR[i] );
01765 else
01766 tau_tmp = 0.0;
01767
01768 if ( tau_tmp < tau_new )
01769 {
01770 if ( tau_tmp >= 0.0 )
01771 {
01772 tau_new = tau_tmp;
01773 BC_idx = ii;
01774 BC_status = ST_LOWER;
01775 }
01776 }
01777 }
01778 }
01779 }
01780 }
01781
01782
01783 if ( bounds.isNoUpper( ) == BT_FALSE )
01784 {
01785 for( i=0; i<nFR; ++i )
01786 {
01787 ii = FR_idx[i];
01788
01789 if ( bounds.getType( ii ) != ST_UNBOUNDED )
01790 {
01791 if ( delta_ub[ii] < delta_xFR[i] )
01792 {
01793 if ( x[ii] < ub[ii] )
01794 tau_tmp = ( x[ii] - ub[ii] ) / ( delta_ub[ii] - delta_xFR[i] );
01795 else
01796 tau_tmp = 0.0;
01797
01798 if ( tau_tmp < tau_new )
01799 {
01800 if ( tau_tmp >= 0.0 )
01801 {
01802 tau_new = tau_tmp;
01803 BC_idx = ii;
01804 BC_status = ST_UPPER;
01805 }
01806 }
01807 }
01808 }
01809 }
01810 }
01811
01812
01813
01814 tau = tau_new;
01815
01816 if ( printlevel == PL_HIGH )
01817 {
01818 #ifdef PC_DEBUG
01819 char messageString[80];
01820
01821 if ( BC_status == ST_UNDEFINED )
01822 sprintf( messageString,"Stepsize is %.6e!",tau );
01823 else
01824 sprintf( messageString,"Stepsize is %.6e! (BC_idx = %d, BC_status = %d)",tau,BC_idx,BC_status );
01825
01826 getGlobalMessageHandler( )->throwInfo( RET_STEPSIZE_NONPOSITIVE,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
01827 #endif
01828 }
01829
01830 return SUCCESSFUL_RETURN;
01831 }
01832
01833
01834
01835
01836
01837 returnValue QProblemB::hotstart_performStep( const int* const FR_idx, const int* const FX_idx,
01838 const real_t* const delta_g, const real_t* const delta_lb, const real_t* const delta_ub,
01839 const real_t* const delta_xFX, const real_t* const delta_xFR,
01840 const real_t* const delta_yFX,
01841 int BC_idx, SubjectToStatus BC_status
01842 )
01843 {
01844 int i, ii;
01845 int nV = getNV( );
01846 int nFR = getNFR( );
01847 int nFX = getNFX( );
01848
01849
01850
01851 if ( areBoundsConsistent( delta_lb,delta_ub ) == BT_FALSE )
01852 {
01853 infeasible = BT_TRUE;
01854 tau = 0.0;
01855
01856 return THROWERROR( RET_QP_INFEASIBLE );
01857 }
01858
01859
01860
01861 if ( tau > ZERO )
01862 {
01863
01864 for( i=0; i<nFR; ++i )
01865 {
01866 ii = FR_idx[i];
01867 x[ii] += tau*delta_xFR[i];
01868 }
01869
01870 for( i=0; i<nFX; ++i )
01871 {
01872 ii = FX_idx[i];
01873 x[ii] += tau*delta_xFX[i];
01874 y[ii] += tau*delta_yFX[i];
01875 }
01876
01877
01878 for( i=0; i<nV; ++i )
01879 {
01880 g[i] += tau*delta_g[i];
01881 lb[i] += tau*delta_lb[i];
01882 ub[i] += tau*delta_ub[i];
01883 }
01884 }
01885 else
01886 {
01887
01888 #ifdef PC_DEBUG
01889 char messageString[80];
01890 sprintf( messageString,"Stepsize is %.6e",tau );
01891 getGlobalMessageHandler( )->throwWarning( RET_STEPSIZE,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
01892 #endif
01893 }
01894
01895
01896
01897 #ifdef PC_DEBUG
01898 char messageString[80];
01899 VisibilityStatus visibilityStatus;
01900
01901 if ( printlevel == PL_HIGH )
01902 visibilityStatus = VS_VISIBLE;
01903 else
01904 visibilityStatus = VS_HIDDEN;
01905 #endif
01906
01907
01908
01909 switch ( BC_status )
01910 {
01911
01912 case ST_UNDEFINED:
01913 return RET_OPTIMAL_SOLUTION_FOUND;
01914
01915
01916
01917 case ST_INACTIVE:
01918 #ifdef PC_DEBUG
01919 sprintf( messageString,"bound no. %d.", BC_idx );
01920 getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
01921 #endif
01922
01923 if ( removeBound( BC_idx,BT_TRUE ) != SUCCESSFUL_RETURN )
01924 return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
01925
01926 y[BC_idx] = 0.0;
01927 break;
01928
01929
01930
01931 default:
01932 #ifdef PC_DEBUG
01933 if ( BC_status == ST_LOWER )
01934 sprintf( messageString,"lower bound no. %d.", BC_idx );
01935 else
01936 sprintf( messageString,"upper bound no. %d.", BC_idx );
01937 getGlobalMessageHandler( )->throwInfo( RET_ADD_TO_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
01938 #endif
01939
01940 if ( addBound( BC_idx,BC_status,BT_TRUE ) != SUCCESSFUL_RETURN )
01941 return THROWERROR( RET_ADD_TO_ACTIVESET_FAILED );
01942 break;
01943 }
01944
01945 return SUCCESSFUL_RETURN;
01946 }
01947
01948
01949 #ifdef PC_DEBUG
01950
01951
01952
01953
01954 returnValue QProblemB::printIteration( int iteration,
01955 int BC_idx, SubjectToStatus BC_status
01956 )
01957 {
01958 char myPrintfString[160];
01959
01960
01961 if ( iteration < 0 )
01962 return THROWERROR( RET_INVALID_ARGUMENTS );
01963
01964
01965 if ( printlevel != PL_MEDIUM )
01966 return SUCCESSFUL_RETURN;
01967
01968
01969
01970 if ( iteration == 0 )
01971 {
01972 sprintf( myPrintfString,"\n############## qpOASES -- QP NO.%4.1d ###############\n", count );
01973 myPrintf( myPrintfString );
01974
01975 sprintf( myPrintfString," Iter | StepLength | Info | nFX \n" );
01976 myPrintf( myPrintfString );
01977 }
01978
01979
01980 if ( BC_status == ST_UNDEFINED )
01981 {
01982 sprintf( myPrintfString," %4.1d | %1.5e | QP SOLVED | %4.1d \n", iteration,tau,getNFX( ) );
01983 myPrintf( myPrintfString );
01984 }
01985 else
01986 {
01987 char info[8];
01988
01989 if ( BC_status == ST_INACTIVE )
01990 sprintf( info,"REM BND" );
01991 else
01992 sprintf( info,"ADD BND" );
01993
01994 sprintf( myPrintfString," %4.1d | %1.5e | %s%4.1d | %4.1d \n", iteration,tau,info,BC_idx,getNFX( ) );
01995 myPrintf( myPrintfString );
01996 }
01997
01998 return SUCCESSFUL_RETURN;
01999 }
02000
02001 #endif
02002
02003
02004
02005
02006
02007
02008 returnValue QProblemB::checkKKTconditions( )
02009 {
02010 #ifdef __PERFORM_KKT_TEST__
02011
02012 int i, j;
02013 int nV = getNV( );
02014
02015 real_t tmp;
02016 real_t maxKKTviolation = 0.0;
02017
02018
02019
02020 for( i=0; i<nV; ++i )
02021 {
02022 tmp = g[i];
02023
02024 for( j=0; j<nV; ++j )
02025 tmp += H[i*nV + j] * x[j];
02026
02027 tmp -= y[i];
02028
02029 if ( getAbs( tmp ) > maxKKTviolation )
02030 maxKKTviolation = getAbs( tmp );
02031 }
02032
02033
02034 for( i=0; i<nV; ++i )
02035 {
02036 if ( lb[i] - x[i] > maxKKTviolation )
02037 maxKKTviolation = lb[i] - x[i];
02038
02039 if ( x[i] - ub[i] > maxKKTviolation )
02040 maxKKTviolation = x[i] - ub[i];
02041 }
02042
02043
02044 for( i=0; i<nV; ++i )
02045 {
02046 switch ( bounds.getStatus( i ) )
02047 {
02048 case ST_LOWER:
02049 if ( -y[i] > maxKKTviolation )
02050 maxKKTviolation = -y[i];
02051 if ( getAbs( ( x[i] - lb[i] ) * y[i] ) > maxKKTviolation )
02052 maxKKTviolation = getAbs( ( x[i] - lb[i] ) * y[i] );
02053 break;
02054
02055 case ST_UPPER:
02056 if ( y[i] > maxKKTviolation )
02057 maxKKTviolation = y[i];
02058 if ( getAbs( ( ub[i] - x[i] ) * y[i] ) > maxKKTviolation )
02059 maxKKTviolation = getAbs( ( ub[i] - x[i] ) * y[i] );
02060 break;
02061
02062 default:
02063 if ( getAbs( y[i] ) > maxKKTviolation )
02064 maxKKTviolation = getAbs( y[i] );
02065 break;
02066 }
02067 }
02068
02069 if ( maxKKTviolation > CRITICALACCURACY )
02070 return RET_NO_SOLUTION;
02071
02072 if ( maxKKTviolation > DESIREDACCURACY )
02073 return RET_INACCURATE_SOLUTION;
02074
02075 #endif
02076
02077 return SUCCESSFUL_RETURN;
02078 }
02079
02080
02081
02082
02083
02084