QProblem.cpp
Go to the documentation of this file.
00001 /*
00002  *      This file is part of qpOASES.
00003  *
00004  *      qpOASES -- An Implementation of the Online Active Set Strategy.
00005  *      Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
00006  *
00007  *      qpOASES is free software; you can redistribute it and/or
00008  *      modify it under the terms of the GNU Lesser General Public
00009  *      License as published by the Free Software Foundation; either
00010  *      version 2.1 of the License, or (at your option) any later version.
00011  *
00012  *      qpOASES is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *      Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with qpOASES; if not, write to the Free Software
00019  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020  *
00021  */
00022 
00023 
00035 #include <QProblem.hpp>
00036 
00037 #include <stdio.h>
00038 
00039 void printmatrix2(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 //#define __PERFORM_KKT_TEST__
00052 
00053 
00054 /*****************************************************************************
00055  *  P U B L I C                                                              *
00056  *****************************************************************************/
00057 
00058 
00059 /*
00060  *      Q P r o b l e m
00061  */
00062 QProblem::QProblem( ) : QProblemB( )
00063 {
00064         constraints.init( 0 );
00065 
00066         sizeT = 0;
00067 
00068         cyclingManager.init( 0,0 );
00069 }
00070 
00071 
00072 /*
00073  *      Q P r o b l e m
00074  */
00075 QProblem::QProblem( int _nV, int _nC ) : QProblemB( _nV )
00076 {
00077         /* consistency checks */
00078         if ( _nV <= 0 )
00079                 _nV = 1;
00080 
00081         if ( _nC < 0 )
00082         {
00083                 _nC = 0;
00084                 THROWERROR( RET_INVALID_ARGUMENTS );
00085         }
00086 
00087         constraints.init( _nC );
00088 
00089 
00090         sizeT = _nC;
00091         if ( _nC > _nV )
00092                 sizeT = _nV;
00093 
00094         cyclingManager.init( _nV,_nC );
00095 }
00096 
00097 
00098 /*
00099  *      Q P r o b l e m
00100  */
00101 QProblem::QProblem( const QProblem& rhs ) :     QProblemB( rhs )
00102 {
00103         int i, j;
00104 
00105         int _nV = rhs.bounds.getNV( );
00106         int _nC = rhs.constraints.getNC( );
00107 
00108         for( i=0; i<_nC; ++i )
00109                 for( j=0; j<_nV; ++j )
00110                         A[i*NVMAX + j] = rhs.A[i*NVMAX + j];
00111 
00112         for( i=0; i<_nC; ++i )
00113                 lbA[i] = rhs.lbA[i];
00114 
00115         for( i=0; i<_nC; ++i )
00116                         ubA[i] = rhs.ubA[i];
00117 
00118         constraints = rhs.constraints;
00119 
00120         for( i=0; i<(_nV+_nC); ++i )
00121                 y[i] = rhs.y[i];
00122 
00123 
00124         sizeT = rhs.sizeT;
00125 
00126         for( i=0; i<sizeT; ++i )
00127                 for( j=0; j<sizeT; ++j )
00128                         T[i*NVMAX + j] = rhs.T[i*NVMAX + j];
00129 
00130         for( i=0; i<_nV; ++i )
00131                 for( j=0; j<_nV; ++j )
00132                         Q[i*NVMAX + j] = rhs.Q[i*NVMAX + j];
00133 
00134         for( i=0; i<_nC; ++i )
00135                 Ax[i] = rhs.Ax[i];
00136 
00137         cyclingManager = rhs.cyclingManager;
00138 }
00139 
00140 
00141 /*
00142  *      ~ Q P r o b l e m
00143  */
00144 QProblem::~QProblem( )
00145 {
00146 }
00147 
00148 
00149 /*
00150  *      o p e r a t o r =
00151  */
00152 QProblem& QProblem::operator=( const QProblem& rhs )
00153 {
00154         int i, j;
00155 
00156         if ( this != &rhs )
00157         {
00158                 QProblemB::operator=( rhs );
00159 
00160 
00161                 int _nV = rhs.bounds.getNV( );
00162                 int _nC = rhs.constraints.getNC( );
00163 
00164                 for( i=0; i<_nC; ++i )
00165                         for( j=0; j<_nV; ++j )
00166                                 A[i*NVMAX + j] = rhs.A[i*NVMAX + j];
00167 
00168                 for( i=0; i<_nC; ++i )
00169                         lbA[i] = rhs.lbA[i];
00170 
00171                 for( i=0; i<_nC; ++i )
00172                         ubA[i] = rhs.ubA[i];
00173 
00174                 constraints = rhs.constraints;
00175 
00176                 for( i=0; i<(_nV+_nC); ++i )
00177                         y[i] = rhs.y[i];
00178 
00179 
00180                 sizeT = rhs.sizeT;
00181 
00182                 for( i=0; i<sizeT; ++i )
00183                         for( j=0; j<sizeT; ++j )
00184                                 T[i*NVMAX + j] = rhs.T[i*NVMAX + j];
00185 
00186                 for( i=0; i<_nV; ++i )
00187                         for( j=0; j<_nV; ++j )
00188                                 Q[i*NVMAX + j] = rhs.Q[i*NVMAX + j];
00189 
00190                 for( i=0; i<_nC; ++i )
00191                         Ax[i] = rhs.Ax[i];
00192 
00193                 cyclingManager = rhs.cyclingManager;
00194         }
00195 
00196         return *this;
00197 }
00198 
00199 
00200 /*
00201  *      r e s e t
00202  */
00203 returnValue QProblem::reset( )
00204 {
00205         int i, j;
00206         int nV = getNV( );
00207         int nC = getNC( );
00208 
00209 
00210         /* 1) Reset bounds, Cholesky decomposition and status flags. */
00211         if ( QProblemB::reset( ) != SUCCESSFUL_RETURN )
00212                 return THROWERROR( RET_RESET_FAILED );
00213 
00214         /* 2) Reset constraints. */
00215         constraints.init( nC );
00216 
00217         /* 3) Reset TQ factorisation. */
00218         for( i=0; i<sizeT; ++i )
00219                 for( j=0; j<sizeT; ++j )
00220                         T[i*NVMAX + j] = 0.0;
00221 
00222         for( i=0; i<nV; ++i )
00223                 for( j=0; j<nV; ++j )
00224                         Q[i*NVMAX + j] = 0.0;
00225 
00226         /* 4) Reset cycling manager. */
00227         if ( cyclingManager.clearCyclingData( ) != SUCCESSFUL_RETURN )
00228                 return THROWERROR( RET_RESET_FAILED );
00229 
00230         return SUCCESSFUL_RETURN;
00231 }
00232 
00233 
00234 /*
00235  *      i n i t
00236  */
00237 returnValue QProblem::init(     const real_t* const _H, const real_t* const _g, const real_t* const _A,
00238                                                         const real_t* const _lb, const real_t* const _ub,
00239                                                         const real_t* const _lbA, const real_t* const _ubA,
00240                                                         int& nWSR, const real_t* const yOpt, real_t* const cputime
00241                                                         )
00242 {
00243         /* 1) Setup QP data. */
00244         if ( setupQPdata( _H,_g,_A,_lb,_ub,_lbA,_ubA ) != SUCCESSFUL_RETURN )
00245                 return THROWERROR( RET_INVALID_ARGUMENTS );
00246 
00247         /* 2) Call to main initialisation routine (without any additional information). */
00248         return solveInitialQP( 0,yOpt,0,0, nWSR,cputime );
00249 }
00250 
00251 
00252 /*
00253  *      h o t s t a r t
00254  */
00255 returnValue QProblem::hotstart( const real_t* const g_new, const real_t* const lb_new, const real_t* const ub_new,
00256                                                                 const real_t* const lbA_new, const real_t* const ubA_new,
00257                                                                 int& nWSR, real_t* const cputime
00258                                                                 )
00259 {
00260         int l;
00261 
00262         /* consistency check */
00263         if ( ( getStatus( ) == QPS_NOTINITIALISED )       ||
00264                  ( getStatus( ) == QPS_PREPARINGAUXILIARYQP ) ||
00265                  ( getStatus( ) == QPS_PERFORMINGHOMOTOPY )   )
00266         {
00267                 return THROWERROR( RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED );
00268         }
00269 
00270         /* start runtime measurement */
00271         real_t starttime = 0.0;
00272         if ( cputime != 0 )
00273                 starttime = getCPUtime( );
00274 
00275 
00276         /* I) PREPARATIONS */
00277         /* 1) Reset cycling and status flags and increase QP counter. */
00278         cyclingManager.clearCyclingData( );
00279 
00280         infeasible = BT_FALSE;
00281         unbounded = BT_FALSE;
00282 
00283         ++count;
00284 
00285         /* 2) Allocate delta vectors of gradient and (constraints') bounds. */
00286         returnValue returnvalue;
00287         BooleanType Delta_bC_isZero, Delta_bB_isZero;
00288 
00289         int FR_idx[NVMAX];
00290         int FX_idx[NVMAX];
00291         int AC_idx[NCMAX_ALLOC];
00292         int IAC_idx[NCMAX_ALLOC];
00293 
00294         real_t delta_g[NVMAX];
00295         real_t delta_lb[NVMAX];
00296         real_t delta_ub[NVMAX];
00297         real_t delta_lbA[NCMAX_ALLOC];
00298         real_t delta_ubA[NCMAX_ALLOC];
00299 
00300         real_t delta_xFR[NVMAX];
00301         real_t delta_xFX[NVMAX];
00302         real_t delta_yAC[NCMAX_ALLOC];
00303         real_t delta_yFX[NVMAX];
00304         real_t delta_Ax[NCMAX_ALLOC];
00305 
00306         int BC_idx;
00307         SubjectToStatus BC_status;
00308         BooleanType BC_isBound;
00309 
00310         #ifdef PC_DEBUG
00311         char messageString[80];
00312         #endif
00313 
00314 
00315         /* II) MAIN HOMOTOPY LOOP */
00316         for( l=0; l<nWSR; ++l )
00317         {
00318                 status = QPS_PERFORMINGHOMOTOPY;
00319 
00320                 if ( printlevel == PL_HIGH )
00321                 {
00322                         #ifdef PC_DEBUG
00323                         sprintf( messageString,"%d ...",l );
00324                         getGlobalMessageHandler( )->throwInfo( RET_ITERATION_STARTED,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
00325                         #endif
00326                 }
00327 
00328                 /* 1) Setup index arrays. */
00329                 if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
00330                         return THROWERROR( RET_HOTSTART_FAILED );
00331 
00332                 if ( bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
00333                         return THROWERROR( RET_HOTSTART_FAILED );
00334 
00335                 if ( constraints.getActive( )->getNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
00336                         return THROWERROR( RET_HOTSTART_FAILED );
00337 
00338                 if ( constraints.getInactive( )->getNumberArray( IAC_idx ) != SUCCESSFUL_RETURN )
00339                         return THROWERROR( RET_HOTSTART_FAILED );
00340 
00341                 /* 2) Detemination of shift direction of the gradient and the (constraints') bounds. */
00342                 returnvalue = hotstart_determineDataShift(  FX_idx, AC_idx,
00343                                                                                                         g_new,lbA_new,ubA_new,lb_new,ub_new,
00344                                                                                                         delta_g,delta_lbA,delta_ubA,delta_lb,delta_ub,
00345                                                                                                         Delta_bC_isZero, Delta_bB_isZero );
00346                 if ( returnvalue != SUCCESSFUL_RETURN )
00347                 {
00348                         nWSR = l;
00349                         THROWERROR( RET_SHIFT_DETERMINATION_FAILED );
00350                         return returnvalue;
00351                 }
00352 
00353                 /* 3) Determination of step direction of X and Y. */
00354                 returnvalue = hotstart_determineStepDirection(  FR_idx,FX_idx,AC_idx,
00355                                                                                                                 delta_g,delta_lbA,delta_ubA,delta_lb,delta_ub,
00356                                                                                                                 Delta_bC_isZero, Delta_bB_isZero,
00357                                                                                                                 delta_xFX,delta_xFR,delta_yAC,delta_yFX
00358                                                                                                                 );
00359                 if ( returnvalue != SUCCESSFUL_RETURN )
00360                 {
00361                         nWSR = l;
00362                         THROWERROR( RET_STEPDIRECTION_DETERMINATION_FAILED );
00363                         return returnvalue;
00364                 }
00365 
00366                 /* 4) Determination of step length TAU. */
00367                 returnvalue = hotstart_determineStepLength(     FR_idx,FX_idx,AC_idx,IAC_idx,
00368                                                                                                         delta_lbA,delta_ubA,delta_lb,delta_ub,
00369                                                                                                         delta_xFX,delta_xFR,delta_yAC,delta_yFX,delta_Ax,
00370                                                                                                         BC_idx,BC_status,BC_isBound
00371                                                                                                         );
00372                 if ( returnvalue != SUCCESSFUL_RETURN )
00373                 {
00374                         nWSR = l;
00375                         THROWERROR( RET_STEPLENGTH_DETERMINATION_FAILED );
00376                         return returnvalue;
00377                 }
00378 
00379                 /* 5) Realisation of the homotopy step. */
00380                 returnvalue = hotstart_performStep(     FR_idx,FX_idx,AC_idx,IAC_idx,
00381                                                                                         delta_g,delta_lbA,delta_ubA,delta_lb,delta_ub,
00382                                                                                         delta_xFX,delta_xFR,delta_yAC,delta_yFX,delta_Ax,
00383                                                                                         BC_idx,BC_status,BC_isBound
00384                                                                                         );
00385 
00386                 if ( returnvalue != SUCCESSFUL_RETURN )
00387                 {
00388                         nWSR = l;
00389 
00390                         /* stop runtime measurement */
00391                         if ( cputime != 0 )
00392                                         *cputime = getCPUtime( ) - starttime;
00393 
00394                         /* optimal solution found? */
00395                         if ( returnvalue == RET_OPTIMAL_SOLUTION_FOUND )
00396                         {
00397                                 status = QPS_SOLVED;
00398 
00399                                 if ( printlevel == PL_HIGH )
00400                                         THROWINFO( RET_OPTIMAL_SOLUTION_FOUND );
00401 
00402                                 #ifdef PC_DEBUG
00403                                 if ( printIteration( l,BC_idx,BC_status,BC_isBound ) != SUCCESSFUL_RETURN )
00404                                         THROWERROR( RET_PRINT_ITERATION_FAILED ); /* do not pass this as return value! */
00405                                 #endif
00406 
00407                                 /* check KKT optimality conditions */
00408                                 return checkKKTconditions( );
00409                         }
00410                         else
00411                         {
00412                                 /* checks for infeasibility... */
00413                                 if ( isInfeasible( ) == BT_TRUE )
00414                                 {
00415                                         status = QPS_HOMOTOPYQPSOLVED;
00416                                         return THROWERROR( RET_HOTSTART_STOPPED_INFEASIBILITY );
00417                                 }
00418 
00419                                 /* ...unboundedness... */
00420                                 if ( unbounded == BT_TRUE ) /* not necessary since objective function convex! */
00421                                         return THROWERROR( RET_HOTSTART_STOPPED_UNBOUNDEDNESS );
00422 
00423                                 /* ... and throw unspecific error otherwise */
00424                                 THROWERROR( RET_HOMOTOPY_STEP_FAILED );
00425                                 return returnvalue;
00426                         }
00427                 }
00428 
00429                 /* 6) Output information of successful QP iteration. */
00430                 status = QPS_HOMOTOPYQPSOLVED;
00431 
00432                 #ifdef PC_DEBUG
00433                 if ( printIteration( l,BC_idx,BC_status,BC_isBound ) != SUCCESSFUL_RETURN )
00434                         THROWERROR( RET_PRINT_ITERATION_FAILED ); /* do not pass this as return value! */
00435                 #endif
00436         }
00437 
00438 
00439         /* stop runtime measurement */
00440         if ( cputime != 0 )
00441                 *cputime = getCPUtime( ) - starttime;
00442 
00443 
00444         /* if programm gets to here, output information that QP could not be solved
00445          * within the given maximum numbers of working set changes */
00446         if ( printlevel == PL_HIGH )
00447         {
00448                 #ifdef PC_DEBUG
00449                 sprintf( messageString,"(nWSR = %d)",nWSR );
00450                 return getGlobalMessageHandler( )->throwWarning( RET_MAX_NWSR_REACHED,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
00451                 #endif
00452         }
00453 
00454         /* Finally check KKT optimality conditions. */
00455         returnValue returnvalueKKTcheck = checkKKTconditions( );
00456 
00457         if ( returnvalueKKTcheck != SUCCESSFUL_RETURN )
00458                 return returnvalueKKTcheck;
00459         else
00460                 return RET_MAX_NWSR_REACHED;
00461 }
00462 
00463 
00464 /*
00465  *      g e t N Z
00466  */
00467 int QProblem::getNZ( )
00468 {
00469         /* nZ = nFR - nAC */
00470         return bounds.getFree( )->getLength( ) - constraints.getActive( )->getLength( );
00471 }
00472 
00473 
00474 /*
00475  *      g e t D u a l S o l u t i o n
00476  */
00477 returnValue QProblem::getDualSolution( real_t* const yOpt ) const
00478 {
00479         int i;
00480 
00481         /* return optimal dual solution vector
00482          * only if current QP has been solved */
00483         if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
00484                  ( getStatus( ) == QPS_HOMOTOPYQPSOLVED )  ||
00485                  ( getStatus( ) == QPS_SOLVED ) )
00486         {
00487                 for( i=0; i<getNV( )+getNC( ); ++i )
00488                         yOpt[i] = y[i];
00489 
00490                 return SUCCESSFUL_RETURN;
00491         }
00492         else
00493         {
00494                 return RET_QP_NOT_SOLVED;
00495         }
00496 }
00497 
00498 
00499 
00500 /*****************************************************************************
00501  *  P R O T E C T E D                                                        *
00502  *****************************************************************************/
00503 
00504 /*
00505  *      s e t u p S u b j e c t T o T y p e
00506  */
00507 returnValue QProblem::setupSubjectToType( )
00508 {
00509         int i;
00510         int nC = getNC( );
00511 
00512 
00513         /* I) SETUP SUBJECTTOTYPE FOR BOUNDS */
00514         if ( QProblemB::setupSubjectToType( ) != SUCCESSFUL_RETURN )
00515                 return THROWERROR( RET_SETUPSUBJECTTOTYPE_FAILED );
00516 
00517 
00518         /* II) SETUP SUBJECTTOTYPE FOR CONSTRAINTS */
00519         /* 1) Check if lower constraints' bounds are present. */
00520         constraints.setNoLower( BT_TRUE );
00521         for( i=0; i<nC; ++i )
00522         {
00523                 if ( lbA[i] > -INFTY )
00524                 {
00525                         constraints.setNoLower( BT_FALSE );
00526                         break;
00527                 }
00528         }
00529 
00530         /* 2) Check if upper constraints' bounds are present. */
00531         constraints.setNoUpper( BT_TRUE );
00532         for( i=0; i<nC; ++i )
00533         {
00534                 if ( ubA[i] < INFTY )
00535                 {
00536                         constraints.setNoUpper( BT_FALSE );
00537                         break;
00538                 }
00539         }
00540 
00541         /* 3) Determine implicit equality constraints and unbounded constraints. */
00542         int nEC = 0;
00543         int nUC = 0;
00544 
00545         for( i=0; i<nC; ++i )
00546         {
00547                 if ( ( lbA[i] < -INFTY + BOUNDTOL ) && ( ubA[i] > INFTY - BOUNDTOL ) )
00548                 {
00549                         constraints.setType( i,ST_UNBOUNDED );
00550                         ++nUC;
00551                 }
00552                 else
00553                 {
00554                         if ( lbA[i] > ubA[i] - BOUNDTOL )
00555                         {
00556                                 constraints.setType( i,ST_EQUALITY );
00557                                 ++nEC;
00558                         }
00559                         else
00560                         {
00561                                 constraints.setType( i,ST_BOUNDED );
00562                         }
00563                 }
00564         }
00565 
00566         /* 4) Set dimensions of constraints structure. */
00567         constraints.setNEC( nEC );
00568         constraints.setNUC( nUC );
00569         constraints.setNIC( nC - nEC - nUC );
00570 
00571         return SUCCESSFUL_RETURN;
00572 }
00573 
00574 
00575 /*
00576  *      c h o l e s k y D e c o m p o s i t i o n P r o j e c t e d
00577  */
00578 returnValue QProblem::setupCholeskyDecompositionProjected( )
00579 {
00580         int i, j, k, ii, kk;
00581         int nV  = getNV( );
00582         int nFR = getNFR( );
00583         int nZ  = getNZ( );
00584 
00585         /* 1) Initialises R with all zeros. */
00586         for( i=0; i<nV; ++i )
00587                 for( j=0; j<nV; ++j )
00588                         R[i*NVMAX + j] = 0.0;
00589 
00590         /* 2) Calculate Cholesky decomposition of projected Hessian Z'*H*Z. */
00591         if ( hessianType == HST_IDENTITY )
00592         {
00593                 /* if Hessian is identity, so is its Cholesky factor. */
00594                 for( i=0; i<nV; ++i )
00595                         R[i*NVMAX + i] = 1.0;
00596         }
00597         else
00598         {
00599                 if ( nZ > 0 )
00600                 {
00601                         int FR_idx[NVMAX];
00602                         if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
00603                                 return THROWERROR( RET_INDEXLIST_CORRUPTED );
00604 
00605                         int AC_idx[NCMAX_ALLOC];
00606                         if ( constraints.getActive( )->getNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
00607                                 return THROWERROR( RET_INDEXLIST_CORRUPTED );
00608 
00609 
00610                         real_t HZ[NVMAX*NVMAX];
00611                         real_t ZHZ[NVMAX*NVMAX];
00612 
00613                         /* calculate H*Z */
00614                         for ( i=0; i<nFR; ++i )
00615                         {
00616                                 ii = FR_idx[i];
00617 
00618                                 for ( j=0; j<nZ; ++j )
00619                                 {
00620                                         HZ[i*NVMAX + j] = 0.0;
00621                                         for ( k=0; k<nFR; ++k )
00622                                         {
00623                                                 kk = FR_idx[k];
00624                                                 HZ[i*NVMAX + j] += H[ii*NVMAX + kk] * Q[kk*NVMAX + j];
00625                                         }
00626                                 }
00627                         }
00628 
00629                         /* calculate Z'*H*Z */
00630                         for ( i=0; i<nZ; ++i )
00631                                 for ( j=0; j<nZ; ++j )
00632                                 {
00633                                         ZHZ[i*NVMAX + j] = 0.0;
00634                                         for ( k=0; k<nFR; ++k )
00635                                         {
00636                                                 kk = FR_idx[k];
00637                                                 ZHZ[i*NVMAX + j] += Q[kk*NVMAX + i] * HZ[k*NVMAX + j];
00638                                         }
00639                                 }
00640 
00641                         /* R'*R = Z'*H*Z */
00642                         real_t sum;
00643 
00644                         for( i=0; i<nZ; ++i )
00645                         {
00646                                 /* j == i */
00647                                 sum = ZHZ[i*NVMAX + i];
00648 
00649                                 for( k=(i-1); k>=0; --k )
00650                                         sum -= R[k*NVMAX + i] * R[k*NVMAX + i];
00651 
00652                                 if ( sum > 0.0 )
00653                                         R[i*NVMAX + i] = sqrt( sum );
00654                                 else
00655                                 {
00656                                         hessianType = HST_SEMIDEF;
00657                                         return THROWERROR( RET_HESSIAN_NOT_SPD );
00658                                 }
00659 
00660                                 for( j=(i+1); j<nZ; ++j )
00661                                 {
00662                                         sum = ZHZ[j*NVMAX + i];
00663 
00664                                         for( k=(i-1); k>=0; --k )
00665                                                 sum -= R[k*NVMAX + i] * R[k*NVMAX + j];
00666 
00667                                         R[i*NVMAX + j] = sum / R[i*NVMAX + i];
00668                                 }
00669                         }
00670                 }
00671         }
00672 
00673         return SUCCESSFUL_RETURN;
00674 }
00675 
00676 
00677 /*
00678  *      s e t u p T Q f a c t o r i s a t i o n
00679  */
00680 returnValue QProblem::setupTQfactorisation( )
00681 {
00682         int i, j, ii;
00683         int nV  = getNV( );
00684         int nFR = getNFR( );
00685 
00686         int FR_idx[NVMAX];
00687         if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
00688                 return THROWERROR( RET_INDEXLIST_CORRUPTED );
00689 
00690         /* 1) Set Q to unity matrix. */
00691         for( i=0; i<nV; ++i )
00692                 for( j=0; j<nV; ++j )
00693                         Q[i*NVMAX + j] = 0.0;
00694 
00695         for( i=0; i<nFR; ++i )
00696         {
00697                 ii = FR_idx[i];
00698                 Q[ii*NVMAX + i] = 1.0;
00699         }
00700 
00701         /* 2) Set T to zero matrix. */
00702         for( i=0; i<sizeT; ++i )
00703                 for( j=0; j<sizeT; ++j )
00704                         T[i*NVMAX + j] = 0.0;
00705 
00706         return SUCCESSFUL_RETURN;
00707 }
00708 
00709 
00710 /*
00711  *      s o l v e I n i t i a l Q P
00712  */
00713 returnValue QProblem::solveInitialQP(   const real_t* const xOpt, const real_t* const yOpt,
00714                                                                                 const Bounds* const guessedBounds, const Constraints* const guessedConstraints,
00715                                                                                 int& nWSR, real_t* const cputime
00716                                                                                 )
00717 {
00718         int i;
00719 
00720         /* some definitions */
00721         int nV = getNV( );
00722         int nC = getNC( );
00723 
00724 
00725         /* start runtime measurement */
00726         real_t starttime = 0.0;
00727         if ( cputime != 0 )
00728                 starttime = getCPUtime( );
00729 
00730 
00731         status = QPS_NOTINITIALISED;
00732 
00733         /* I) ANALYSE QP DATA: */
00734         /* 1) Check if Hessian happens to be the identity matrix. */
00735         if ( checkForIdentityHessian( ) != SUCCESSFUL_RETURN )
00736                 return THROWERROR( RET_INIT_FAILED );
00737 
00738         /* 2) Setup type of bounds and constraints (i.e. unbounded, implicitly fixed etc.). */
00739         if ( setupSubjectToType( ) != SUCCESSFUL_RETURN )
00740                 return THROWERROR( RET_INIT_FAILED );
00741 
00742         /* 3) Initialise cycling manager. */
00743         cyclingManager.clearCyclingData( );
00744 
00745         status = QPS_PREPARINGAUXILIARYQP;
00746 
00747 
00748         /* II) SETUP AUXILIARY QP WITH GIVEN OPTIMAL SOLUTION: */
00749         /* 1) Setup bounds and constraints data structure. */
00750         if ( bounds.setupAllFree( ) != SUCCESSFUL_RETURN )
00751                 return THROWERROR( RET_INIT_FAILED );
00752 
00753         if ( constraints.setupAllInactive( ) != SUCCESSFUL_RETURN )
00754                 return THROWERROR( RET_INIT_FAILED );
00755 
00756         /* 2) Setup optimal primal/dual solution for auxiliary QP. */
00757         if ( setupAuxiliaryQPsolution( xOpt,yOpt ) != SUCCESSFUL_RETURN )
00758                 return THROWERROR( RET_INIT_FAILED );
00759 
00760         /* 3) Obtain linear independent working set for auxiliary QP. */
00761 
00762         static Bounds auxiliaryBounds;
00763 
00764         auxiliaryBounds.init( nV );
00765 
00766         static Constraints auxiliaryConstraints;
00767 
00768         auxiliaryConstraints.init( nC );
00769 
00770         if ( obtainAuxiliaryWorkingSet( xOpt,yOpt,guessedBounds,guessedConstraints,
00771                                                                         &auxiliaryBounds,&auxiliaryConstraints ) != SUCCESSFUL_RETURN )
00772                 return THROWERROR( RET_INIT_FAILED );
00773 
00774         /* 4) Setup working set of auxiliary QP and setup matrix factorisations. */
00775         if ( setupTQfactorisation( ) != SUCCESSFUL_RETURN )
00776                 return THROWERROR( RET_INIT_FAILED_TQ );
00777 
00778         if ( setupAuxiliaryWorkingSet( &auxiliaryBounds,&auxiliaryConstraints,BT_TRUE ) != SUCCESSFUL_RETURN )
00779                 return THROWERROR( RET_INIT_FAILED );
00780 
00781         if ( ( getNAC( ) + getNFX( ) ) == 0 )
00782         {
00783                 /* Factorise full Hessian if no bounds/constraints are active. */
00784                 if ( setupCholeskyDecomposition( ) != SUCCESSFUL_RETURN )
00785                         return THROWERROR( RET_INIT_FAILED_CHOLESKY );
00786         }
00787         else
00788         {
00789                 /* Factorise projected Hessian if there active bounds/constraints. */
00790                 if ( setupCholeskyDecompositionProjected( ) != SUCCESSFUL_RETURN )
00791                         return THROWERROR( RET_INIT_FAILED_CHOLESKY );
00792         }
00793 
00794         /* 5) Store original QP formulation... */
00795         real_t g_original[NVMAX];
00796         real_t lb_original[NVMAX];
00797         real_t ub_original[NVMAX];
00798         real_t lbA_original[NCMAX_ALLOC];
00799         real_t ubA_original[NCMAX_ALLOC];
00800 
00801         for( i=0; i<nV; ++i )
00802         {
00803                 g_original[i] = g[i];
00804                 lb_original[i] = lb[i];
00805                 ub_original[i] = ub[i];
00806         }
00807 
00808         for( i=0; i<nC; ++i )
00809         {
00810                 lbA_original[i] = lbA[i];
00811                 ubA_original[i] = ubA[i];
00812         }
00813 
00814         /* ... and setup QP data of an auxiliary QP having an optimal solution
00815          * as specified by the user (or xOpt = yOpt = 0, by default). */
00816         if ( setupAuxiliaryQPgradient( ) != SUCCESSFUL_RETURN )
00817                 return THROWERROR( RET_INIT_FAILED );
00818 
00819         if ( setupAuxiliaryQPbounds( &auxiliaryBounds,&auxiliaryConstraints,BT_TRUE ) != SUCCESSFUL_RETURN )
00820                 return THROWERROR( RET_INIT_FAILED );
00821 
00822         status = QPS_AUXILIARYQPSOLVED;
00823 
00824 
00825         /* III) SOLVE ACTUAL INITIAL QP: */
00826         /* Use hotstart method to find the solution of the original initial QP,... */
00827         returnValue returnvalue = hotstart( g_original,lb_original,ub_original,lbA_original,ubA_original, nWSR,0 );
00828 
00829 
00830         /* ... check for infeasibility and unboundedness... */
00831         if ( isInfeasible( ) == BT_TRUE )
00832                 return THROWERROR( RET_INIT_FAILED_INFEASIBILITY );
00833 
00834         if ( isUnbounded( ) == BT_TRUE )
00835                 return THROWERROR( RET_INIT_FAILED_UNBOUNDEDNESS );
00836 
00837         /* ... and internal errors. */
00838         if ( ( returnvalue != SUCCESSFUL_RETURN ) && ( returnvalue != RET_MAX_NWSR_REACHED )  &&
00839              ( returnvalue != RET_INACCURATE_SOLUTION ) && ( returnvalue != RET_NO_SOLUTION ) )
00840                 return THROWERROR( RET_INIT_FAILED_HOTSTART );
00841 
00842 
00843         /* stop runtime measurement */
00844         if ( cputime != 0 )
00845                 *cputime = getCPUtime( ) - starttime;
00846 
00847         if ( printlevel == PL_HIGH )
00848                 THROWINFO( RET_INIT_SUCCESSFUL );
00849 
00850         return returnvalue;
00851 }
00852 
00853 
00854 /*
00855  *      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
00856  */
00857 returnValue QProblem::obtainAuxiliaryWorkingSet(        const real_t* const xOpt, const real_t* const yOpt,
00858                                                                                                         const Bounds* const guessedBounds, const Constraints* const guessedConstraints,
00859                                                                                                         Bounds* auxiliaryBounds, Constraints* auxiliaryConstraints
00860                                                                                                         ) const
00861 {
00862         int i = 0;
00863         int nV = getNV( );
00864         int nC = getNC( );
00865 
00866 
00867         /* 1) Ensure that desiredBounds is allocated (and different from guessedBounds). */
00868         if ( ( auxiliaryBounds == 0 ) || ( auxiliaryBounds == guessedBounds ) )
00869                 return THROWERROR( RET_INVALID_ARGUMENTS );
00870 
00871         if ( ( auxiliaryConstraints == 0 ) || ( auxiliaryConstraints == guessedConstraints ) )
00872                 return THROWERROR( RET_INVALID_ARGUMENTS );
00873 
00874 
00875         SubjectToStatus guessedStatus;
00876 
00877         /* 2) Setup working set of bounds for auxiliary initial QP. */
00878         if ( QProblemB::obtainAuxiliaryWorkingSet( xOpt,yOpt,guessedBounds, auxiliaryBounds ) != SUCCESSFUL_RETURN )
00879                 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00880 
00881         /* 3) Setup working set of constraints for auxiliary initial QP. */
00882         if ( guessedConstraints != 0 )
00883         {
00884                 /* If an initial working set is specific, use it!
00885                  * Moreover, add all equality constraints if specified. */
00886                 for( i=0; i<nC; ++i )
00887                 {
00888                         guessedStatus = guessedConstraints->getStatus( i );
00889 
00890                         if ( constraints.getType( i ) == ST_EQUALITY )
00891                         {
00892                                 if ( auxiliaryConstraints->setupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00893                                         return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00894                         }
00895                         else
00896                         {
00897                                 if ( auxiliaryConstraints->setupConstraint( i,guessedStatus ) != SUCCESSFUL_RETURN )
00898                                         return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00899                         }
00900                 }
00901         }
00902         else    /* No initial working set specified. */
00903         {
00904                 /* Obtain initial working set by "clipping". */
00905                 if ( ( xOpt != 0 ) && ( yOpt == 0 ) )
00906                 {
00907                         for( i=0; i<nC; ++i )
00908                         {
00909                                 if ( Ax[i] <= lbA[i] + BOUNDTOL )
00910                                 {
00911                                         if ( auxiliaryConstraints->setupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00912                                                 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00913                                         continue;
00914                                 }
00915 
00916                                 if ( Ax[i] >= ubA[i] - BOUNDTOL )
00917                                 {
00918                                         if ( auxiliaryConstraints->setupConstraint( i,ST_UPPER ) != SUCCESSFUL_RETURN )
00919                                                         return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00920                                         continue;
00921                                 }
00922 
00923                                 /* Moreover, add all equality constraints if specified. */
00924                                 if ( constraints.getType( i ) == ST_EQUALITY )
00925                                 {
00926                                         if ( auxiliaryConstraints->setupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00927                                                 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00928                                 }
00929                                 else
00930                                 {
00931                                         if ( auxiliaryConstraints->setupConstraint( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
00932                                                 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00933                                 }
00934                         }
00935                 }
00936 
00937                 /* Obtain initial working set in accordance to sign of dual solution vector. */
00938                 if ( ( xOpt == 0 ) && ( yOpt != 0 ) )
00939                 {
00940                         for( i=0; i<nC; ++i )
00941                         {
00942                                 if ( yOpt[nV+i] > ZERO )
00943                                 {
00944                                         if ( auxiliaryConstraints->setupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00945                                                 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00946                                         continue;
00947                                 }
00948 
00949                                 if ( yOpt[nV+i] < -ZERO )
00950                                 {
00951                                         if ( auxiliaryConstraints->setupConstraint( i,ST_UPPER ) != SUCCESSFUL_RETURN )
00952                                                 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00953                                         continue;
00954                                 }
00955 
00956                                 /* Moreover, add all equality constraints if specified. */
00957                                 if ( constraints.getType( i ) == ST_EQUALITY )
00958                                 {
00959                                         if ( auxiliaryConstraints->setupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00960                                                 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00961                                 }
00962                                 else
00963                                 {
00964                                         if ( auxiliaryConstraints->setupConstraint( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
00965                                                 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00966                                 }
00967                         }
00968                 }
00969 
00970                 /* If xOpt and yOpt are null pointer and no initial working is specified,
00971                  * start with empty working set (or implicitly fixed bounds and equality constraints only)
00972                  * for auxiliary QP. */
00973                 if ( ( xOpt == 0 ) && ( yOpt == 0 ) )
00974                 {
00975                         for( i=0; i<nC; ++i )
00976                         {
00977                                 /* Only add all equality constraints if specified. */
00978                                 if ( constraints.getType( i ) == ST_EQUALITY )
00979                                 {
00980                                         if ( auxiliaryConstraints->setupConstraint( i,ST_LOWER ) != SUCCESSFUL_RETURN )
00981                                                 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00982                                 }
00983                                 else
00984                                 {
00985                                         if ( auxiliaryConstraints->setupConstraint( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
00986                                                 return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
00987                                 }
00988                         }
00989                 }
00990         }
00991 
00992         return SUCCESSFUL_RETURN;
00993 }
00994 
00995 
00996 
00997 /*
00998  *      s e t u p A u x i l i a r y W o r k i n g S e t
00999  */
01000 returnValue QProblem::setupAuxiliaryWorkingSet( const Bounds* const auxiliaryBounds,
01001                                                                                                 const Constraints* const auxiliaryConstraints,
01002                                                                                                 BooleanType setupAfresh
01003                                                                                                 )
01004 {
01005         int i;
01006         int nV = getNV( );
01007         int nC = getNC( );
01008 
01009         /* consistency checks */
01010         if ( auxiliaryBounds != 0 )
01011         {
01012                 for( i=0; i<nV; ++i )
01013                         if ( ( bounds.getStatus( i ) == ST_UNDEFINED ) || ( auxiliaryBounds->getStatus( i ) == ST_UNDEFINED ) )
01014                                 return THROWERROR( RET_UNKNOWN_BUG );
01015         }
01016         else
01017         {
01018                 return THROWERROR( RET_INVALID_ARGUMENTS );
01019         }
01020 
01021         if ( auxiliaryConstraints != 0 )
01022         {
01023                 for( i=0; i<nC; ++i )
01024                         if ( ( constraints.getStatus( i ) == ST_UNDEFINED ) || ( auxiliaryConstraints->getStatus( i ) == ST_UNDEFINED ) )
01025                                 return THROWERROR( RET_UNKNOWN_BUG );
01026         }
01027         else
01028         {
01029                 return THROWERROR( RET_INVALID_ARGUMENTS );
01030         }
01031 
01032 
01033         /* I) SETUP CHOLESKY FLAG:
01034          *    Cholesky decomposition shall only be updated if working set
01035          *    shall be updated (i.e. NOT setup afresh!) */
01036         BooleanType updateCholesky;
01037         if ( setupAfresh == BT_TRUE )
01038                 updateCholesky = BT_FALSE;
01039         else
01040                 updateCholesky = BT_TRUE;
01041 
01042 
01043         /* II) REMOVE FORMERLY ACTIVE (CONSTRAINTS') BOUNDS (IF NECESSARY): */
01044         if ( setupAfresh == BT_FALSE )
01045         {
01046                 /* 1) Remove all active constraints that shall be inactive AND
01047                 *    all active constraints that are active at the wrong bound. */
01048                 for( i=0; i<nC; ++i )
01049                 {
01050                         if ( ( constraints.getStatus( i ) == ST_LOWER ) && ( auxiliaryConstraints->getStatus( i ) != ST_LOWER ) )
01051                                 if ( removeConstraint( i,updateCholesky ) != SUCCESSFUL_RETURN )
01052                                         return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
01053 
01054                         if ( ( constraints.getStatus( i ) == ST_UPPER ) && ( auxiliaryConstraints->getStatus( i ) != ST_UPPER ) )
01055                                 if ( removeConstraint( i,updateCholesky ) != SUCCESSFUL_RETURN )
01056                                         return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
01057                 }
01058 
01059                 /* 2) Remove all active bounds that shall be inactive AND
01060                 *    all active bounds that are active at the wrong bound. */
01061                 for( i=0; i<nV; ++i )
01062                 {
01063                         if ( ( bounds.getStatus( i ) == ST_LOWER ) && ( auxiliaryBounds->getStatus( i ) != ST_LOWER ) )
01064                                 if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
01065                                         return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
01066 
01067                         if ( ( bounds.getStatus( i ) == ST_UPPER ) && ( auxiliaryBounds->getStatus( i ) != ST_UPPER ) )
01068                                 if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
01069                                         return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
01070                 }
01071         }
01072 
01073 
01074         /* III) ADD NEWLY ACTIVE (CONSTRAINTS') BOUNDS: */
01075         /* 1) Add all inactive bounds that shall be active AND
01076          *    all formerly active bounds that have been active at the wrong bound. */
01077         for( i=0; i<nV; ++i )
01078         {
01079                 if ( ( bounds.getStatus( i ) == ST_INACTIVE ) && ( auxiliaryBounds->getStatus( i ) != ST_INACTIVE ) )
01080                 {
01081                         /* Add bound only if it is linearly independent from the current working set. */
01082                         if ( addBound_checkLI( i ) == RET_LINEARLY_INDEPENDENT )
01083                         {
01084                                 if ( addBound( i,auxiliaryBounds->getStatus( i ),updateCholesky ) != SUCCESSFUL_RETURN )
01085                                         return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
01086                         }
01087                 }
01088         }
01089 
01090         /* 2) Add all inactive constraints that shall be active AND
01091          *    all formerly active constraints that have been active at the wrong bound. */
01092         for( i=0; i<nC; ++i )
01093         {
01094                 if ( ( auxiliaryConstraints->getStatus( i ) == ST_LOWER ) || ( auxiliaryConstraints->getStatus( i ) == ST_UPPER ) )
01095                 {
01096                         /* formerly inactive */
01097                         if ( constraints.getStatus( i ) == ST_INACTIVE )
01098                         {
01099                                 /* Add constraint only if it is linearly independent from the current working set. */
01100                                 if ( addConstraint_checkLI( i ) == RET_LINEARLY_INDEPENDENT )
01101                                 {
01102                                         if ( addConstraint( i,auxiliaryConstraints->getStatus( i ),updateCholesky ) != SUCCESSFUL_RETURN )
01103                                                 return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
01104                                 }
01105                         }
01106                 }
01107         }
01108 
01109         return SUCCESSFUL_RETURN;
01110 }
01111 
01112 
01113 /*
01114  *      s e t u p A u x i l i a r y Q P s o l u t i o n
01115  */
01116 returnValue QProblem::setupAuxiliaryQPsolution( const real_t* const xOpt, const real_t* const yOpt
01117                                                                                                 )
01118 {
01119         int i, j;
01120         int nV = getNV( );
01121         int nC = getNC( );
01122 
01123 
01124         /* Setup primal/dual solution vector for auxiliary initial QP:
01125          * if a null pointer is passed, a zero vector is assigned;
01126          *  old solution vector is kept if pointer to internal solution vevtor is passed. */
01127         if ( xOpt != 0 )
01128         {
01129                 if ( xOpt != x )
01130                         for( i=0; i<nV; ++i )
01131                                 x[i] = xOpt[i];
01132 
01133                 for ( j=0; j<nC; ++j )
01134                 {
01135                         Ax[j] = 0.0;
01136 
01137                         for( i=0; i<nV; ++i )
01138                                 Ax[j] += A[j*NVMAX + i] * x[i];
01139                 }
01140         }
01141         else
01142         {
01143                 for( i=0; i<nV; ++i )
01144                         x[i] = 0.0;
01145 
01146                 for ( j=0; j<nC; ++j )
01147                         Ax[j] = 0.0;
01148         }
01149 
01150         if ( yOpt != 0 )
01151         {
01152                 if ( yOpt != y )
01153                         for( i=0; i<nV+nC; ++i )
01154                                 y[i] = yOpt[i];
01155         }
01156         else
01157         {
01158                 for( i=0; i<nV+nC; ++i )
01159                         y[i] = 0.0;
01160         }
01161 
01162         return SUCCESSFUL_RETURN;
01163 }
01164 
01165 
01166 /*
01167  *      s e t u p A u x i l i a r y Q P g r a d i e n t
01168  */
01169 returnValue QProblem::setupAuxiliaryQPgradient( )
01170 {
01171         int i, j;
01172         int nV = getNV( );
01173         int nC = getNC( );
01174 
01175 
01176         /* Setup gradient vector: g = -H*x + [Id A]'*[yB yC]. */
01177         for ( i=0; i<nV; ++i )
01178         {
01179                 /* Id'*yB */
01180                 g[i] = y[i];
01181 
01182                 /* A'*yC */
01183                 for ( j=0; j<nC; ++j )
01184                         g[i] += A[j*NVMAX + i] * y[nV+j];
01185 
01186                 /* -H*x */
01187                 for ( j=0; j<nV; ++j )
01188                         g[i] -= H[i*NVMAX + j] * x[j];
01189         }
01190 
01191         return SUCCESSFUL_RETURN;
01192 }
01193 
01194 
01195 /*
01196  *      s e t u p A u x i l i a r y Q P b o u n d s
01197  */
01198 returnValue QProblem::setupAuxiliaryQPbounds(   const Bounds* const auxiliaryBounds,
01199                                                                                                 const Constraints* const auxiliaryConstraints,
01200                                                                                                 BooleanType useRelaxation
01201                                                                                                 )
01202 {
01203         int i;
01204         int nV = getNV( );
01205         int nC = getNC( );
01206 
01207 
01208         /* 1) Setup bound vectors. */
01209         for ( i=0; i<nV; ++i )
01210         {
01211                 switch ( bounds.getStatus( i ) )
01212                 {
01213                         case ST_INACTIVE:
01214                                 if ( useRelaxation == BT_TRUE )
01215                                 {
01216                                         if ( bounds.getType( i ) == ST_EQUALITY )
01217                                         {
01218                                                 lb[i] = x[i];
01219                                                 ub[i] = x[i];
01220                                         }
01221                                         else
01222                                         {
01223                                                 /* If a bound is inactive although it was supposed to be
01224                                                 * active by the auxiliaryBounds, it could not be added
01225                                                 * due to linear dependence. Thus set it "strongly inactive". */
01226                                                 if ( auxiliaryBounds->getStatus( i ) == ST_LOWER )
01227                                                         lb[i] = x[i];
01228                                                 else
01229                                                         lb[i] = x[i] - BOUNDRELAXATION;
01230 
01231                                                 if ( auxiliaryBounds->getStatus( i ) == ST_UPPER )
01232                                                         ub[i] = x[i];
01233                                                 else
01234                                                         ub[i] = x[i] + BOUNDRELAXATION;
01235                                         }
01236                                 }
01237                                 break;
01238 
01239                         case ST_LOWER:
01240                                 lb[i] = x[i];
01241                                 if ( bounds.getType( i ) == ST_EQUALITY )
01242                                 {
01243                                         ub[i] = x[i];
01244                                 }
01245                                 else
01246                                 {
01247                                         if ( useRelaxation == BT_TRUE )
01248                                                 ub[i] = x[i] + BOUNDRELAXATION;
01249                                 }
01250                                 break;
01251 
01252                         case ST_UPPER:
01253                                 ub[i] = x[i];
01254                                 if ( bounds.getType( i ) == ST_EQUALITY )
01255                                 {
01256                                         lb[i] = x[i];
01257                                 }
01258                                 else
01259                                 {
01260                                         if ( useRelaxation == BT_TRUE )
01261                                                 lb[i] = x[i] - BOUNDRELAXATION;
01262                                 }
01263                                 break;
01264 
01265                         default:
01266                                 return THROWERROR( RET_UNKNOWN_BUG );
01267                 }
01268         }
01269 
01270         /* 2) Setup constraints vectors. */
01271         for ( i=0; i<nC; ++i )
01272         {
01273                 switch ( constraints.getStatus( i ) )
01274                 {
01275                         case ST_INACTIVE:
01276                                 if ( useRelaxation == BT_TRUE )
01277                                 {
01278                                         if ( constraints.getType( i ) == ST_EQUALITY )
01279                                         {
01280                                                 lbA[i] = Ax[i];
01281                                                 ubA[i] = Ax[i];
01282                                         }
01283                                         else
01284                                         {
01285                                                 /* If a constraint is inactive although it was supposed to be
01286                                                 * active by the auxiliaryConstraints, it could not be added
01287                                                 * due to linear dependence. Thus set it "strongly inactive". */
01288                                                 if ( auxiliaryConstraints->getStatus( i ) == ST_LOWER )
01289                                                         lbA[i] = Ax[i];
01290                                                 else
01291                                                         lbA[i] = Ax[i] - BOUNDRELAXATION;
01292 
01293                                                 if ( auxiliaryConstraints->getStatus( i ) == ST_UPPER )
01294                                                         ubA[i] = Ax[i];
01295                                                 else
01296                                                         ubA[i] = Ax[i] + BOUNDRELAXATION;
01297                                         }
01298                                 }
01299                                 break;
01300 
01301                         case ST_LOWER:
01302                                 lbA[i] = Ax[i];
01303                                 if ( constraints.getType( i ) == ST_EQUALITY )
01304                                 {
01305                                         ubA[i] = Ax[i];
01306                                 }
01307                                 else
01308                                 {
01309                                         if ( useRelaxation == BT_TRUE )
01310                                                 ubA[i] = Ax[i] + BOUNDRELAXATION;
01311                                 }
01312                                 break;
01313 
01314                         case ST_UPPER:
01315                                 ubA[i] = Ax[i];
01316                                 if ( constraints.getType( i ) == ST_EQUALITY )
01317                                 {
01318                                         lbA[i] = Ax[i];
01319                                 }
01320                                 else
01321                                 {
01322                                         if ( useRelaxation == BT_TRUE )
01323                                                 lbA[i] = Ax[i] - BOUNDRELAXATION;
01324                                 }
01325                                 break;
01326 
01327                         default:
01328                                 return THROWERROR( RET_UNKNOWN_BUG );
01329                 }
01330         }
01331 
01332         return SUCCESSFUL_RETURN;
01333 }
01334 
01335 
01336 /*
01337  *      a d d C o n s t r a i n t
01338  */
01339 returnValue QProblem::addConstraint(    int number, SubjectToStatus C_status,
01340                                                                                 BooleanType updateCholesky
01341                                                                                 )
01342 {
01343         int i, j, ii;
01344 
01345         /* consistency checks */
01346         if ( constraints.getStatus( number ) != ST_INACTIVE )
01347                 return THROWERROR( RET_CONSTRAINT_ALREADY_ACTIVE );
01348 
01349         if ( ( constraints.getNC( ) - getNAC( ) ) == constraints.getNUC( ) )
01350                 return THROWERROR( RET_ALL_CONSTRAINTS_ACTIVE );
01351 
01352         if ( ( getStatus( ) == QPS_NOTINITIALISED )    ||
01353                  ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
01354                  ( getStatus( ) == QPS_HOMOTOPYQPSOLVED )  ||
01355                  ( getStatus( ) == QPS_SOLVED )            )
01356         {
01357                 return THROWERROR( RET_UNKNOWN_BUG );
01358         }
01359 
01360 
01361         /* I) ENSURE LINEAR INDEPENDENCE OF THE WORKING SET,
01362          *    i.e. remove a constraint or bound if linear dependence occurs. */
01363         /* check for LI only if Cholesky decomposition shall be updated! */
01364         if ( updateCholesky == BT_TRUE )
01365         {
01366                 returnValue ensureLIreturnvalue = addConstraint_ensureLI( number,C_status );
01367 
01368                 switch ( ensureLIreturnvalue )
01369                 {
01370                         case SUCCESSFUL_RETURN:
01371                                 break;
01372 
01373                         case RET_LI_RESOLVED:
01374                                 break;
01375 
01376                         case RET_ENSURELI_FAILED_NOINDEX:
01377                                 return THROWERROR( RET_ADDCONSTRAINT_FAILED_INFEASIBILITY );
01378 
01379                         case RET_ENSURELI_FAILED_CYCLING:
01380                                 return THROWERROR( RET_ADDCONSTRAINT_FAILED_INFEASIBILITY );
01381 
01382                         default:
01383                                 return THROWERROR( RET_ENSURELI_FAILED );
01384                 }
01385         }
01386 
01387         /* some definitions */
01388         int nFR = getNFR( );
01389         int nAC = getNAC( );
01390         int nZ  = getNZ( );
01391 
01392         int tcol = sizeT - nAC;
01393 
01394 
01395         int FR_idx[NVMAX];
01396         if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
01397                 return THROWERROR( RET_ADDCONSTRAINT_FAILED );
01398 
01399         real_t aFR[NVMAX];
01400         real_t wZ[NVMAX];
01401         for( i=0; i<nZ; ++i )
01402                 wZ[i] = 0.0;
01403 
01404 
01405         /* II) ADD NEW ACTIVE CONSTRAINT TO MATRIX T: */
01406         /* 1) Add row [wZ wY] = aFR'*[Z Y] to the end of T: assign aFR. */
01407         for( i=0; i<nFR; ++i )
01408         {
01409                 ii = FR_idx[i];
01410                 aFR[i] = A[number*NVMAX + ii];
01411         }
01412 
01413         /* calculate wZ */
01414         for( i=0; i<nFR; ++i )
01415         {
01416                 ii = FR_idx[i];
01417                 for( j=0; j<nZ; ++j )
01418                         wZ[j] += aFR[i] * Q[ii*NVMAX + j];
01419         }
01420 
01421         /* 2) Calculate wY and store it directly into T. */
01422         if ( nAC > 0 )
01423         {
01424                 for( j=0; j<nAC; ++j )
01425                         T[nAC*NVMAX + tcol+j] = 0.0;
01426                 for( i=0; i<nFR; ++i )
01427                 {
01428                         ii = FR_idx[i];
01429                         for( j=0; j<nAC; ++j )
01430                                 T[nAC*NVMAX + tcol+j] += aFR[i] * Q[ii*NVMAX + nZ+j];
01431                 }
01432         }
01433 
01434 
01435         real_t c, s;
01436 
01437         if ( nZ > 0 )
01438         {
01439                 /* II) RESTORE TRIANGULAR FORM OF T: */
01440                 /*     Use column-wise Givens rotations to restore reverse triangular form
01441                 *      of T, simultanenous change of Q (i.e. Z) and R. */
01442                 for( j=0; j<nZ-1; ++j )
01443                 {
01444                         computeGivens( wZ[j+1],wZ[j], wZ[j+1],wZ[j],c,s );
01445 
01446                         for( i=0; i<nFR; ++i )
01447                         {
01448                                 ii = FR_idx[i];
01449                                 applyGivens( c,s,Q[ii*NVMAX + 1+j],Q[ii*NVMAX + j], Q[ii*NVMAX + 1+j],Q[ii*NVMAX + j] );
01450                         }
01451 
01452                         if ( ( updateCholesky == BT_TRUE ) && ( hessianType != HST_IDENTITY ) )
01453                         {
01454                                 for( i=0; i<=j+1; ++i )
01455                                         applyGivens( c,s,R[i*NVMAX + 1+j],R[i*NVMAX + j], R[i*NVMAX + 1+j],R[i*NVMAX + j] );
01456                         }
01457                 }
01458 
01459                 T[nAC*NVMAX + tcol-1] = wZ[nZ-1];
01460 
01461 
01462                 if ( ( updateCholesky == BT_TRUE ) && ( hessianType != HST_IDENTITY ) )
01463                 {
01464                         /* III) RESTORE TRIANGULAR FORM OF R:
01465                          *      Use row-wise Givens rotations to restore upper triangular form of R. */
01466                         for( i=0; i<nZ-1; ++i )
01467                         {
01468                                 computeGivens( R[i*NVMAX + i],R[(1+i)*NVMAX + i], R[i*NVMAX + i],R[(1+i)*NVMAX + i],c,s );
01469 
01470                                 for( j=(1+i); j<(nZ-1); ++j ) /* last column of R is thrown away */
01471                                         applyGivens( c,s,R[i*NVMAX + j],R[(1+i)*NVMAX + j], R[i*NVMAX + j],R[(1+i)*NVMAX + j] );
01472                         }
01473                         /* last column of R is thrown away */
01474                         for( i=0; i<nZ; ++i )
01475                                 R[i*NVMAX + nZ-1] = 0.0;
01476                 }
01477         }
01478 
01479 
01480         /* IV) UPDATE INDICES */
01481         if ( constraints.moveInactiveToActive( number,C_status ) != SUCCESSFUL_RETURN )
01482                 return THROWERROR( RET_ADDCONSTRAINT_FAILED );
01483 
01484 
01485         return SUCCESSFUL_RETURN;
01486 }
01487 
01488 
01489 
01490 /*
01491  *      a d d C o n s t r a i n t _ c h e c k L I
01492  */
01493 returnValue QProblem::addConstraint_checkLI( int number )
01494 {
01495         int i, j, jj;
01496         int nFR = getNFR( );
01497         int nZ  = getNZ( );
01498 
01499         int FR_idx[NVMAX];
01500         if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
01501                 return THROWERROR( RET_INDEXLIST_CORRUPTED );
01502 
01503         /* Check if constraint <number> is linearly independent from the
01504            the active ones (<=> is element of null space of Afr). */
01505         real_t sum;
01506 
01507         for( i=0; i<nZ; ++i )
01508         {
01509                 sum = 0.0;
01510                 for( j=0; j<nFR; ++j )
01511                 {
01512                         jj = FR_idx[j];
01513                         sum += Q[jj*NVMAX + i] * A[number*NVMAX + jj];
01514                 }
01515 
01516                 if ( getAbs( sum ) > 10.0*EPS )
01517                         return RET_LINEARLY_INDEPENDENT;
01518         }
01519 
01520         return RET_LINEARLY_DEPENDENT;
01521 }
01522 
01523 
01524 /*
01525  *      a d d C o n s t r a i n t _ e n s u r e L I
01526  */
01527 returnValue QProblem::addConstraint_ensureLI( int number, SubjectToStatus C_status )
01528 {
01529         int i, j, ii, jj;
01530         int nV  = getNV( );
01531         int nFR = getNFR( );
01532         int nFX = getNFX( );
01533         int nAC = getNAC( );
01534         int nZ  = getNZ( );
01535 
01536 
01537         /* I) Check if new constraint is linearly independent from the active ones. */
01538         returnValue returnvalueCheckLI = addConstraint_checkLI( number );
01539 
01540         if ( returnvalueCheckLI == RET_INDEXLIST_CORRUPTED )
01541                 return THROWERROR( RET_ENSURELI_FAILED );
01542 
01543         if ( returnvalueCheckLI == RET_LINEARLY_INDEPENDENT )
01544                 return SUCCESSFUL_RETURN;
01545 
01546 
01547         /* II) NEW CONSTRAINT IS LINEARLY DEPENDENT: */
01548         /* 1) Determine coefficients of linear combination,
01549          *    cf. M.J. Best. Applied Mathematics and Parallel Computing, chapter:
01550          *    An Algorithm for the Solution of the Parametric Quadratic Programming
01551          *    Problem, pages 57-76. Physica-Verlag, Heidelberg, 1996. */
01552         int FR_idx[NVMAX];
01553         if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
01554                 return THROWERROR( RET_ENSURELI_FAILED );
01555 
01556         int FX_idx[NVMAX];
01557         if ( bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
01558                 return THROWERROR( RET_ENSURELI_FAILED );
01559 
01560         real_t xiC[NCMAX_ALLOC];
01561         real_t xiC_TMP[NCMAX_ALLOC];
01562         real_t xiB[NVMAX];
01563 
01564         /* 2) Calculate xiC */
01565         if ( nAC > 0 )
01566         {
01567                 if ( C_status == ST_LOWER )
01568                 {
01569                         for( i=0; i<nAC; ++i )
01570                         {
01571                                 xiC_TMP[i] = 0.0;
01572                                 for( j=0; j<nFR; ++j )
01573                                 {
01574                                         jj = FR_idx[j];
01575                                         xiC_TMP[i] += Q[jj*NVMAX + nZ+i] * A[number*NVMAX + jj];
01576                                 }
01577                         }
01578                 }
01579                 else
01580                 {
01581                         for( i=0; i<nAC; ++i )
01582                         {
01583                                 xiC_TMP[i] = 0.0;
01584                                 for( j=0; j<nFR; ++j )
01585                                 {
01586                                         jj = FR_idx[j];
01587                                         xiC_TMP[i] -= Q[jj*NVMAX + nZ+i] * A[number*NVMAX + jj];
01588                                 }
01589                         }
01590                 }
01591 
01592                 if ( backsolveT( xiC_TMP, BT_TRUE, xiC ) != SUCCESSFUL_RETURN )
01593                         return THROWERROR( RET_ENSURELI_FAILED_TQ );
01594         }
01595 
01596         /* 3) Calculate xiB. */
01597         int AC_idx[NCMAX_ALLOC];
01598         if ( constraints.getActive( )->getNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
01599                 return THROWERROR( RET_ENSURELI_FAILED );
01600 
01601         if ( C_status == ST_LOWER )
01602         {
01603                 for( i=0; i<nFX; ++i )
01604                 {
01605                         ii = FX_idx[i];
01606                         xiB[i] = A[number*NVMAX + ii];
01607 
01608                         for( j=0; j<nAC; ++j )
01609                         {
01610                                 jj = AC_idx[j];
01611                                 xiB[i] -= A[jj*NVMAX + ii] * xiC[j];
01612                         }
01613                 }
01614         }
01615         else
01616         {
01617                 for( i=0; i<nFX; ++i )
01618                 {
01619                         ii = FX_idx[i];
01620                         xiB[i] = -A[number*NVMAX + ii];
01621 
01622                         for( j=0; j<nAC; ++j )
01623                         {
01624                                 jj = AC_idx[j];
01625                                 xiB[i] -= A[jj*NVMAX + ii] * xiC[j];
01626                         }
01627                 }
01628         }
01629 
01630 
01631         /* III) DETERMINE CONSTRAINT/BOUND TO BE REMOVED. */
01632         real_t y_min = INFTY * INFTY;
01633         int y_min_number = -1;
01634         BooleanType y_min_isBound = BT_FALSE;
01635 
01636         /* 1) Constraints. */
01637         for( i=0; i<nAC; ++i )
01638         {
01639                 ii = AC_idx[i];
01640 
01641                 if ( constraints.getStatus( ii ) == ST_LOWER )
01642                 {
01643                         if ( ( xiC[i] > ZERO ) && ( y[nV+ii] >= 0.0 ) )
01644                         {
01645                                 if ( y[nV+ii]/xiC[i] < y_min )
01646                                 {
01647                                         y_min = y[nV+ii]/xiC[i];
01648                                         y_min_number = ii;
01649                                 }
01650                         }
01651                 }
01652                 else
01653                 {
01654                         if ( ( xiC[i] < -ZERO ) && ( y[nV+ii] <= 0.0 ) )
01655                         {
01656                                 if ( y[nV+ii]/xiC[i] < y_min )
01657                                 {
01658                                         y_min = y[nV+ii]/xiC[i];
01659                                         y_min_number = ii;
01660                                 }
01661                         }
01662                 }
01663         }
01664 
01665         /* 2) Bounds. */
01666         for( i=0; i<nFX; ++i )
01667         {
01668                 ii = FX_idx[i];
01669 
01670                 if ( bounds.getStatus( ii ) == ST_LOWER )
01671                 {
01672                         if ( ( xiB[i] > ZERO ) && ( y[ii] >= 0.0 ) )
01673                         {
01674                                 if ( y[ii]/xiB[i] < y_min )
01675                                 {
01676                                         y_min = y[ii]/xiB[i];
01677                                         y_min_number = ii;
01678                                         y_min_isBound = BT_TRUE;
01679                                 }
01680                         }
01681                 }
01682                 else
01683                 {
01684                         if ( ( xiB[i] < -ZERO ) && ( y[ii] <= 0.0 ) )
01685                         {
01686                                 if ( y[ii]/xiB[i] < y_min )
01687                                 {
01688                                         y_min = y[ii]/xiB[i];
01689                                         y_min_number = ii;
01690                                         y_min_isBound = BT_TRUE;
01691                                 }
01692                         }
01693                 }
01694         }
01695 
01696         /* setup output preferences */
01697         #ifdef PC_DEBUG
01698         char messageString[80];
01699         VisibilityStatus visibilityStatus;
01700 
01701         if ( printlevel == PL_HIGH )
01702                 visibilityStatus = VS_VISIBLE;
01703         else
01704                 visibilityStatus = VS_HIDDEN;
01705         #endif
01706 
01707 
01708         /* IV) REMOVE CONSTRAINT/BOUND FOR RESOLVING LINEAR DEPENDENCE: */
01709         if ( y_min_number >= 0 )
01710         {
01711                 /* 1) Check for cycling due to infeasibility. */
01712                 if ( ( cyclingManager.getCyclingStatus( number,BT_FALSE ) == CYC_PREV_REMOVED ) &&
01713                          ( cyclingManager.getCyclingStatus( y_min_number,y_min_isBound ) == CYC_PREV_ADDED ) )
01714                 {
01715                         infeasible = BT_TRUE;
01716 
01717                         return THROWERROR( RET_ENSURELI_FAILED_CYCLING );
01718                 }
01719                 else
01720                 {
01721                         /* set cycling data */
01722                         cyclingManager.clearCyclingData( );
01723                         cyclingManager.setCyclingStatus( number,BT_FALSE, CYC_PREV_ADDED );
01724                         cyclingManager.setCyclingStatus( y_min_number,y_min_isBound, CYC_PREV_REMOVED );
01725                 }
01726 
01727                 /* 2) Update Lagrange multiplier... */
01728                 for( i=0; i<nAC; ++i )
01729                 {
01730                         ii = AC_idx[i];
01731                         y[nV+ii] -= y_min * xiC[i];
01732                 }
01733                 for( i=0; i<nFX; ++i )
01734                 {
01735                         ii = FX_idx[i];
01736                         y[ii] -= y_min * xiB[i];
01737                 }
01738 
01739                 /* ... also for newly active constraint... */
01740                 if ( C_status == ST_LOWER )
01741                         y[nV+number] = y_min;
01742                 else
01743                         y[nV+number] = -y_min;
01744 
01745                 /* ... and for constraint to be removed. */
01746                 if ( y_min_isBound == BT_TRUE )
01747                 {
01748                         #ifdef PC_DEBUG
01749                         sprintf( messageString,"bound no. %d.",y_min_number );
01750                         getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
01751                         #endif
01752 
01753                         if ( removeBound( y_min_number,BT_TRUE ) != SUCCESSFUL_RETURN )
01754                                 return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
01755 
01756                         y[y_min_number] = 0.0;
01757                 }
01758                 else
01759                 {
01760                         #ifdef PC_DEBUG
01761                         sprintf( messageString,"constraint no. %d.",y_min_number );
01762                         getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
01763                         #endif
01764 
01765                         if ( removeConstraint( y_min_number,BT_TRUE ) != SUCCESSFUL_RETURN )
01766                                 return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
01767 
01768                         y[nV+y_min_number] = 0.0;
01769                 }
01770         }
01771         else
01772         {
01773                 /* no constraint/bound can be removed => QP is infeasible! */
01774                 infeasible = BT_TRUE;
01775 
01776                 return THROWERROR( RET_ENSURELI_FAILED_NOINDEX );
01777         }
01778 
01779         return getGlobalMessageHandler( )->throwInfo( RET_LI_RESOLVED,0,__FUNCTION__,__FILE__,__LINE__,VS_HIDDEN );
01780 }
01781 
01782 
01783 
01784 /*
01785  *      a d d B o u n d
01786  */
01787 returnValue QProblem::addBound( int number, SubjectToStatus B_status,
01788                                                                 BooleanType updateCholesky
01789                                                                 )
01790 {
01791         int i, j, ii;
01792 
01793         /* consistency checks */
01794         if ( bounds.getStatus( number ) != ST_INACTIVE )
01795                 return THROWERROR( RET_BOUND_ALREADY_ACTIVE );
01796 
01797         if ( getNFR( ) == bounds.getNUV( ) )
01798                 return THROWERROR( RET_ALL_BOUNDS_ACTIVE );
01799 
01800         if ( ( getStatus( ) == QPS_NOTINITIALISED )    ||
01801                  ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
01802                  ( getStatus( ) == QPS_HOMOTOPYQPSOLVED )  ||
01803                  ( getStatus( ) == QPS_SOLVED )            )
01804         {
01805                 return THROWERROR( RET_UNKNOWN_BUG );
01806         }
01807 
01808 
01809         /* I) ENSURE LINEAR INDEPENDENCE OF THE WORKING SET,
01810          *    i.e. remove a constraint or bound if linear dependence occurs. */
01811         /* check for LI only if Cholesky decomposition shall be updated! */
01812         if ( updateCholesky == BT_TRUE )
01813         {
01814                 returnValue ensureLIreturnvalue = addBound_ensureLI( number,B_status );
01815 
01816                 switch ( ensureLIreturnvalue )
01817                 {
01818                         case SUCCESSFUL_RETURN:
01819                                 break;
01820 
01821                         case RET_LI_RESOLVED:
01822                                 break;
01823 
01824                         case RET_ENSURELI_FAILED_NOINDEX:
01825                                 return THROWERROR( RET_ADDBOUND_FAILED_INFEASIBILITY );
01826 
01827                         case RET_ENSURELI_FAILED_CYCLING:
01828                                 return THROWERROR( RET_ADDBOUND_FAILED_INFEASIBILITY );
01829 
01830                         default:
01831                                 return THROWERROR( RET_ENSURELI_FAILED );
01832                 }
01833         }
01834 
01835 
01836         /* some definitions */
01837         int nFR = getNFR( );
01838         int nAC = getNAC( );
01839         int nZ  = getNZ( );
01840 
01841         int tcol = sizeT - nAC;
01842 
01843 
01844         /* I) SWAP INDEXLIST OF FREE VARIABLES:
01845          *    move the variable to be fixed to the end of the list of free variables. */
01846         int lastfreenumber = bounds.getFree( )->getLastNumber( );
01847         if ( lastfreenumber != number )
01848                 if ( bounds.swapFree( number,lastfreenumber ) != SUCCESSFUL_RETURN )
01849                         THROWERROR( RET_ADDBOUND_FAILED );
01850 
01851 
01852         int FR_idx[NVMAX];
01853         if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
01854                 return THROWERROR( RET_ADDBOUND_FAILED );
01855 
01856         real_t w[NVMAX];
01857 
01858 
01859         /* II) ADD NEW ACTIVE BOUND TO TOP OF MATRIX T: */
01860         /* 1) add row [wZ wY] = [Z Y](number) at the top of T: assign w */
01861         for( i=0; i<nFR; ++i )
01862                 w[i] = Q[FR_idx[nFR-1]*NVMAX + i];
01863 
01864 
01865         /* 2) Use column-wise Givens rotations to restore reverse triangular form
01866          *    of the first row of T, simultanenous change of Q (i.e. Z) and R. */
01867         real_t c, s;
01868 
01869         for( j=0; j<nZ-1; ++j )
01870         {
01871                 computeGivens( w[j+1],w[j], w[j+1],w[j],c,s );
01872 
01873                 for( i=0; i<nFR; ++i )
01874                 {
01875                         ii = FR_idx[i];
01876                         applyGivens( c,s,Q[ii*NVMAX + 1+j],Q[ii*NVMAX + j], Q[ii*NVMAX + 1+j],Q[ii*NVMAX + j] );
01877                 }
01878 
01879                 if ( ( updateCholesky == BT_TRUE ) && ( hessianType != HST_IDENTITY ) )
01880                 {
01881                         for( i=0; i<=j+1; ++i )
01882                                 applyGivens( c,s,R[i*NVMAX + 1+j],R[i*NVMAX + j], R[i*NVMAX + 1+j],R[i*NVMAX + j] );
01883                 }
01884         }
01885 
01886 
01887         if ( nAC > 0 )    /* ( nAC == 0 ) <=> ( nZ == nFR ) <=> Y and T are empty => nothing to do */
01888         {
01889                 /* store new column a in a temporary vector instead of shifting T one column to the left */
01890                 real_t tmp[NCMAX_ALLOC];
01891                 for( i=0; i<nAC; ++i )
01892                         tmp[i] = 0.0;
01893 
01894                 {
01895                         j = nZ-1;
01896 
01897                         computeGivens( w[j+1],w[j], w[j+1],w[j],c,s );
01898 
01899                         for( i=0; i<nFR; ++i )
01900                         {
01901                                 ii = FR_idx[i];
01902                                 applyGivens( c,s,Q[ii*NVMAX + 1+j],Q[ii*NVMAX + j], Q[ii*NVMAX + 1+j],Q[ii*NVMAX + j] );
01903                         }
01904 
01905                         applyGivens( c,s,T[(nAC-1)*NVMAX + tcol],tmp[nAC-1], tmp[nAC-1],T[(nAC-1)*NVMAX + tcol] );
01906                 }
01907 
01908                 for( j=nZ; j<nFR-1; ++j )
01909                 {
01910                         computeGivens( w[j+1],w[j], w[j+1],w[j],c,s );
01911 
01912                         for( i=0; i<nFR; ++i )
01913                         {
01914                                 ii = FR_idx[i];
01915                                 applyGivens( c,s,Q[ii*NVMAX + 1+j],Q[ii*NVMAX + j], Q[ii*NVMAX + 1+j],Q[ii*NVMAX + j] );
01916                         }
01917 
01918                         for( i=(nFR-2-j); i<nAC; ++i )
01919                                 applyGivens( c,s,T[i*NVMAX + 1+tcol-nZ+j],tmp[i], tmp[i],T[i*NVMAX + 1+tcol-nZ+j] );
01920                 }
01921 
01922         }
01923 
01924 
01925         if ( ( updateCholesky == BT_TRUE ) && ( hessianType != HST_IDENTITY ) )
01926         {
01927                 /* III) RESTORE TRIANGULAR FORM OF R:
01928                  *      use row-wise Givens rotations to restore upper triangular form of R */
01929                 for( i=0; i<nZ-1; ++i )
01930                 {
01931                         computeGivens( R[i*NVMAX + i],R[(1+i)*NVMAX + i], R[i*NVMAX + i],R[(1+i)*NVMAX + i],c,s );
01932 
01933                         for( j=(1+i); j<nZ-1; ++j ) /* last column of R is thrown away */
01934                                 applyGivens( c,s,R[i*NVMAX + j],R[(1+i)*NVMAX + j], R[i*NVMAX + j],R[(1+i)*NVMAX + j] );
01935                 }
01936                 /* last column of R is thrown away */
01937                 for( i=0; i<nZ; ++i )
01938                         R[i*NVMAX + nZ-1] = 0.0;
01939         }
01940 
01941 
01942         /* IV) UPDATE INDICES */
01943         if ( bounds.moveFreeToFixed( number,B_status ) != SUCCESSFUL_RETURN )
01944                 return THROWERROR( RET_ADDBOUND_FAILED );
01945 
01946         return SUCCESSFUL_RETURN;
01947 }
01948 
01949 
01950 /*
01951  *      a d d B o u n d _ c h e c k L I
01952  */
01953 returnValue QProblem::addBound_checkLI( int number )
01954 {
01955         int i;
01956 
01957         /* some definitions */
01958         int nZ  = getNZ( );
01959 
01960         /* Check if constraint <number> is linearly independent from the
01961            the active ones (<=> is element of null space of Afr). */
01962         for( i=0; i<nZ; ++i )
01963         {
01964                 if ( getAbs( Q[number*NVMAX + i] ) > EPS )
01965                         return RET_LINEARLY_INDEPENDENT;
01966         }
01967 
01968         return RET_LINEARLY_DEPENDENT;
01969 }
01970 
01971 
01972 /*
01973  *      a d d B o u n d _ e n s u r e L I
01974  */
01975 returnValue QProblem::addBound_ensureLI( int number, SubjectToStatus B_status )
01976 {
01977         int i, j, ii, jj;
01978         int nV  = getNV( );
01979         int nFX = getNFX( );
01980         int nAC = getNAC( );
01981         int nZ  = getNZ( );
01982 
01983 
01984         /* I) Check if new constraint is linearly independent from the active ones. */
01985         returnValue returnvalueCheckLI = addBound_checkLI( number );
01986 
01987         if ( returnvalueCheckLI == RET_LINEARLY_INDEPENDENT )
01988                 return SUCCESSFUL_RETURN;
01989 
01990 
01991         /* II) NEW BOUND IS LINEARLY DEPENDENT: */
01992         /* 1) Determine coefficients of linear combination,
01993          *    cf. M.J. Best. Applied Mathematics and Parallel Computing, chapter:
01994          *    An Algorithm for the Solution of the Parametric Quadratic Programming
01995          *    Problem, pages 57-76. Physica-Verlag, Heidelberg, 1996. */
01996         int FR_idx[NVMAX];
01997         if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
01998                 return THROWERROR( RET_ENSURELI_FAILED );
01999 
02000         int FX_idx[NVMAX];
02001         if ( bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
02002                 return THROWERROR( RET_ENSURELI_FAILED );
02003 
02004         int AC_idx[NCMAX_ALLOC];
02005         if ( constraints.getActive( )->getNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
02006                 return THROWERROR( RET_ENSURELI_FAILED );
02007 
02008         real_t xiC[NCMAX_ALLOC];
02009         real_t xiC_TMP[NCMAX_ALLOC];
02010         real_t xiB[NVMAX];
02011 
02012         /* 2) Calculate xiC. */
02013         if ( nAC > 0 )
02014         {
02015                 if ( B_status == ST_LOWER )
02016                 {
02017                         for( i=0; i<nAC; ++i )
02018                                 xiC_TMP[i] = Q[number*NVMAX + nZ+i];
02019                 }
02020                 else
02021                 {
02022                         for( i=0; i<nAC; ++i )
02023                                 xiC_TMP[i] = -Q[number*NVMAX + nZ+i];
02024                 }
02025 
02026                 if ( backsolveT( xiC_TMP, BT_TRUE, xiC ) != SUCCESSFUL_RETURN )
02027                         return THROWERROR( RET_ENSURELI_FAILED_TQ );
02028         }
02029 
02030         /* 3) Calculate xiB. */
02031         for( i=0; i<nFX; ++i )
02032         {
02033                 ii = FX_idx[i];
02034 
02035                 xiB[i] = 0.0;
02036                 for( j=0; j<nAC; ++j )
02037                 {
02038                         jj = AC_idx[j];
02039                         xiB[i] -= A[jj*NVMAX + ii] * xiC[j];
02040                 }
02041         }
02042 
02043 
02044         /* III) DETERMINE CONSTRAINT/BOUND TO BE REMOVED. */
02045         real_t y_min = INFTY * INFTY;
02046         int y_min_number = -1;
02047         BooleanType y_min_isBound = BT_FALSE;
02048 
02049         /* 1) Constraints. */
02050         for( i=0; i<nAC; ++i )
02051         {
02052                 ii = AC_idx[i];
02053 
02054                 if ( constraints.getStatus( ii ) == ST_LOWER )
02055                 {
02056                         if ( ( xiC[i] > ZERO ) && ( y[nV+ii] >= 0.0 ) )
02057                         {
02058                                 if ( y[nV+ii]/xiC[i] < y_min )
02059                                 {
02060                                         y_min = y[nV+ii]/xiC[i];
02061                                         y_min_number = ii;
02062                                 }
02063                         }
02064                 }
02065                 else
02066                 {
02067                         if ( ( xiC[i] < -ZERO ) && ( y[nV+ii] <= 0.0 ) )
02068                         {
02069                                 if ( y[nV+ii]/xiC[i] < y_min )
02070                                 {
02071                                         y_min = y[nV+ii]/xiC[i];
02072                                         y_min_number = ii;
02073                                 }
02074                         }
02075                 }
02076         }
02077 
02078         /* 2) Bounds. */
02079         for( i=0; i<nFX; ++i )
02080         {
02081                 ii = FX_idx[i];
02082 
02083                 if ( bounds.getStatus( ii ) == ST_LOWER )
02084                 {
02085                         if ( ( xiB[i] > ZERO ) && ( y[ii] >= 0.0 ) )
02086                         {
02087                                 if ( y[ii]/xiB[i] < y_min )
02088                                 {
02089                                         y_min = y[ii]/xiB[i];
02090                                         y_min_number = ii;
02091                                         y_min_isBound = BT_TRUE;
02092                                 }
02093                         }
02094                 }
02095                 else
02096                 {
02097                         if ( ( xiB[i] < -ZERO ) && ( y[ii] <= 0.0 ) )
02098                         {
02099                                 if ( y[ii]/xiB[i] < y_min )
02100                                 {
02101                                         y_min = y[ii]/xiB[i];
02102                                         y_min_number = ii;
02103                                         y_min_isBound = BT_TRUE;
02104                                 }
02105                         }
02106                 }
02107         }
02108 
02109         /* setup output preferences */
02110         #ifdef PC_DEBUG
02111         char messageString[80];
02112         VisibilityStatus visibilityStatus;
02113 
02114         if ( printlevel == PL_HIGH )
02115                 visibilityStatus = VS_VISIBLE;
02116         else
02117                 visibilityStatus = VS_HIDDEN;
02118         #endif
02119 
02120 
02121         /* IV) REMOVE CONSTRAINT/BOUND FOR RESOLVING LINEAR DEPENDENCE: */
02122         if ( y_min_number >= 0 )
02123         {
02124                 /* 1) Check for cycling due to infeasibility. */
02125                 if ( ( cyclingManager.getCyclingStatus( number,BT_TRUE ) == CYC_PREV_REMOVED ) &&
02126                          ( cyclingManager.getCyclingStatus( y_min_number,y_min_isBound ) == CYC_PREV_ADDED ) )
02127                 {
02128                         infeasible = BT_TRUE;
02129 
02130                         return THROWERROR( RET_ENSURELI_FAILED_CYCLING );
02131                 }
02132                 else
02133                 {
02134                         /* set cycling data */
02135                         cyclingManager.clearCyclingData( );
02136                         cyclingManager.setCyclingStatus( number,BT_TRUE, CYC_PREV_ADDED );
02137                         cyclingManager.setCyclingStatus( y_min_number,y_min_isBound, CYC_PREV_REMOVED );
02138                 }
02139 
02140 
02141                 /* 2) Update Lagrange multiplier... */
02142                 for( i=0; i<nAC; ++i )
02143                 {
02144                         ii = AC_idx[i];
02145                         y[nV+ii] -= y_min * xiC[i];
02146                 }
02147                 for( i=0; i<nFX; ++i )
02148                 {
02149                         ii = FX_idx[i];
02150                         y[ii] -= y_min * xiB[i];
02151                 }
02152 
02153                 /* ... also for newly active bound ... */
02154                 if ( B_status == ST_LOWER )
02155                         y[number] = y_min;
02156                 else
02157                         y[number] = -y_min;
02158 
02159                 /* ... and for bound to be removed. */
02160                 if ( y_min_isBound == BT_TRUE )
02161                 {
02162                         #ifdef PC_DEBUG
02163                         sprintf( messageString,"bound no. %d.",y_min_number );
02164                         getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
02165                         #endif
02166 
02167                         if ( removeBound( y_min_number,BT_TRUE ) != SUCCESSFUL_RETURN )
02168                                 return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
02169 
02170                         y[y_min_number] = 0.0;
02171                 }
02172                 else
02173                 {
02174                         #ifdef PC_DEBUG
02175                         sprintf( messageString,"constraint no. %d.",y_min_number );
02176                         getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
02177                         #endif
02178 
02179                         if ( removeConstraint( y_min_number,BT_TRUE ) != SUCCESSFUL_RETURN )
02180                                 return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
02181 
02182                         y[nV+y_min_number] = 0.0;
02183                 }
02184         }
02185         else
02186         {
02187                 /* no constraint/bound can be removed => QP is infeasible! */
02188                 infeasible = BT_TRUE;
02189 
02190                 return THROWERROR( RET_ENSURELI_FAILED_NOINDEX );
02191         }
02192 
02193         return getGlobalMessageHandler( )->throwInfo( RET_LI_RESOLVED,0,__FUNCTION__,__FILE__,__LINE__,VS_HIDDEN );
02194 }
02195 
02196 
02197 
02198 /*
02199  *      r e m o v e C o n s t r a i n t
02200  */
02201 returnValue QProblem::removeConstraint( int number,
02202                                                                                 BooleanType updateCholesky
02203                                                                                 )
02204 {
02205         int i, j, ii, jj;
02206 
02207         /* consistency check */
02208         if ( ( getStatus( ) == QPS_NOTINITIALISED )    ||
02209                  ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
02210                  ( getStatus( ) == QPS_HOMOTOPYQPSOLVED )  ||
02211                  ( getStatus( ) == QPS_SOLVED )            )
02212         {
02213                 return THROWERROR( RET_UNKNOWN_BUG );
02214         }
02215 
02216         /* some definitions */
02217         int nFR = getNFR( );
02218         int nAC = getNAC( );
02219         int nZ  = getNZ( );
02220 
02221         int tcol = sizeT - nAC;
02222         int number_idx = constraints.getActive( )->getIndex( number );
02223 
02224 
02225         /* consistency checks */
02226         if ( constraints.getStatus( number ) == ST_INACTIVE )
02227                 return THROWERROR( RET_CONSTRAINT_NOT_ACTIVE );
02228 
02229         if ( ( number_idx < 0 ) || ( number_idx >= nAC ) )
02230                 return THROWERROR( RET_CONSTRAINT_NOT_ACTIVE );
02231 
02232 
02233         int FR_idx[NVMAX];
02234         if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
02235                 return THROWERROR( RET_REMOVECONSTRAINT_FAILED );
02236 
02237 
02238         /* I) REMOVE <number>th ROW FROM T,
02239          *    i.e. shift rows number+1 through nAC  upwards (instead of the actual
02240          *    constraint number its corresponding index within matrix A is used). */
02241         if ( number_idx < nAC-1 )
02242         {
02243                 for( i=(number_idx+1); i<nAC; ++i )
02244                         for( j=(nAC-i-1); j<nAC; ++j )
02245                                 T[(i-1)*NVMAX + tcol+j] = T[i*NVMAX + tcol+j];
02246                 /* gimmick: write zeros into the last row of T */
02247                 for( j=0; j<nAC; ++j )
02248                         T[(nAC-1)*NVMAX + tcol+j] = 0.0;
02249 
02250 
02251                 /* II) RESTORE TRIANGULAR FORM OF T,
02252                  *     use column-wise Givens rotations to restore reverse triangular form
02253                  *     of T simultanenous change of Q (i.e. Y). */
02254                 real_t c, s;
02255 
02256                 for( j=(nAC-2-number_idx); j>=0; --j )
02257                 {
02258                         computeGivens( T[(nAC-2-j)*NVMAX + tcol+1+j],T[(nAC-2-j)*NVMAX + tcol+j], T[(nAC-2-j)*NVMAX + tcol+1+j],T[(nAC-2-j)*NVMAX + tcol+j],c,s );
02259 
02260                         for( i=(nAC-j-1); i<(nAC-1); ++i )
02261                                 applyGivens( c,s,T[i*NVMAX + tcol+1+j],T[i*NVMAX + tcol+j], T[i*NVMAX + tcol+1+j],T[i*NVMAX + tcol+j] );
02262 
02263                         for( i=0; i<nFR; ++i )
02264                         {
02265                                 ii = FR_idx[i];
02266                                 applyGivens( c,s,Q[ii*NVMAX + nZ+1+j],Q[ii*NVMAX + nZ+j], Q[ii*NVMAX + nZ+1+j],Q[ii*NVMAX + nZ+j] );
02267                         }
02268                 }
02269         }
02270         else
02271         {
02272                 /* gimmick: write zeros into the last row of T */
02273                 for( j=0; j<nAC; ++j )
02274                         T[(nAC-1)*NVMAX + tcol+j] = 0.0;
02275         }
02276 
02277 
02278         if ( ( updateCholesky == BT_TRUE ) && ( hessianType != HST_IDENTITY ) )
02279         {
02280                 /* III) UPDATE CHOLESKY DECOMPOSITION,
02281                  *      calculate new additional column (i.e. [r sqrt(rho2)]')
02282                  *      of the Cholesky factor R. */
02283                 real_t Hz[NVMAX];
02284                 for ( i=0; i<nFR; ++i )
02285                         Hz[i] = 0.0;
02286                 real_t rho2 = 0.0;
02287 
02288                 /* 1) Calculate Hz = H*z, where z is the new rightmost column of Z
02289                  *    (i.e. the old leftmost column of Y).  */
02290                 for( j=0; j<nFR; ++j )
02291                 {
02292                         jj = FR_idx[j];
02293                         for( i=0; i<nFR; ++i )
02294                                 Hz[i] += H[jj*NVMAX + FR_idx[i]] * Q[jj*NVMAX + nZ];
02295                 }
02296 
02297                 if ( nZ > 0 )
02298                 {
02299                         real_t ZHz[NVMAX];
02300                         for ( i=0; i<nZ; ++i )
02301                                 ZHz[i] = 0.0;
02302                         real_t r[NVMAX];
02303 
02304                         /* 2) Calculate ZHz = Z'*Hz (old Z). */
02305                         for( j=0; j<nFR; ++j )
02306                         {
02307                                 jj = FR_idx[j];
02308 
02309                                 for( i=0; i<nZ; ++i )
02310                                         ZHz[i] += Q[jj*NVMAX + i] * Hz[j];
02311                         }
02312 
02313                         /* 3) Calculate r = R^-T * ZHz. */
02314                         if ( backsolveR( ZHz,BT_TRUE,r ) != SUCCESSFUL_RETURN )
02315                                 return THROWERROR( RET_REMOVECONSTRAINT_FAILED );
02316 
02317                         /* 4) Calculate rho2 = rho^2 = z'*Hz - r'*r
02318                          *    and store r into R. */
02319                         for( i=0; i<nZ; ++i )
02320                         {
02321                                 rho2 -= r[i]*r[i];
02322                                 R[i*NVMAX + nZ] = r[i];
02323                         }
02324                 }
02325 
02326                 for( j=0; j<nFR; ++j )
02327                         rho2 += Q[FR_idx[j]*NVMAX + nZ] * Hz[j];
02328 
02329                 /* 5) Store rho into R. */
02330                 if ( rho2 > 0.0 )
02331                         R[nZ*NVMAX + nZ] = sqrt( rho2 );
02332                 else
02333                 {
02334                         hessianType = HST_SEMIDEF;
02335                         return THROWERROR( RET_HESSIAN_NOT_SPD );
02336                 }
02337         }
02338 
02339         /* IV) UPDATE INDICES */
02340         if ( constraints.moveActiveToInactive( number ) != SUCCESSFUL_RETURN )
02341                 return THROWERROR( RET_REMOVECONSTRAINT_FAILED );
02342 
02343 
02344         return SUCCESSFUL_RETURN;
02345 }
02346 
02347 
02348 /*
02349  *      r e m o v e B o u n d
02350  */
02351 returnValue QProblem::removeBound(      int number,
02352                                                                         BooleanType updateCholesky
02353                                                                         )
02354 {
02355         int i, j, ii, jj;
02356 
02357         /* consistency checks */
02358         if ( bounds.getStatus( number ) == ST_INACTIVE )
02359                 return THROWERROR( RET_BOUND_NOT_ACTIVE );
02360 
02361         if ( ( getStatus( ) == QPS_NOTINITIALISED )    ||
02362                  ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
02363                  ( getStatus( ) == QPS_HOMOTOPYQPSOLVED )  ||
02364                  ( getStatus( ) == QPS_SOLVED )            )
02365         {
02366                 return THROWERROR( RET_UNKNOWN_BUG );
02367         }
02368 
02369         /* some definitions */
02370         int nFR = getNFR( );
02371         int nAC = getNAC( );
02372         int nZ  = getNZ( );
02373 
02374         int tcol = sizeT - nAC;
02375 
02376 
02377         /* I) UPDATE INDICES */
02378         if ( bounds.moveFixedToFree( number ) != SUCCESSFUL_RETURN )
02379                 return THROWERROR( RET_REMOVEBOUND_FAILED );
02380 
02381 
02382         int FR_idx[NVMAX];
02383         if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
02384                 return THROWERROR( RET_REMOVEBOUND_FAILED );
02385 
02386         /* I) APPEND <nFR+1>th UNITY VECOTR TO Q. */
02387         int nnFRp1 = FR_idx[nFR];
02388         for( i=0; i<nFR; ++i )
02389         {
02390                 ii = FR_idx[i];
02391                 Q[ii*NVMAX + nFR] = 0.0;
02392                 Q[nnFRp1*NVMAX + i] = 0.0;
02393         }
02394         Q[nnFRp1*NVMAX + nFR] = 1.0;
02395 
02396         if ( nAC > 0 )
02397         {
02398                 /* store new column a in a temporary vector instead of shifting T one column to the left and appending a */
02399                 int AC_idx[NCMAX_ALLOC];
02400                 if ( constraints.getActive( )->getNumberArray( AC_idx ) != SUCCESSFUL_RETURN )
02401                         return THROWERROR( RET_REMOVEBOUND_FAILED );
02402 
02403                 real_t tmp[NCMAX_ALLOC];
02404                 for( i=0; i<nAC; ++i )
02405                 {
02406                         ii = AC_idx[i];
02407                         tmp[i] =  A[ii*NVMAX + number];
02408                 }
02409 
02410 
02411                 /* II) RESTORE TRIANGULAR FORM OF T,
02412                  *     use column-wise Givens rotations to restore reverse triangular form
02413                  *     of T = [T A(:,number)], simultanenous change of Q (i.e. Y and Z). */
02414                 real_t c, s;
02415 
02416                 for( j=(nAC-1); j>=0; --j )
02417                 {
02418                         computeGivens( tmp[nAC-1-j],T[(nAC-1-j)*NVMAX + tcol+j],T[(nAC-1-j)*NVMAX + tcol+j],tmp[nAC-1-j],c,s );
02419 
02420                         for( i=(nAC-j); i<nAC; ++i )
02421                                 applyGivens( c,s,tmp[i],T[i*NVMAX + tcol+j],T[i*NVMAX + tcol+j],tmp[i] );
02422 
02423                         for( i=0; i<=nFR; ++i )
02424                         {
02425                                 ii = FR_idx[i];
02426                                 /* nZ+1+nAC = nFR+1  /  nZ+(1) = nZ+1 */
02427                                 applyGivens( c,s,Q[ii*NVMAX + nZ+1+j],Q[ii*NVMAX + nZ+j],Q[ii*NVMAX + nZ+1+j],Q[ii*NVMAX + nZ+j] );
02428                         }
02429                 }
02430         }
02431 
02432 
02433         if ( ( updateCholesky == BT_TRUE ) && ( hessianType != HST_IDENTITY ) )
02434         {
02435                 /* III) UPDATE CHOLESKY DECOMPOSITION,
02436                  *      calculate new additional column (i.e. [r sqrt(rho2)]')
02437                  *      of the Cholesky factor R: */
02438                 real_t z2 = Q[nnFRp1*NVMAX + nZ];
02439                 real_t rho2 = H[nnFRp1*NVMAX + nnFRp1]*z2*z2; /* rho2 = h2*z2*z2 */
02440 
02441                 if ( nFR > 0 )
02442                 {
02443                         real_t Hz[NVMAX];
02444                         for( i=0; i<nFR; ++i )
02445                                 Hz[i] = 0.0;
02446                         /* 1) Calculate R'*r = Zfr'*Hfr*z1 + z2*Zfr'*h1 =: Zfr'*Hz + z2*Zfr'*h1 =: rhs and
02447                          *    rho2 = z1'*Hfr*z1 + 2*z2*h1'*z1 + h2*z2^2 - r'*r =: z1'*Hz + 2*z2*h1'*z1 + h2*z2^2 - r'r */
02448                         for( j=0; j<nFR; ++j )
02449                         {
02450                                 jj = FR_idx[j];
02451                                 for( i=0; i<nFR; ++i )
02452                                 {
02453                                         ii = FR_idx[i];
02454                                         /*                         H * z1 */
02455                                         Hz[i] += H[jj*NVMAX + ii] * Q[jj*NVMAX + nZ];
02456                                 }
02457                         }
02458 
02459                         if ( nZ > 0 )
02460                         {
02461                                 real_t r[NVMAX];
02462                                 real_t rhs[NVMAX];
02463                                 for( i=0; i<nZ; ++i )
02464                                         rhs[i] = 0.0;
02465 
02466                                 /* 2) Calculate rhs. */
02467                                 for( j=0; j<nFR; ++j )
02468                                 {
02469                                         jj = FR_idx[j];
02470                                         for( i=0; i<nZ; ++i )
02471                                                                                 /* Zfr' * ( Hz + z2*h1 ) */
02472                                                 rhs[i] += Q[jj*NVMAX + i] * ( Hz[j] + z2 * H[nnFRp1*NVMAX + jj] );
02473                                 }
02474 
02475                                 /* 3) Calculate r = R^-T * rhs. */
02476                                 if ( backsolveR( rhs,BT_TRUE,BT_TRUE,r ) != SUCCESSFUL_RETURN )
02477                                         return THROWERROR( RET_REMOVEBOUND_FAILED );
02478 
02479                                 /* 4) Calculate rho2 = rho^2 = z'*Hz - r'*r
02480                                  *    and store r into R. */
02481                                 for( i=0; i<nZ; ++i )
02482                                 {
02483                                         rho2 -= r[i]*r[i];
02484                                         R[i*NVMAX + nZ] = r[i];
02485                                 }
02486                         }
02487 
02488                         for( j=0; j<nFR; ++j )
02489                         {
02490                                 jj = FR_idx[j];
02491                                                         /* z1' * ( Hz + 2*z2*h1 ) */
02492                                 rho2 += Q[jj*NVMAX + nZ] * ( Hz[j] + 2.0*z2*H[nnFRp1*NVMAX + jj] );
02493                         }
02494                 }
02495 
02496 
02497                 /* 5) Store rho into R. */
02498                 if ( rho2 > 0.0 )
02499                         R[nZ*NVMAX + nZ] = sqrt( rho2 );
02500                 else
02501                 {
02502                         hessianType = HST_SEMIDEF;
02503                         return THROWERROR( RET_HESSIAN_NOT_SPD );
02504                 }
02505         }
02506 
02507         return SUCCESSFUL_RETURN;
02508 }
02509 
02510 
02511 /*
02512  *      b a c k s o l v e R  (CODE DUPLICATE OF QProblemB CLASS!!!)
02513  */
02514 returnValue QProblem::backsolveR(       const real_t* const b, BooleanType transposed,
02515                                                                         real_t* const a
02516                                                                         )
02517 {
02518         /* Call standard backsolve procedure (i.e. removingBound == BT_FALSE). */
02519         return backsolveR( b,transposed,BT_FALSE,a );
02520 }
02521 
02522 
02523 /*
02524  *      b a c k s o l v e R  (CODE DUPLICATE OF QProblemB CLASS!!!)
02525  */
02526 returnValue QProblem::backsolveR(       const real_t* const b, BooleanType transposed,
02527                                                                         BooleanType removingBound,
02528                                                                         real_t* const a
02529                                                                         )
02530 {
02531         int i, j;
02532         int nR = getNZ( );
02533 
02534         real_t sum;
02535 
02536         /* if backsolve is called while removing a bound, reduce nZ by one. */
02537         if ( removingBound == BT_TRUE )
02538                 --nR;
02539 
02540         /* nothing to do */
02541         if ( nR <= 0 )
02542                 return SUCCESSFUL_RETURN;
02543 
02544 
02545         /* Solve Ra = b, where R might be transposed. */
02546         if ( transposed == BT_FALSE )
02547         {
02548                 /* solve Ra = b */
02549                 for( i=(nR-1); i>=0; --i )
02550                 {
02551                         sum = b[i];
02552                         for( j=(i+1); j<nR; ++j )
02553                                 sum -= R[i*NVMAX + j] * a[j];
02554 
02555                         if ( getAbs( R[i*NVMAX + i] ) > ZERO )
02556                                 a[i] = sum / R[i*NVMAX + i];
02557                         else
02558                                 return THROWERROR( RET_DIV_BY_ZERO );
02559                 }
02560         }
02561         else
02562         {
02563                 /* solve R^T*a = b */
02564                 for( i=0; i<nR; ++i )
02565                 {
02566                         sum = b[i];
02567 
02568                         for( j=0; j<i; ++j )
02569                                 sum -= R[j*NVMAX + i] * a[j];
02570 
02571                         if ( getAbs( R[i*NVMAX + i] ) > ZERO )
02572                                 a[i] = sum / R[i*NVMAX + i];
02573                         else
02574                                 return THROWERROR( RET_DIV_BY_ZERO );
02575                 }
02576         }
02577 
02578         return SUCCESSFUL_RETURN;
02579 }
02580 
02581 
02582 
02583 /*
02584  *      b a c k s o l v e T
02585  */
02586 returnValue QProblem::backsolveT( const real_t* const b, BooleanType transposed, real_t* const a )
02587 {
02588         int i, j;
02589         int nT = getNAC( );
02590         int tcol = sizeT - nT;
02591 
02592         real_t sum;
02593 
02594         /* nothing to do */
02595         if ( nT <= 0 )
02596                 return SUCCESSFUL_RETURN;
02597 
02598 
02599         /* Solve Ta = b, where T might be transposed. */
02600         if ( transposed == BT_FALSE )
02601         {
02602                 /* solve Ta = b */
02603                 for( i=0; i<nT; ++i )
02604                 {
02605                         sum = b[i];
02606                         for( j=0; j<i; ++j )
02607                                 sum -= T[i*NVMAX + sizeT-1-j] * a[nT-1-j];
02608 
02609                         if ( getAbs( T[i*NVMAX + sizeT-1-i] ) > ZERO )
02610                                 a[nT-1-i] = sum / T[i*NVMAX + sizeT-1-i];
02611                         else
02612                                 return THROWERROR( RET_DIV_BY_ZERO );
02613                 }
02614         }
02615         else
02616         {
02617                 /* solve T^T*a = b */
02618                 for( i=0; i<nT; ++i )
02619                 {
02620                         sum = b[i];
02621                         for( j=0; j<i; ++j )
02622                                 sum -= T[(nT-1-j)*NVMAX + tcol+i] * a[nT-1-j];
02623 
02624                         if ( getAbs( T[(nT-1-i)*NVMAX + tcol+i] ) > ZERO )
02625                                 a[nT-1-i] = sum / T[(nT-1-i)*NVMAX + tcol+i];
02626                         else
02627                                 return THROWERROR( RET_DIV_BY_ZERO );
02628                 }
02629         }
02630 
02631 
02632         return SUCCESSFUL_RETURN;
02633 }
02634 
02635 
02636 /*
02637  *      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
02638  */
02639 returnValue QProblem::hotstart_determineDataShift(  const int* const FX_idx, const int* const AC_idx,
02640                                                                                                         const real_t* const g_new, const real_t* const lbA_new, const real_t* const ubA_new,
02641                                                                                                         const real_t* const lb_new, const real_t* const ub_new,
02642                                                                                                         real_t* const delta_g, real_t* const delta_lbA, real_t* const delta_ubA,
02643                                                                                                         real_t* const delta_lb, real_t* const delta_ub,
02644                                                                                                         BooleanType& Delta_bC_isZero, BooleanType& Delta_bB_isZero
02645                                                                                                         )
02646 {
02647         int i, ii;
02648         int nC  = getNC( );
02649         int nAC = getNAC( );
02650 
02651 
02652         /* I) DETERMINE DATA SHIFT FOR BOUNDS */
02653         QProblemB::hotstart_determineDataShift( FX_idx,g_new,lb_new,ub_new, delta_g,delta_lb,delta_ub, Delta_bB_isZero );
02654 
02655 
02656         /* II) DETERMINE DATA SHIFT FOR CONSTRAINTS */
02657         /* 1) Calculate shift directions. */
02658         for( i=0; i<nC; ++i )
02659         {
02660                 /* if lower constraints' bounds do not exist, shift them to -infinity */
02661                 if ( lbA_new != 0 )
02662                         delta_lbA[i] = lbA_new[i] - lbA[i];
02663                 else
02664                         delta_lbA[i] = -INFTY - lbA[i];
02665         }
02666 
02667         for( i=0; i<nC; ++i )
02668         {
02669                 /* if upper constraints' bounds do not exist, shift them to infinity */
02670                 if ( ubA_new != 0 )
02671                         delta_ubA[i] = ubA_new[i] - ubA[i];
02672                 else
02673                         delta_ubA[i] = INFTY - ubA[i];
02674         }
02675 
02676         /* 2) Determine if active constraints' bounds are to be shifted. */
02677         Delta_bC_isZero = BT_TRUE;
02678 
02679         for ( i=0; i<nAC; ++i )
02680         {
02681                 ii = AC_idx[i];
02682 
02683                 if ( ( getAbs( delta_lbA[ii] ) > EPS ) || ( getAbs( delta_ubA[ii] ) > EPS ) )
02684                 {
02685                         Delta_bC_isZero = BT_FALSE;
02686                         break;
02687                 }
02688         }
02689 
02690         return SUCCESSFUL_RETURN;
02691 }
02692 
02693 
02694 /*
02695  *      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
02696  */
02697 returnValue QProblem::hotstart_determineStepDirection(  const int* const FR_idx, const int* const FX_idx, const int* const AC_idx,
02698                                                                                                                 const real_t* const delta_g, const real_t* const delta_lbA, const real_t* const delta_ubA,
02699                                                                                                                 const real_t* const delta_lb, const real_t* const delta_ub,
02700                                                                                                                 BooleanType Delta_bC_isZero, BooleanType Delta_bB_isZero,
02701                                                                                                                 real_t* const delta_xFX, real_t* const delta_xFR,
02702                                                                                                                 real_t* const delta_yAC, real_t* const delta_yFX
02703                                                                                                                 )
02704 {
02705         int i, j, ii, jj;
02706         int nFR = getNFR( );
02707         int nFX = getNFX( );
02708         int nAC = getNAC( );
02709         int nZ  = getNZ( );
02710 
02711         /* initialise auxiliary vectors */
02712         real_t HMX_delta_xFX[NVMAX];
02713         real_t YFR_delta_xFRy[NVMAX];
02714         real_t ZFR_delta_xFRz[NVMAX];
02715         real_t HFR_YFR_delta_xFRy[NVMAX];
02716         for( i=0; i<nFR; ++i )
02717         {
02718                 delta_xFR[i] = 0.0;
02719                 HMX_delta_xFX[i] = 0.0;
02720                 YFR_delta_xFRy[i] = 0.0;
02721                 ZFR_delta_xFRz[i] = 0.0;
02722                 HFR_YFR_delta_xFRy[i] = 0.0;
02723         }
02724 
02725         real_t delta_xFRy[NCMAX_ALLOC];
02726         real_t delta_xFRz[NVMAX];
02727         for( i=0; i<nZ; ++i )
02728                 delta_xFRz[i] = 0.0;
02729 
02730 
02731         /* I) DETERMINE delta_xFX */
02732         if ( nFX > 0 )
02733         {
02734                 for( i=0; i<nFX; ++i )
02735                 {
02736                         ii = FX_idx[i];
02737 
02738                         if ( bounds.getStatus( ii ) == ST_LOWER )
02739                                 delta_xFX[i] = delta_lb[ii];
02740                         else
02741                                 delta_xFX[i] = delta_ub[ii];
02742                 }
02743         }
02744 
02745         /* II) DETERMINE delta_xFR */
02746         if ( nFR > 0 )
02747         {
02748                 /* 1) Determine delta_xFRy. */
02749                 if ( nAC > 0 )
02750                 {
02751                         if ( ( Delta_bC_isZero == BT_TRUE ) && ( Delta_bB_isZero == BT_TRUE ) )
02752                         {
02753                                 for( i=0; i<nAC; ++i )
02754                                         delta_xFRy[i] = 0.0;
02755 
02756                                 for( i=0; i<nFR; ++i )
02757                                         delta_xFR[i] = 0.0;
02758                         }
02759                         else
02760                         {
02761                                 /* auxillary variable */
02762                                 real_t delta_xFRy_TMP[NCMAX_ALLOC];
02763 
02764                                 for( i=0; i<nAC; ++i )
02765                                 {
02766                                         ii = AC_idx[i];
02767 
02768                                         if ( constraints.getStatus( ii ) == ST_LOWER )
02769                                                 delta_xFRy_TMP[i] = delta_lbA[ii];
02770                                         else
02771                                                 delta_xFRy_TMP[i] = delta_ubA[ii];
02772 
02773                                         if ( Delta_bB_isZero == BT_FALSE )
02774                                         {
02775                                                 for( j=0; j<nFX; ++j )
02776                                                 {
02777                                                         jj = FX_idx[j];
02778                                                         delta_xFRy_TMP[i] -= A[ii*NVMAX + jj] * delta_xFX[j];
02779                                                 }
02780                                         }
02781                                 }
02782 
02783                                 if ( backsolveT( delta_xFRy_TMP, BT_FALSE, delta_xFRy ) != SUCCESSFUL_RETURN )
02784                                         return THROWERROR( RET_STEPDIRECTION_FAILED_TQ );
02785 
02786                                 for( i=0; i<nFR; ++i )
02787                                 {
02788                                         ii = FR_idx[i];
02789                                         for( j=0; j<nAC; ++j )
02790                                                 YFR_delta_xFRy[i] += Q[ii*NVMAX + nZ+j] * delta_xFRy[j];
02791 
02792                                         /* delta_xFR = YFR*delta_xFRy (+ ZFR*delta_xFRz) */
02793                                         delta_xFR[i] = YFR_delta_xFRy[i];
02794                                 }
02795                         }
02796                 }
02797 
02798                 /* 2) Determine delta_xFRz. */
02799                 if ( hessianType == HST_IDENTITY )
02800                 {
02801                         for( j=0; j<nFR; ++j )
02802                         {
02803                                 jj = FR_idx[j];
02804                                 for( i=0; i<nZ; ++i )
02805                                         delta_xFRz[i] -= Q[jj*NVMAX + i] * delta_g[jj];
02806                         }
02807 
02808                         if ( nZ > 0 )
02809                         {
02810                                 for( i=0; i<nFR; ++i )
02811                                 {
02812                                         ii = FR_idx[i];
02813                                         for( j=0; j<nZ; ++j )
02814                                                 ZFR_delta_xFRz[i] += Q[ii*NVMAX + j] * delta_xFRz[j];
02815 
02816                                         delta_xFR[i] += ZFR_delta_xFRz[i];
02817                                 }
02818                         }
02819                 }
02820                 else
02821                 {
02822                         if ( Delta_bB_isZero == BT_FALSE )
02823                         {
02824                                 for( i=0; i<nFR; ++i )
02825                                 {
02826                                         ii = FR_idx[i];
02827                                         for( j=0; j<nFX; ++j )
02828                                         {
02829                                                 jj = FX_idx[j];
02830                                                 HMX_delta_xFX[i] += H[ii*NVMAX + jj] * delta_xFX[j];
02831                                         }
02832                                 }
02833                         }
02834 
02835                         if ( nAC > 0 )
02836                         {
02837                                 if ( ( Delta_bC_isZero == BT_FALSE ) || ( Delta_bB_isZero == BT_FALSE ) )
02838                                 {
02839                                         for( i=0; i<nFR; ++i )
02840                                         {
02841                                                 ii = FR_idx[i];
02842                                                 for( j=0; j<nFR; ++j )
02843                                                 {
02844                                                         jj = FR_idx[j];
02845                                                         HFR_YFR_delta_xFRy[i] += H[ii*NVMAX + jj] * YFR_delta_xFRy[j];
02846                                                 }
02847                                         }
02848                                 }
02849                         }
02850 
02851 
02852                         if ( nZ > 0 )
02853                         {
02854                                 /* auxiliary variable */
02855                                 real_t delta_xFRz_TMP[NVMAX];
02856                                 real_t delta_xFRz_RHS[NVMAX];
02857 
02858 
02859                                 if ( ( nAC > 0 ) && ( nFX > 0 ) && ( Delta_bB_isZero == BT_FALSE ) )
02860                                 {
02861                                         for( j=0; j<nFR; ++j )
02862                                         {
02863                                                 jj = FR_idx[j];
02864                                                 delta_xFRz_RHS[j] = delta_g[jj] + HFR_YFR_delta_xFRy[j] + HMX_delta_xFX[j];
02865                                         }
02866                                 }
02867                                 else
02868                                 {
02869                                         if ( ( nAC == 0 ) && ( Delta_bB_isZero == BT_TRUE ) )
02870                                         {
02871                                                 for( j=0; j<nFR; ++j )
02872                                                 {
02873                                                         jj = FR_idx[j];
02874                                                         delta_xFRz_RHS[j] = delta_g[jj];
02875                                                 }
02876                                         }
02877                                         else
02878                                         {
02879                                                 if ( nAC > 0 ) /* => Delta_bB_isZero == BT_TRUE, as BT_FALSE would imply nFX>0 */
02880                                                 {
02881                                                         for( j=0; j<nFR; ++j )
02882                                                         {
02883                                                                 jj = FR_idx[j];
02884                                                                 delta_xFRz_RHS[j] = delta_g[jj] + HFR_YFR_delta_xFRy[j];
02885                                                         }
02886                                                 }
02887                                                 else /* Delta_bB_isZero == BT_FALSE, as nAC==0 */
02888                                                 {
02889                                                         for( j=0; j<nFR; ++j )
02890                                                         {
02891                                                                 jj = FR_idx[j];
02892                                                                 delta_xFRz_RHS[j] = delta_g[jj] + HMX_delta_xFX[j];
02893                                                         }
02894                                                 }
02895                                         }
02896                                 }
02897 
02898                                 for( j=0; j<nFR; ++j )
02899                                 {
02900                                         jj = FR_idx[j];
02901                                         for( i=0; i<nZ; ++i )
02902                                                 delta_xFRz[i] -= Q[jj*NVMAX + i] * delta_xFRz_RHS[j];
02903                                 }
02904 
02905 
02906                                 if ( backsolveR( delta_xFRz,BT_TRUE,delta_xFRz_TMP ) != SUCCESSFUL_RETURN )
02907                                         return THROWERROR( RET_STEPDIRECTION_FAILED_CHOLESKY );
02908 
02909                                 if ( backsolveR( delta_xFRz_TMP,BT_FALSE,delta_xFRz ) != SUCCESSFUL_RETURN )
02910                                         return THROWERROR( RET_STEPDIRECTION_FAILED_CHOLESKY );
02911 
02912 
02913                                 for( i=0; i<nFR; ++i )
02914                                 {
02915                                         ii = FR_idx[i];
02916                                         for( j=0; j<nZ; ++j )
02917                                                 ZFR_delta_xFRz[i] += Q[ii*NVMAX + j] * delta_xFRz[j];
02918 
02919                                         delta_xFR[i] += ZFR_delta_xFRz[i];
02920                                 }
02921                         }
02922                 }
02923         }
02924 
02925         /* III) DETERMINE delta_yAC */
02926         if ( nAC > 0 ) /* => ( nFR = nZ + nAC > 0 ) */
02927         {
02928                 /* auxiliary variables */
02929                 real_t delta_yAC_TMP[NCMAX_ALLOC];
02930                 for( i=0; i<nAC; ++i )
02931                         delta_yAC_TMP[i] = 0.0;
02932                 real_t delta_yAC_RHS[NVMAX];
02933                 for( i=0; i<nFR; ++i )
02934                         delta_yAC_RHS[i] = 0.0;
02935 
02936                 if ( hessianType == HST_IDENTITY )
02937                 {
02938                         /* delta_yAC = (T')^-1 * ( Yfr*delta_gFR + delta_xFRy ) */
02939                         for( j=0; j<nAC; ++j )
02940                         {
02941                                 for( i=0; i<nFR; ++i )
02942                                 {
02943                                         ii = FR_idx[i];
02944                                         delta_yAC_TMP[j] += Q[ii*NVMAX + nZ+j] * delta_g[ii];
02945                                 }
02946 
02947                                 delta_yAC_TMP[j] += delta_xFRy[j];
02948                         }
02949                 }
02950                 else
02951                 {
02952                         if ( ( Delta_bC_isZero == BT_TRUE ) && ( Delta_bB_isZero == BT_TRUE ) )
02953                         {
02954                                 for( i=0; i<nFR; ++i )
02955                                 {
02956                                         ii = FR_idx[i];
02957                                         delta_yAC_RHS[i] = delta_g[ii];
02958                                 }
02959                         }
02960                         else
02961                         {
02962                                 for( i=0; i<nFR; ++i )
02963                                 {
02964                                         ii = FR_idx[i];
02965                                         delta_yAC_RHS[i] = HFR_YFR_delta_xFRy[i] + delta_g[ii];
02966                                 }
02967                         }
02968 
02969                         if ( nZ > 0 )
02970                         {
02971                                 for( i=0; i<nFR; ++i )
02972                                 {
02973                                         ii = FR_idx[i];
02974                                         for( j=0; j<nFR; ++j )
02975                                         {
02976                                                 jj = FR_idx[j];
02977                                                 delta_yAC_RHS[i] += H[ii*NVMAX + jj] * ZFR_delta_xFRz[j];
02978                                         }
02979                                 }
02980                         }
02981 
02982                         if ( nFX > 0 )
02983                         {
02984                                 if ( Delta_bB_isZero == BT_FALSE )
02985                                 {
02986                                         for( i=0; i<nFR; ++i )
02987                                                 delta_yAC_RHS[i] += HMX_delta_xFX[i];
02988                                 }
02989                         }
02990 
02991                         for( i=0; i<nAC; ++i)
02992                         {
02993                                 for( j=0; j<nFR; ++j )
02994                                 {
02995                                         jj = FR_idx[j];
02996                                         delta_yAC_TMP[i] += Q[jj*NVMAX + nZ+i] * delta_yAC_RHS[j];
02997                                 }
02998                         }
02999                 }
03000 
03001                 if ( backsolveT( delta_yAC_TMP,BT_TRUE,delta_yAC ) != SUCCESSFUL_RETURN )
03002                         return THROWERROR( RET_STEPDIRECTION_FAILED_TQ );
03003         }
03004 
03005 
03006         /* IV) DETERMINE delta_yFX */
03007         if ( nFX > 0 )
03008         {
03009                 for( i=0; i<nFX; ++i )
03010                 {
03011                         ii = FX_idx[i];
03012 
03013                         delta_yFX[i] = delta_g[ii];
03014 
03015                         for( j=0; j<nAC; ++j )
03016                         {
03017                                 jj = AC_idx[j];
03018                                 delta_yFX[i] -= A[jj*NVMAX + ii] * delta_yAC[j];
03019                         }
03020 
03021                         if ( hessianType == HST_IDENTITY )
03022                         {
03023                                 delta_yFX[i] += delta_xFX[i];
03024                         }
03025                         else
03026                         {
03027                                 for( j=0; j<nFR; ++j )
03028                                 {
03029                                         jj = FR_idx[j];
03030                                         delta_yFX[i] += H[ii*NVMAX + jj] * delta_xFR[j];
03031                                 }
03032 
03033                                 if ( Delta_bB_isZero == BT_FALSE )
03034                                 {
03035                                         for( j=0; j<nFX; ++j )
03036                                         {
03037                                                 jj = FX_idx[j];
03038                                                 delta_yFX[i] += H[ii*NVMAX + jj] * delta_xFX[j];
03039                                         }
03040                                 }
03041                         }
03042                 }
03043         }
03044 
03045         return SUCCESSFUL_RETURN;
03046 }
03047 
03048 
03049 /*
03050  *      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
03051  */
03052 returnValue QProblem::hotstart_determineStepLength(     const int* const FR_idx, const int* const FX_idx, const int* const AC_idx, const int* const IAC_idx,
03053                                                                                                         const real_t* const delta_lbA, const real_t* const delta_ubA,
03054                                                                                                         const real_t* const delta_lb, const real_t* const delta_ub,
03055                                                                                                         const real_t* const delta_xFX, const real_t* const delta_xFR,
03056                                                                                                         const real_t* const delta_yAC, const real_t* const delta_yFX,
03057                                                                                                         real_t* const delta_Ax, int& BC_idx, SubjectToStatus& BC_status, BooleanType& BC_isBound
03058                                                                                                         )
03059 {
03060         int i, j, ii, jj;
03061         int nV  = getNV( );
03062         int nC  = getNC( );
03063         int nFR = getNFR( );
03064         int nFX = getNFX( );
03065         int nAC = getNAC( );
03066         int nIAC = getNIAC( );
03067 
03068         /* initialise maximum steplength array */
03069         real_t maxStepLength[2*(NVMAX+NCMAX_ALLOC)];
03070         for ( i=0; i<2*(nV+nC); ++i )
03071                 maxStepLength[i] = 1.0;
03072 
03073 
03074         /* I) DETERMINE MAXIMUM DUAL STEPLENGTH: */
03075         /* 1) Ensure that active dual constraints' bounds remain valid
03076          *    (ignoring inequality constraints).  */
03077         for( i=0; i<nAC; ++i )
03078         {
03079                 ii = AC_idx[i];
03080 
03081                 if ( constraints.getType( ii ) != ST_EQUALITY )
03082                 {
03083                         if ( constraints.getStatus( ii ) == ST_LOWER )
03084                         {
03085                                 /* active lower constraints' bounds */
03086                                 if ( delta_yAC[i] < -ZERO )
03087                                 {
03088                                         if ( y[nV+ii] > 0.0 )
03089                                                 maxStepLength[nV+ii] = y[nV+ii] / ( -delta_yAC[i] );
03090                                         else
03091                                                 maxStepLength[nV+ii] = 0.0;
03092                                 }
03093                         }
03094                         else
03095                         {
03096                                 /* active upper constraints' bounds */
03097                                 if ( delta_yAC[i] > ZERO )
03098                                 {
03099                                         if ( y[nV+ii] < 0.0 )
03100                                                 maxStepLength[nV+ii] = y[nV+ii] / ( -delta_yAC[i] );
03101                                         else
03102                                                 maxStepLength[nV+ii] = 0.0;
03103                                 }
03104                         }
03105                 }
03106         }
03107 
03108         /* 2) Ensure that active dual bounds remain valid
03109          *    (ignoring implicitly fixed variables). */
03110         for( i=0; i<nFX; ++i )
03111         {
03112                 ii = FX_idx[i];
03113 
03114                 if ( bounds.getType( ii ) != ST_EQUALITY )
03115                 {
03116                         if ( bounds.getStatus( ii ) == ST_LOWER )
03117                         {
03118                                 /* active lower bounds */
03119                                 if ( delta_yFX[i] < -ZERO )
03120                                 {
03121                                         if ( y[ii] > 0.0 )
03122                                                 maxStepLength[ii] = y[ii] / ( -delta_yFX[i] );
03123                                         else
03124                                                 maxStepLength[ii] = 0.0;
03125                                 }
03126                         }
03127                         else
03128                         {
03129                                 /* active upper bounds */
03130                                 if ( delta_yFX[i] > ZERO )
03131                                 {
03132                                         if ( y[ii] < 0.0 )
03133                                                 maxStepLength[ii] = y[ii] / ( -delta_yFX[i] );
03134                                         else
03135                                                 maxStepLength[ii] = 0.0;
03136                                 }
03137                         }
03138                 }
03139         }
03140 
03141 
03142         /* II) DETERMINE MAXIMUM PRIMAL STEPLENGTH */
03143         /* 1) Ensure that inactive constraints' bounds remain valid
03144          *    (ignoring unbounded constraints). */
03145         real_t delta_x[NVMAX];
03146         for( j=0; j<nFR; ++j )
03147         {
03148                 jj = FR_idx[j];
03149                 delta_x[jj] = delta_xFR[j];
03150         }
03151         for( j=0; j<nFX; ++j )
03152         {
03153                 jj = FX_idx[j];
03154                 delta_x[jj] = delta_xFX[j];
03155         }
03156 
03157         for( i=0; i<nIAC; ++i )
03158         {
03159                 ii = IAC_idx[i];
03160 
03161                 if ( constraints.getType( ii ) != ST_UNBOUNDED )
03162                 {
03163                         delta_Ax[ii] = 0.0;
03164                         for( j=0; j<nV; ++j )
03165                                 delta_Ax[ii] += A[ii*NVMAX + j] * delta_x[j]; // POSSIBLE SPEEDUP!
03166 
03167                         /* inactive lower constraints' bounds */
03168                         if ( constraints.isNoLower( ) == BT_FALSE )
03169                         {
03170                                 if ( delta_lbA[ii] > delta_Ax[ii] )
03171                                 {
03172                                         if ( Ax[ii] > lbA[ii] )
03173                                                 maxStepLength[nV+ii] = ( Ax[ii] - lbA[ii] ) / ( delta_lbA[ii] - delta_Ax[ii] );
03174                                         else
03175                                                 maxStepLength[nV+ii] = 0.0;
03176                                 }
03177                         }
03178 
03179                         /* inactive upper constraints' bounds */
03180                         if ( constraints.isNoUpper( ) == BT_FALSE )
03181                         {
03182                                 if ( delta_ubA[ii] < delta_Ax[ii] )
03183                                 {
03184                                         if ( Ax[ii] < ubA[ii] )
03185                                                 maxStepLength[nV+nC+nV+ii] = ( Ax[ii] - ubA[ii] ) / ( delta_ubA[ii] - delta_Ax[ii] );
03186                                         else
03187                                                 maxStepLength[nV+nC+nV+ii] = 0.0;
03188                                 }
03189                         }
03190                 }
03191         }
03192 
03193 
03194         /* 2) Ensure that inactive bounds remain valid
03195          *    (ignoring unbounded variables). */
03196         /* inactive lower bounds */
03197         if ( bounds.isNoLower( ) == BT_FALSE )
03198         {
03199                 for( i=0; i<nFR; ++i )
03200                 {
03201                         ii = FR_idx[i];
03202                         if ( bounds.getType( ii ) != ST_UNBOUNDED )
03203                                 if ( delta_lb[ii] > delta_xFR[i] )
03204                                 {
03205                                         if ( x[ii] > lb[ii] )
03206                                                 maxStepLength[ii] = ( x[ii] - lb[ii] ) / ( delta_lb[ii] - delta_xFR[i] );
03207                                         else
03208                                                 maxStepLength[ii] = 0.0;
03209                                 }
03210                 }
03211         }
03212 
03213         /* inactive upper bounds */
03214         if ( bounds.isNoUpper( ) == BT_FALSE )
03215         {
03216                 for( i=0; i<nFR; ++i )
03217                 {
03218                         ii = FR_idx[i];
03219                         if ( bounds.getType( ii ) != ST_UNBOUNDED )
03220                                 if ( delta_ub[ii] < delta_xFR[i] )
03221                                 {
03222                                         if ( x[ii] < ub[ii] )
03223                                                 maxStepLength[nV+nC+ii] = ( x[ii] - ub[ii] ) / ( delta_ub[ii] - delta_xFR[i] );
03224                                         else
03225                                                 maxStepLength[nV+nC+ii] = 0.0;
03226                                 }
03227                 }
03228         }
03229 
03230 
03231         /* III) DETERMINE MAXIMUM HOMOTOPY STEPLENGTH */
03232         real_t tau_new = 1.0;
03233 
03234         BC_idx = 0;
03235         BC_status = ST_UNDEFINED;
03236         BC_isBound = BT_FALSE;
03237 
03238         for ( i=0; i<nV; ++i )
03239         {
03240                 /* 1) Consider lower/dual blocking bounds. */
03241                 if ( maxStepLength[i] < tau_new )
03242                 {
03243                         tau_new = maxStepLength[i];
03244                         BC_idx = i;
03245                         BC_isBound = BT_TRUE;
03246                         if ( bounds.getStatus( i ) == ST_INACTIVE ) /* inactive? */
03247                                 BC_status = ST_LOWER;
03248                         else
03249                                 BC_status = ST_INACTIVE;
03250                 }
03251 
03252                 /* 2) Consider upper blocking bounds. */
03253                 if ( maxStepLength[nV+nC+i] < tau_new )
03254                 {
03255                         tau_new = maxStepLength[nV+nC+i];
03256                         BC_idx = i;
03257                         BC_isBound = BT_TRUE;
03258                         BC_status = ST_UPPER;
03259                 }
03260         }
03261 
03262         for ( i=nV; i<nV+nC; ++i )
03263         {
03264                 /* 3) Consider lower/dual blocking constraints. */
03265                 if ( maxStepLength[i] < tau_new )
03266                 {
03267                         tau_new = maxStepLength[i];
03268                         BC_idx = i-nV;
03269                         BC_isBound = BT_FALSE;
03270                         if ( constraints.getStatus( i-nV ) == ST_INACTIVE ) /* inactive? */
03271                                 BC_status = ST_LOWER;
03272                         else
03273                                 BC_status = ST_INACTIVE;
03274                 }
03275 
03276                 /* 4) Consider upper blocking constraints. */
03277                 if ( maxStepLength[nV+nC+i] < tau_new )
03278                 {
03279                         tau_new = maxStepLength[nV+nC+i];
03280                         BC_idx = i-nV;
03281                         BC_isBound = BT_FALSE;
03282                         BC_status = ST_UPPER;
03283                 }
03284         }
03285 
03286 
03287         /* IV) CLEAR CYCLING DATA
03288          *     if a positive step can be taken */
03289         if ( tau_new > EPS )
03290                 cyclingManager.clearCyclingData( );
03291 
03292 
03293         /* V) SET MAXIMUM HOMOTOPY STEPLENGTH */
03294         tau = tau_new;
03295 
03296         #ifdef PC_DEBUG
03297         if ( printlevel == PL_HIGH )
03298         {
03299 
03300                 char messageString[80];
03301 
03302                 if ( BC_status == ST_UNDEFINED )
03303                         sprintf( messageString,"Stepsize is %.6e!",tau );
03304                 else
03305                         sprintf( messageString,"Stepsize is %.6e! (BC_idx = %d, BC_isBound = %d, BC_status = %d)",tau,BC_idx,BC_isBound,BC_status );
03306 
03307                 getGlobalMessageHandler( )->throwInfo( RET_STEPSIZE_NONPOSITIVE,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
03308         }
03309         #endif
03310 
03311         return SUCCESSFUL_RETURN;
03312 }
03313 
03314 
03315 /*
03316  *      h o t s t a r t _ p e r f o r m S t e p
03317  */
03318 returnValue QProblem::hotstart_performStep(     const int* const FR_idx, const int* const FX_idx, const int* const AC_idx, const int* const IAC_idx,
03319                                                                                         const real_t* const delta_g, const real_t* const delta_lbA, const real_t* const delta_ubA,
03320                                                                                         const real_t* const delta_lb, const real_t* const delta_ub,
03321                                                                                         const real_t* const delta_xFX, const real_t* const delta_xFR,
03322                                                                                         const real_t* const delta_yAC, const real_t* const delta_yFX,
03323                                                                                         const real_t* const delta_Ax, int BC_idx, SubjectToStatus BC_status, BooleanType BC_isBound
03324                                                                                         )
03325 {
03326         int i, j, ii;
03327         int nV  = getNV( );
03328         int nC  = getNC( );
03329         int nFR = getNFR( );
03330         int nFX = getNFX( );
03331         int nAC = getNAC( );
03332         int nIAC = getNIAC( );
03333 
03334 
03335         /* I) CHECK (CONSTRAINTS') BOUNDS' CONSISTENCY */
03336         if ( areBoundsConsistent( delta_lb,delta_ub,delta_lbA,delta_ubA ) == BT_FALSE )
03337         {
03338                 infeasible = BT_TRUE;
03339                 tau = 0.0;
03340 
03341                 return THROWERROR( RET_QP_INFEASIBLE );
03342         }
03343 
03344 
03345         /* II) GO TO ACTIVE SET CHANGE */
03346         if ( tau > ZERO )
03347         {
03348                 /* 1) Perform step in primal und dual space... */
03349                 for( i=0; i<nFR; ++i )
03350                 {
03351                         ii = FR_idx[i];
03352                         x[ii] += tau*delta_xFR[i];
03353                 }
03354 
03355                 for( i=0; i<nFX; ++i )
03356                 {
03357                         ii = FX_idx[i];
03358                         x[ii] += tau*delta_xFX[i];
03359                         y[ii] += tau*delta_yFX[i];
03360                 }
03361 
03362                 for( i=0; i<nAC; ++i )
03363                 {
03364                         ii = AC_idx[i];
03365                         y[nV+ii] += tau*delta_yAC[i];
03366                 }
03367 
03368                 /* ... also for Ax. */
03369                 for( i=0; i<nIAC; ++i )
03370                 {
03371                         ii = IAC_idx[i];
03372                         if ( constraints.getType( ii ) != ST_UNBOUNDED )
03373                                 Ax[ii] += tau*delta_Ax[ii];
03374                 }
03375                 for( i=0; i<nAC; ++i )
03376                 {
03377                         ii = AC_idx[i];
03378 
03379                         Ax[ii] = 0.0;
03380                         for( j=0; j<nV; ++j )
03381                                 Ax[ii] += A[ii*NVMAX + j] * x[j];
03382                 }
03383 
03384                 /* 2) Shift QP data. */
03385                 for( i=0; i<nV; ++i )
03386                 {
03387                         g[i]  += tau*delta_g[i];
03388                         lb[i] += tau*delta_lb[i];
03389                         ub[i] += tau*delta_ub[i];
03390                 }
03391 
03392                 for( i=0; i<nC; ++i )
03393                 {
03394                         lbA[i] += tau*delta_lbA[i];
03395                         ubA[i] += tau*delta_ubA[i];
03396                 }
03397         }
03398         else
03399         {
03400                 /* print a stepsize warning if stepsize is zero */
03401                 #ifdef PC_DEBUG
03402                 char messageString[80];
03403                 sprintf( messageString,"Stepsize is %.6e",tau );
03404                 getGlobalMessageHandler( )->throwWarning( RET_STEPSIZE,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
03405                 #endif
03406         }
03407 
03408 
03409         /* setup output preferences */
03410         #ifdef PC_DEBUG
03411         char messageString[80];
03412         VisibilityStatus visibilityStatus;
03413 
03414         if ( printlevel == PL_HIGH )
03415                 visibilityStatus = VS_VISIBLE;
03416         else
03417                 visibilityStatus = VS_HIDDEN;
03418         #endif
03419 
03420         
03421         /* III) UPDATE ACTIVE SET */
03422         switch ( BC_status )
03423         {
03424                 /* Optimal solution found as no working set change detected. */
03425                 case ST_UNDEFINED:
03426                         return RET_OPTIMAL_SOLUTION_FOUND;
03427 
03428 
03429                 /* Remove one variable from active set. */
03430                 case ST_INACTIVE:
03431                         if ( BC_isBound == BT_TRUE )
03432                         {
03433                                 #ifdef PC_DEBUG
03434                                 sprintf( messageString,"bound no. %d.", BC_idx );
03435                                 getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
03436                                 #endif
03437 
03438                                 if ( removeBound( BC_idx,BT_TRUE ) != SUCCESSFUL_RETURN )
03439                                         return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
03440 
03441                                 y[BC_idx] = 0.0;
03442                         }
03443                         else
03444                         {
03445                                 #ifdef PC_DEBUG
03446                                 sprintf( messageString,"constraint no. %d.", BC_idx );
03447                                 getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
03448                                 #endif
03449 
03450                                 if ( removeConstraint( BC_idx,BT_TRUE ) != SUCCESSFUL_RETURN )
03451                                         return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
03452 
03453                                 y[nV+BC_idx] = 0.0;
03454                         }
03455                         break;
03456 
03457 
03458                 /* Add one variable to active set. */
03459                 default:
03460                         if ( BC_isBound == BT_TRUE )
03461                         {
03462                                 #ifdef PC_DEBUG
03463                                 if ( BC_status == ST_LOWER )
03464                                         sprintf( messageString,"lower bound no. %d.", BC_idx );
03465                                 else
03466                                         sprintf( messageString,"upper bound no. %d.", BC_idx );
03467                                 getGlobalMessageHandler( )->throwInfo( RET_ADD_TO_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
03468                                 #endif
03469 
03470                                 if ( addBound( BC_idx,BC_status,BT_TRUE ) != SUCCESSFUL_RETURN )
03471                                         return THROWERROR( RET_ADD_TO_ACTIVESET_FAILED );
03472                         }
03473                         else
03474                         {
03475                                 #ifdef PC_DEBUG
03476                                 if ( BC_status == ST_LOWER )
03477                                         sprintf( messageString,"lower constraint's bound no. %d.", BC_idx );
03478                                 else
03479                                         sprintf( messageString,"upper constraint's bound no. %d.", BC_idx );
03480                                 getGlobalMessageHandler( )->throwInfo( RET_ADD_TO_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
03481                                 #endif
03482 
03483                                 if ( addConstraint( BC_idx,BC_status,BT_TRUE ) != SUCCESSFUL_RETURN )
03484                                         return THROWERROR( RET_ADD_TO_ACTIVESET_FAILED );
03485                         }
03486                         break;
03487         }
03488 
03489         return SUCCESSFUL_RETURN;
03490 }
03491 
03492 
03493 /*
03494  *      a r e B o u n d s C o n s i s t e n t
03495  */
03496 BooleanType QProblem::areBoundsConsistent(      const real_t* const delta_lb, const real_t* const delta_ub,
03497                                                                                         const real_t* const delta_lbA, const real_t* const delta_ubA
03498                                                                                         ) const
03499 {
03500         int i;
03501 
03502         /* 1) Check bounds' consistency. */
03503         if ( QProblemB::areBoundsConsistent( delta_lb,delta_ub ) == BT_FALSE )
03504                 return BT_FALSE;
03505 
03506         /* 2) Check constraints' consistency, i.e.
03507          *    check if delta_lb[i] is greater than delta_ub[i]
03508          *    for a component i whose bounds are already (numerically) equal. */
03509         for( i=0; i<getNC( ); ++i )
03510                 if ( ( lbA[i] > ubA[i] - BOUNDTOL ) && ( delta_lbA[i] > delta_ubA[i] + EPS ) )
03511                         return BT_FALSE;
03512 
03513         return BT_TRUE;
03514 }
03515 
03516 
03517 /*
03518  *      s e t u p Q P d a t a
03519  */
03520 returnValue QProblem::setupQPdata(      const real_t* const _H, const real_t* const _g, const real_t* const _A,
03521                                                                         const real_t* const _lb, const real_t* const _ub,
03522                                                                         const real_t* const _lbA, const real_t* const _ubA
03523                                                                         )
03524 {
03525         int i, j;
03526         int nV = getNV( );
03527         int nC = getNC( );
03528 
03529 
03530         /* 1) Load Hessian matrix as well as lower and upper bounds vectors. */
03531         if ( QProblemB::setupQPdata( _H,_g,_lb,_ub ) != SUCCESSFUL_RETURN )
03532                 return THROWERROR( RET_INVALID_ARGUMENTS );
03533 
03534         /* 2) Load constraint matrix. */
03535         if ( ( nC > 0 ) && ( _A == 0 ) )
03536                 return THROWERROR( RET_INVALID_ARGUMENTS );
03537 
03538         if ( nC > 0 )
03539         {
03540                 for( i=0; i<nC; ++i )
03541                         for( j=0; j<nV; ++j )
03542                                 A[i*NVMAX + j] = _A[i*nV + j];
03543 
03544                 /* 3) Setup lower constraints' bounds vector. */
03545                 if ( _lbA != 0 )
03546                 {
03547                         for( i=0; i<nC; ++i )
03548                                 lbA[i] = _lbA[i];
03549                 }
03550                 else
03551                 {
03552                         /* if no lower constraints' bounds are specified, set them to -infinity */
03553                         for( i=0; i<nC; ++i )
03554                                 lbA[i] = -INFTY;
03555                 }
03556 
03557                 /* 4) Setup upper constraints' bounds vector. */
03558                 if ( _ubA != 0 )
03559                 {
03560                         for( i=0; i<nC; ++i )
03561                                 ubA[i] = _ubA[i];
03562                 }
03563                 else
03564                 {
03565                         /* if no upper constraints' bounds are specified, set them to infinity */
03566                         for( i=0; i<nC; ++i )
03567                                 ubA[i] = INFTY;
03568                 }
03569         }
03570 
03571 //      printmatrix2( "A",A,10,20 );
03572         
03573 //      printmatrix2( "lbA",lbA,1,nC );
03574 //      printmatrix2( "ubA",ubA,1,nC );
03575 
03576         return SUCCESSFUL_RETURN;
03577 }
03578 
03579 
03580 
03581 #ifdef PC_DEBUG  /* Define print functions only for debugging! */
03582 
03583 /*
03584  *      p r i n t I t e r a t i o n
03585  */
03586 returnValue QProblem::printIteration(   int iteration,
03587                                                                                 int BC_idx,     SubjectToStatus BC_status, BooleanType BC_isBound
03588                                                                                 )
03589 {
03590         char myPrintfString[160];
03591 
03592         /* consistency check */
03593         if ( iteration < 0 )
03594                 return THROWERROR( RET_INVALID_ARGUMENTS );
03595 
03596         /* nothing to do */
03597         if ( printlevel != PL_MEDIUM )
03598                 return SUCCESSFUL_RETURN;
03599 
03600 
03601         /* 1) Print header at first iteration. */
03602         if ( iteration == 0 )
03603         {
03604                 sprintf( myPrintfString,"\n##############  qpOASES  --  QP NO.%4.1d  ###############\n", count );
03605                 myPrintf( myPrintfString );
03606 
03607                 sprintf( myPrintfString,"  Iter  |  StepLength   |     Info      |  nFX  |  nAC  \n" );
03608                 myPrintf( myPrintfString );
03609         }
03610 
03611         /* 2) Print iteration line. */
03612         if ( BC_status == ST_UNDEFINED )
03613         {
03614                 sprintf( myPrintfString,"  %4.1d  |  %1.5e  |   QP SOLVED   | %4.1d  | %4.1d  \n", iteration,tau,getNFX( ),getNAC( ) );
03615                 myPrintf( myPrintfString );
03616         }
03617         else
03618         {
03619                 char info[8];
03620 
03621                 if ( BC_status == ST_INACTIVE )
03622                         sprintf( info,"REM " );
03623                 else
03624                         sprintf( info,"ADD " );
03625 
03626                 if ( BC_isBound == BT_TRUE )
03627                         sprintf( &(info[4]),"BND" );
03628                 else
03629                         sprintf( &(info[4]),"CON" );
03630 
03631                 sprintf( myPrintfString,"  %4.1d  |  %1.5e  |  %s%4.1d  | %4.1d  | %4.1d  \n", iteration,tau,info,BC_idx,getNFX( ),getNAC( ) );
03632                 myPrintf( myPrintfString );
03633         }
03634 
03635         return SUCCESSFUL_RETURN;
03636 }
03637 
03638 
03639 /*
03640  *      p r i n t I t e r a t i o n
03641  */
03642 returnValue QProblem::printIteration(   int iteration,
03643                                                                                 int BC_idx,     SubjectToStatus BC_status
03644                                                                                 )
03645 {
03646         return printIteration( iteration,BC_idx,BC_status,BT_TRUE );
03647 }
03648 
03649 #endif  /* PC_DEBUG */
03650 
03651 
03652 
03653 /*
03654  *      c h e c k K K T c o n d i t i o n s
03655  */
03656 returnValue QProblem::checkKKTconditions( )
03657 {
03658         #ifdef __PERFORM_KKT_TEST__
03659 
03660         int i, j, jj;
03661         int nV  = getNV( );
03662         int nC  = getNC( );
03663         int nAC = getNAC( );
03664 
03665         real_t tmp;
03666         real_t maxKKTviolation = 0.0;
03667 
03668         int AC_idx[NCMAX_ALLOC];
03669         constraints.getActive( )->getNumberArray( AC_idx );
03670 
03671         /* 1) check for Hx + g - [yFX yAC]*[Id A]' = 0. */
03672         for( i=0; i<nV; ++i )
03673         {
03674                 tmp = g[i];
03675 
03676                 for( j=0; j<nV; ++j )
03677                         tmp += H[i*NVMAX + j] * x[j];
03678 
03679                 tmp -= y[i];
03680 
03681                 /* Only sum over active constraints as y is zero for all inactive ones. */
03682                 for( j=0; j<nAC; ++j )
03683                 {
03684                         jj = AC_idx[j];
03685                         tmp -= A[jj*NVMAX + i] * y[nV+jj];
03686                 }
03687 
03688                 if ( getAbs( tmp ) > maxKKTviolation )
03689                         maxKKTviolation = getAbs( tmp );
03690         }
03691 
03692         /* 2) Check for [lb lbA] <= [Id A]*x <= [ub ubA]. */
03693         /* lbA <= Ax <= ubA */
03694         for( i=0; i<nC; ++i )
03695         {
03696                 if ( lbA[i] - Ax[i] > maxKKTviolation )
03697                         maxKKTviolation = lbA[i] - Ax[i];
03698 
03699                 if ( Ax[i] - ubA[i] > maxKKTviolation )
03700                         maxKKTviolation = Ax[i] - ubA[i];
03701         }
03702 
03703         /* lb <= x <= ub */
03704         for( i=0; i<nV; ++i )
03705         {
03706                 if ( lb[i] - x[i] > maxKKTviolation )
03707                         maxKKTviolation = lb[i] - x[i];
03708 
03709                 if ( x[i] - ub[i] > maxKKTviolation )
03710                         maxKKTviolation = x[i] - ub[i];
03711         }
03712 
03713         /* 3) Check for correct sign of y and for complementary slackness. */
03714         /* bounds */
03715         for( i=0; i<nV; ++i )
03716         {
03717                 switch ( bounds.getStatus( i ) )
03718                 {
03719                         case ST_LOWER:
03720                                 if ( -y[i] > maxKKTviolation )
03721                                         maxKKTviolation = -y[i];
03722                                 if ( getAbs( x[i] - lb[i] ) > maxKKTviolation )
03723                                         maxKKTviolation = getAbs( x[i] - lb[i] );
03724                                 break;
03725 
03726                         case ST_UPPER:
03727                                 if ( y[i] > maxKKTviolation )
03728                                         maxKKTviolation = y[i];
03729                                 if ( getAbs( ub[i] - x[i] ) > maxKKTviolation )
03730                                         maxKKTviolation = getAbs( ub[i] - x[i] );
03731                                 break;
03732 
03733                         default: /* inactive */
03734                         if ( getAbs( y[i] ) > maxKKTviolation )
03735                                         maxKKTviolation = getAbs( y[i] );
03736                                 break;
03737                 }
03738         }
03739 
03740         /* constraints */
03741         for( i=0; i<nC; ++i )
03742         {
03743                 switch ( constraints.getStatus( i ) )
03744                 {
03745                         case ST_LOWER:
03746                                 if ( -y[nV+i] > maxKKTviolation )
03747                                         maxKKTviolation = -y[nV+i];
03748                                 if ( getAbs( Ax[i] - lbA[i] ) > maxKKTviolation )
03749                                         maxKKTviolation = getAbs( Ax[i] - lbA[i] );
03750                                 break;
03751 
03752                         case ST_UPPER:
03753                                 if ( y[nV+i] > maxKKTviolation )
03754                                         maxKKTviolation = y[nV+i];
03755                                 if ( getAbs( ubA[i] - Ax[i] ) > maxKKTviolation )
03756                                         maxKKTviolation = getAbs( ubA[i] - Ax[i] );
03757                                 break;
03758 
03759                         default: /* inactive */
03760                         if ( getAbs( y[nV+i] ) > maxKKTviolation )
03761                                         maxKKTviolation = getAbs( y[nV+i] );
03762                                 break;
03763                 }
03764         }
03765 
03766         if ( maxKKTviolation > CRITICALACCURACY )
03767                 return RET_NO_SOLUTION;
03768 
03769         if ( maxKKTviolation > DESIREDACCURACY )
03770                 return RET_INACCURATE_SOLUTION;
03771 
03772         #endif /* __PERFORM_KKT_TEST__ */
03773 
03774         return SUCCESSFUL_RETURN;
03775 }
03776 
03777 
03778 /*
03779  *      end of file
03780  */


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Thu Aug 27 2015 11:59:50