#include <ClpPredictorCorrector.hpp>
Inheritance diagram for ClpPredictorCorrector:
Public Member Functions | |
Description of algorithm | |
int | solve () |
Functions used in algorithm | |
double | findStepLength (const int phase) |
findStepLength. | |
double | findDirectionVector (const int phase) |
findDirectionVector. | |
void | createSolution () |
createSolution. Creates solution from scratch | |
double | complementarityGap (int &numberComplementarityPairs, const int phase) |
complementarityGap. Computes gap | |
void | setupForSolve (const int phase) |
setupForSolve. | |
bool | checkGoodMove (const bool doCorrector) |
bool | checkGoodMove2 (const double move) |
: checks for one step size | |
int | updateSolution () |
updateSolution. Updates solution at end of iteration | |
double | affineProduct () |
Save info on products of affine deltaT*deltaW and deltaS*deltaZ. |
It is rather basic as Interior point is not my speciality
It inherits from ClpInterior. It has no data of its own and is never created - only cast from a ClpInterior object at algorithm time.
Definition at line 24 of file ClpPredictorCorrector.hpp.
|
Primal Dual Predictor Corrector algorithm Method Big TODO Definition at line 38 of file ClpPredictorCorrector.cpp. References affineProduct(), ClpInterior::checkSolution(), complementarityGap(), createSolution(), ClpInterior::createWorkingData(), ClpModel::dualTolerance(), ClpCholeskyBase::factorize(), findDirectionVector(), findStepLength(), CoinMessageHandler::message(), ClpModel::objectiveValue(), ClpCholeskyBase::order(), ClpModel::primalTolerance(), ClpCholeskyBase::rank(), ClpCholeskyBase::resetRowsDropped(), setupForSolve(), ClpCholeskyBase::status(), ClpMatrixBase::times(), ClpMatrixBase::transposeTimes(), and updateSolution().
00039 { 00040 problemStatus_=-1; 00041 algorithm_=1; 00042 //create all regions 00043 if (!createWorkingData()) { 00044 problemStatus_=4; 00045 return 2; 00046 } 00047 //initializeFeasible(); - this just set fixed flag 00048 smallestInfeasibility_=COIN_DBL_MAX; 00049 int i; 00050 for (i=0;i<LENGTH_HISTORY;i++) 00051 historyInfeasibility_[i]=COIN_DBL_MAX; 00052 00053 //bool firstTime=true; 00054 //firstFactorization(true); 00055 cholesky_->order(this); 00056 mu_=1.0e10; 00057 //set iterations 00058 numberIterations_=-1; 00059 //initialize solution here 00060 createSolution(); 00061 //firstFactorization(false); 00062 CoinZeroN(dual_,numberRows_); 00063 multiplyAdd(solution_+numberColumns_,numberRows_,-1.0,errorRegion_,0.0); 00064 matrix_->times(1.0,solution_,errorRegion_); 00065 maximumRHSError_=maximumAbsElement(errorRegion_,numberRows_); 00066 maximumBoundInfeasibility_=maximumRHSError_; 00067 //double maximumDualError_=COIN_DBL_MAX; 00068 //initialize 00069 actualDualStep_=0.0; 00070 actualPrimalStep_=0.0; 00071 gonePrimalFeasible_=false; 00072 goneDualFeasible_=false; 00073 //bool hadGoodSolution=false; 00074 diagonalScaleFactor_=1.0; 00075 diagonalNorm_=solutionNorm_; 00076 mu_=solutionNorm_; 00077 int numberFixed=updateSolution(); 00078 int numberFixedTotal=numberFixed; 00079 //int numberRows_DroppedBefore=0; 00080 //double extra=eExtra; 00081 //double maximumPerturbation=COIN_DBL_MAX; 00082 //constants for infeas interior point 00083 const double beta2 = 0.99995; 00084 const double tau = 0.00002; 00085 double lastComplementarityGap=COIN_DBL_MAX; 00086 int lastGoodIteration=0; 00087 double bestObjectiveGap=COIN_DBL_MAX; 00088 int saveIteration=-1; 00089 bool sloppyOptimal=false; 00090 double * savePi=NULL; 00091 double * savePrimal=NULL; 00092 int numberTotal = numberRows_+numberColumns_; 00093 while (problemStatus_<0) { 00094 complementarityGap_=complementarityGap(numberComplementarityPairs_,0); 00095 handler_->message(CLP_BARRIER_ITERATION,messages_) 00096 <<numberIterations_ 00097 <<primalObjective_*optimizationDirection_- dblParam_[ClpObjOffset] 00098 << dualObjective_*optimizationDirection_- dblParam_[ClpObjOffset] 00099 <<complementarityGap_ 00100 <<numberFixedTotal 00101 <<cholesky_->rank() 00102 <<CoinMessageEol; 00103 double goodGapChange; 00104 if (!sloppyOptimal) { 00105 goodGapChange=0.93; 00106 } else { 00107 goodGapChange=0.7; 00108 } 00109 double gapO; 00110 double lastGood=bestObjectiveGap; 00111 if (gonePrimalFeasible_&&goneDualFeasible_) { 00112 double largestObjective; 00113 if (fabs(primalObjective_)>fabs(dualObjective_)) { 00114 largestObjective = fabs(primalObjective_); 00115 } else { 00116 largestObjective = fabs(dualObjective_); 00117 } 00118 if (largestObjective<1.0) { 00119 largestObjective=1.0; 00120 } 00121 gapO=fabs(primalObjective_-dualObjective_)/largestObjective; 00122 handler_->message(CLP_BARRIER_OBJECTIVE_GAP,messages_) 00123 <<gapO 00124 <<CoinMessageEol; 00125 //start saving best 00126 if (gapO<bestObjectiveGap) { 00127 saveIteration=numberIterations_; 00128 bestObjectiveGap=gapO; 00129 if (!savePi) { 00130 savePi=new double[numberRows_]; 00131 savePrimal = new double [numberTotal]; 00132 } 00133 CoinMemcpyN(dual_,numberRows_,savePi); 00134 CoinMemcpyN(solution_,numberTotal,savePrimal); 00135 } else if(gapO>2.0*bestObjectiveGap) { 00136 //maybe be more sophisticated e.g. re-initialize having 00137 //fixed variables and dropped rows 00138 //std::cout <<" gap increasing "<<std::endl; 00139 } 00140 //std::cout <<"could stop"<<std::endl; 00141 //gapO=0.0; 00142 if (fabs(primalObjective_-dualObjective_)<dualTolerance()) { 00143 gapO=0.0; 00144 } 00145 } else { 00146 gapO=COIN_DBL_MAX; 00147 if (saveIteration>=0) { 00148 handler_->message(CLP_BARRIER_GONE_INFEASIBLE,messages_) 00149 <<CoinMessageEol; 00150 } 00151 } 00152 if (gapO<1.0e-7&&!sloppyOptimal) { 00153 sloppyOptimal=true; 00154 handler_->message(CLP_BARRIER_CLOSE_TO_OPTIMAL,messages_) 00155 <<numberIterations_<<complementarityGap_ 00156 <<CoinMessageEol; 00157 } 00158 if (complementarityGap_>=1.05*lastComplementarityGap) { 00159 handler_->message(CLP_BARRIER_COMPLEMENTARITY,messages_) 00160 <<complementarityGap_<<"increasing" 00161 <<CoinMessageEol; 00162 if (saveIteration>=0&&sloppyOptimal) { 00163 handler_->message(CLP_BARRIER_EXIT2,messages_) 00164 <<saveIteration 00165 <<CoinMessageEol; 00166 break; 00167 } else { 00168 //lastComplementarityGap=complementarityGap_; 00169 } 00170 } else if (complementarityGap_<goodGapChange*lastComplementarityGap) { 00171 lastGoodIteration=numberIterations_; 00172 lastComplementarityGap=complementarityGap_; 00173 } else if (numberIterations_-lastGoodIteration>=5&&complementarityGap_<1.0e-3) { 00174 handler_->message(CLP_BARRIER_COMPLEMENTARITY,messages_) 00175 <<complementarityGap_<<"not decreasing" 00176 <<CoinMessageEol; 00177 if (gapO>0.75*lastGood) { 00178 break; 00179 } 00180 } 00181 if (numberIterations_>maximumBarrierIterations_) { 00182 handler_->message(CLP_BARRIER_STOPPING,messages_) 00183 <<CoinMessageEol; 00184 break; 00185 } 00186 if (gapO<targetGap_) { 00187 problemStatus_=0; 00188 handler_->message(CLP_BARRIER_EXIT,messages_) 00189 <<" " 00190 <<CoinMessageEol; 00191 break;//finished 00192 } 00193 if (complementarityGap_<1.0e-18) { 00194 problemStatus_=0; 00195 handler_->message(CLP_BARRIER_EXIT,messages_) 00196 <<"- small complementarity gap" 00197 <<CoinMessageEol; 00198 break;//finished 00199 } 00200 if (complementarityGap_<1.0e-10&&gapO<1.0e-10) { 00201 problemStatus_=0; 00202 handler_->message(CLP_BARRIER_EXIT,messages_) 00203 <<"- objective gap and complementarity gap both small" 00204 <<CoinMessageEol; 00205 break;//finished 00206 } 00207 if (gapO<1.0e-9) { 00208 double value=gapO*complementarityGap_; 00209 value*=actualPrimalStep_; 00210 value*=actualDualStep_; 00211 //std::cout<<value<<std::endl; 00212 if (value<1.0e-17&&numberIterations_>lastGoodIteration) { 00213 problemStatus_=0; 00214 handler_->message(CLP_BARRIER_EXIT,messages_) 00215 <<"- objective gap and complementarity gap both smallish and small steps" 00216 <<CoinMessageEol; 00217 break;//finished 00218 } 00219 } 00220 bool useAffine=false; 00221 bool goodMove=false; 00222 bool doCorrector=true; 00223 //bool retry=false; 00224 worstDirectionAccuracy_=0.0; 00225 while (!goodMove) { 00226 goodMove=true; 00227 int newDropped=0; 00228 //Predictor step 00229 //Are we going to use the affine direction? 00230 if (!useAffine) { 00231 //no - normal 00232 //prepare for cholesky. Set up scaled diagonal in weights 00233 // ** for efficiency may be better if scale factor known before 00234 double norm2=0.0; 00235 double maximumValue; 00236 getNorms(diagonal_,numberColumns_,maximumValue,norm2); 00237 diagonalNorm_ = sqrt(norm2/numberComplementarityPairs_); 00238 diagonalScaleFactor_=1.0; 00239 double maximumAllowable=eScale; 00240 //scale so largest is less than allowable ? could do better 00241 double factor=0.5; 00242 while (maximumValue>maximumAllowable) { 00243 diagonalScaleFactor_*=factor; 00244 maximumValue*=factor; 00245 } /* endwhile */ 00246 if (diagonalScaleFactor_!=1.0) { 00247 handler_->message(CLP_BARRIER_SCALING,messages_) 00248 <<"diagonal"<<diagonalScaleFactor_ 00249 <<CoinMessageEol; 00250 diagonalNorm_*=diagonalScaleFactor_; 00251 } 00252 multiplyAdd(NULL,numberTotal,0.0,diagonal_, 00253 diagonalScaleFactor_); 00254 int * rowsDroppedThisTime = new int [numberRows_]; 00255 newDropped=cholesky_->factorize(diagonal_,rowsDroppedThisTime); 00256 if (newDropped) { 00257 //int newDropped2=cholesky_->factorize(diagonal_,rowsDroppedThisTime); 00258 //assert(!newDropped2); 00259 if (newDropped<0) { 00260 //replace dropped 00261 newDropped=-newDropped; 00262 //off 1 to allow for reset all 00263 newDropped--; 00264 //set all bits false 00265 cholesky_->resetRowsDropped(); 00266 } 00267 } 00268 delete [] rowsDroppedThisTime; 00269 if (cholesky_->status()) { 00270 std::cout << "bad cholesky?" <<std::endl; 00271 abort(); 00272 } 00273 } 00274 //set up for affine direction 00275 setupForSolve(0); 00276 double directionAccuracy=findDirectionVector(0); 00277 if (directionAccuracy>worstDirectionAccuracy_) { 00278 worstDirectionAccuracy_=directionAccuracy; 00279 } 00280 int phase=0; // predictor, corrector , primal dual 00281 // 0 - normal 00282 // 1 - second time around i.e. no need for first part 00283 // 2 - affine step only 00284 // 9 - to exit from while because of error (to go round again) 00285 // (9 also used to signal end of while (but then goodMove is true)) 00286 int recoveryMode=0; 00287 if (!goodMove) { 00288 recoveryMode=9; 00289 } 00290 if (goodMove&&useAffine) { 00291 recoveryMode=2; 00292 phase=0; 00293 } 00294 while (recoveryMode!=9) { 00295 goodMove=true; 00296 if (!recoveryMode) { 00297 findStepLength(phase); 00298 int nextNumber; //number of complementarity pairs 00299 double nextGap=complementarityGap(nextNumber,1); 00300 //if (complementarityGap_>1.0e-1&&worstDirectionAccuracy_<1.0e-5) { 00301 //wasif (complementarityGap_>1.0e-2*numberComplementarityPairs_) { 00302 if (complementarityGap_>1.0e-4*numberComplementarityPairs_) { 00303 //std::cout <<"predicted duality gap "<<nextGap<<std::endl; 00304 //double part1=nextGap/numberComplementarityPairs_; 00305 double part1=nextGap/numberComplementarityPairs_; 00306 double part2=nextGap/complementarityGap_; 00307 mu_=part1*part2*part2; 00308 } else { 00309 double phi; 00310 if (numberComplementarityPairs_<=500) { 00311 phi=pow(numberComplementarityPairs_,2); 00312 } else { 00313 phi=pow(numberComplementarityPairs_,1.5); 00314 if (phi<500.0*500.0) { 00315 phi=500.0*500.0; 00316 } 00317 } 00318 mu_=complementarityGap_/phi; 00319 //? could use gapO? 00320 //if small then should be stopping 00321 //if (mu_<1.0e-4/(numberComplementarityPairs_*qqqq)) { 00322 //mu_=1.0e-4/(numberComplementarityPairs_*qqqq); 00323 //? better to skip corrector? 00324 //} 00325 } 00326 //save information 00327 double product=affineProduct(); 00328 //can we do corrector step? 00329 double xx= complementarityGap_*(beta2-tau) +product; 00330 //std::cout<<"gap part "<< 00331 //complementarityGap_*(beta2-tau)<<" after adding product = "<<xx; 00332 if (xx>0.0) { 00333 double saveMu = mu_; 00334 double mu2=numberComplementarityPairs_; 00335 mu2=xx/mu2; 00336 if (mu2>mu_) { 00337 //std::cout<<" could increase to "<<mu2<<std::endl; 00338 //was mu2=mu2*0.25; 00339 mu2=mu2*0.99; 00340 if (mu2<mu_) { 00341 mu_=mu2; 00342 //std::cout<<" changing mu to "<<mu_<<std::endl; 00343 } else { 00344 //std::cout<<std::endl; 00345 } 00346 } else { 00347 //std::cout<<" should decrease to "<<mu2<<std::endl; 00348 mu_=0.5*mu2; 00349 std::cout<<" changing mu to "<<mu_<<std::endl; 00350 } 00351 handler_->message(CLP_BARRIER_MU,messages_) 00352 <<saveMu<<mu_ 00353 <<CoinMessageEol; 00354 } else { 00355 //std::cout<<" bad by any standards"<<std::endl; 00356 } 00357 if (complementarityGap_*(beta2-tau)+product-mu_*numberComplementarityPairs_<0.0) { 00358 doCorrector=false; 00359 double floatNumber = numberComplementarityPairs_; 00360 mu_=complementarityGap_/(floatNumber*floatNumber); 00361 //? if small we should be stopping 00362 //if (mu_<1.0e-4/(numberComplementarityPairs_*numberComplementarityPairs_)) { 00363 //mu_=1.0e-4/(totalVariables*totalVariables); 00364 //} 00365 handler_->message(CLP_BARRIER_INFO,messages_) 00366 <<"no corrector step" 00367 <<CoinMessageEol; 00368 phase=2; 00369 } else { 00370 phase=1; 00371 } 00372 } 00373 //set up for next step 00374 setupForSolve(phase); 00375 double directionAccuracy2=findDirectionVector(phase); 00376 if (directionAccuracy2>worstDirectionAccuracy_) { 00377 worstDirectionAccuracy_=directionAccuracy2; 00378 } 00379 double testValue=1.0e2*directionAccuracy; 00380 if (1.0e2*projectionTolerance_>testValue) { 00381 testValue=1.0e2*projectionTolerance_; 00382 } 00383 if (primalTolerance()>testValue) { 00384 testValue=primalTolerance(); 00385 } 00386 if (maximumRHSError_>testValue) { 00387 testValue=maximumRHSError_; 00388 } 00389 if (!recoveryMode) { 00390 if (directionAccuracy2>testValue&&numberIterations_>=-77) { 00391 goodMove=false; 00392 useAffine=true;//if bad accuracy 00393 doCorrector=false; 00394 recoveryMode=9; 00395 } 00396 } 00397 if (goodMove) { 00398 findStepLength(phase); 00399 if (numberIterations_>=-77) { 00400 goodMove=checkGoodMove(doCorrector); 00401 } else { 00402 goodMove=true; 00403 } 00404 if (!goodMove) { 00405 if (doCorrector) { 00406 doCorrector=false; 00407 double floatNumber = numberComplementarityPairs_; 00408 mu_=complementarityGap_/(floatNumber*floatNumber); 00409 handler_->message(CLP_BARRIER_INFO,messages_) 00410 <<" no corrector step - original move would be bad" 00411 <<CoinMessageEol; 00412 phase=2; 00413 recoveryMode=1; 00414 } else { 00415 // if any killed then do zero step and hope for best 00416 abort(); 00417 } 00418 } 00419 } 00420 //force leave 00421 if (goodMove) { 00422 recoveryMode=9; 00423 } 00424 } /* endwhile */ 00425 } /* endwhile */ 00426 numberFixed=updateSolution(); 00427 numberFixedTotal+=numberFixed; 00428 } /* endwhile */ 00429 if (savePi) { 00430 //std::cout<<"Restoring from iteration "<<saveIteration<<std::endl; 00431 CoinMemcpyN(savePi,numberRows_,dual_); 00432 CoinMemcpyN(savePrimal,numberTotal,solution_); 00433 delete [] savePi; 00434 delete [] savePrimal; 00435 } 00436 //recompute slacks 00437 // Split out solution 00438 CoinZeroN(rowActivity_,numberRows_); 00439 CoinMemcpyN(solution_,numberColumns_,columnActivity_); 00440 matrix_->times(1.0,columnActivity_,rowActivity_); 00441 //unscale objective 00442 multiplyAdd(NULL,numberTotal,0.0,cost_,scaleFactor_); 00443 multiplyAdd(NULL,numberRows_,0,dual_,scaleFactor_); 00444 CoinMemcpyN(cost_,numberColumns_,reducedCost_); 00445 matrix_->transposeTimes(-1.0,dual_,reducedCost_); 00446 CoinMemcpyN(reducedCost_,numberColumns_,dj_); 00447 checkSolution(); 00448 handler_->message(CLP_BARRIER_END,messages_) 00449 <<sumPrimalInfeasibilities_ 00450 <<sumDualInfeasibilities_ 00451 <<complementarityGap_ 00452 <<objectiveValue() 00453 <<CoinMessageEol; 00454 //std::cout<<"Absolute primal infeasibility at end "<<sumPrimalInfeasibilities_<<std::endl; 00455 //std::cout<<"Absolute dual infeasibility at end "<<sumDualInfeasibilities_<<std::endl; 00456 //std::cout<<"Absolute complementarity at end "<<complementarityGap_<<std::endl; 00457 //std::cout<<"Primal objective "<<objectiveValue()<<std::endl; 00458 //std::cout<<"maximum complementarity "<<worstComplementarity_<<std::endl; 00459 //delete all temporary regions 00460 deleteWorkingData(); 00461 return problemStatus_; 00462 } |