00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CouenneAggrProbing.hpp"
00012 #include "CouenneProblemElem.hpp"
00013 #include "CouenneExprVar.hpp"
00014 #include "CouenneExprOpp.hpp"
00015
00016 #include "CouenneBab.hpp"
00017 #include "CouenneCutGenerator.hpp"
00018 #include <string>
00019
00020 #define COUENNE_AGGR_PROBING_FINITE_BOUND 1.0e+10
00021 #define COUENNE_AGGR_PROBING_MIN_INTERVAL 1.0e-2
00022 #define COUENNE_AGGR_PROBING_BND_RELAX COUENNE_EPS
00023
00024 using namespace Couenne;
00025
00026 CouenneAggrProbing::CouenneAggrProbing(CouenneSetup *setup,
00027 const Ipopt::SmartPtr<Ipopt::OptionsList> options)
00028 {
00029 couenne_ = setup;
00030 numCols_ = couenne_->couennePtr()->Problem()->nVars();
00031 maxTime_ = COIN_DBL_MAX;
00032 maxFailedSteps_ = 10;
00033 maxNodes_ = 1000;
00034 initCutoff_ = COUENNE_INFINITY;
00035 restoreCutoff_ = false;
00036
00037 }
00038
00039 CouenneAggrProbing::CouenneAggrProbing(const CouenneAggrProbing &rhs){
00040 couenne_ = new CouenneSetup(*rhs.couenne_);
00041 numCols_ = rhs.numCols_;
00042 maxTime_ = rhs.maxTime_;
00043 maxFailedSteps_ = rhs.maxFailedSteps_;
00044 maxNodes_ = rhs.maxNodes_;
00045 initCutoff_ = rhs.initCutoff_;
00046 restoreCutoff_ = rhs.restoreCutoff_;
00047 }
00048
00049 CouenneAggrProbing::~CouenneAggrProbing(){
00050 }
00051
00052 void CouenneAggrProbing::registerOptions(Ipopt::SmartPtr <Bonmin::RegisteredOptions> roptions) {
00053
00054 }
00055
00056 void CouenneAggrProbing::generateCuts(const OsiSolverInterface& solver,
00057 OsiCuts& cuts,
00058 const CglTreeInfo info) const {
00059
00060 }
00061
00062 double CouenneAggrProbing::getMaxTime() const {
00063 return maxTime_;
00064 }
00065
00066 void CouenneAggrProbing::setMaxTime(double value){
00067 maxTime_ = value;
00068 }
00069
00070 int CouenneAggrProbing::getMaxFailedSteps() const {
00071 return maxFailedSteps_;
00072 }
00073
00074 void CouenneAggrProbing::setMaxFailedSteps(int value){
00075 maxFailedSteps_ = value;
00076 }
00077
00078 int CouenneAggrProbing::getMaxNodes() const {
00079 return maxNodes_;
00080 }
00081
00082 void CouenneAggrProbing::setMaxNodes(int value){
00083 maxNodes_ = value;
00084 }
00085
00086 bool CouenneAggrProbing::getRestoreCutoff() const {
00087 return restoreCutoff_;
00088 }
00089
00090 void CouenneAggrProbing::setRestoreCutoff(bool value){
00091 restoreCutoff_ = value;
00092 }
00093
00094 double CouenneAggrProbing::probeVariable(int index, bool probeLower){
00095
00096
00097 OsiSolverInterface* nlp = couenne_->nonlinearSolver();
00098 OsiSolverInterface* lp = couenne_->continuousSolver();
00099 CouenneProblem* problem = couenne_->couennePtr()->Problem();
00100
00101
00102 double initUpper = lp->getColUpper()[index];
00103 double initLower = lp->getColLower()[index];
00104
00105 double* initLowerLp = new double[numCols_];
00106 double* initUpperLp = new double[numCols_];
00107
00108 memcpy(initLowerLp, lp->getColLower(), numCols_*sizeof(double));
00109 memcpy(initUpperLp, lp->getColUpper(), numCols_*sizeof(double));
00110
00111 if (initUpper < initLower + COUENNE_EPS){
00112
00113 return ((probeLower) ? initLower : initUpper);
00114 }
00115
00116
00117 int indobj = problem->Obj(0)->Body()->Index();
00118
00119
00120 double initCutoff = problem->Ub()[indobj];
00121
00122 double* initCutoffSol = NULL;
00123
00124 if (restoreCutoff_ && problem->getCutOff() < COUENNE_INFINITY){
00125 initCutoffSol = new double[numCols_];
00126 memcpy(initCutoffSol, problem->getCutOffSol(), numCols_*sizeof(double));
00127 }
00128
00129
00130 Bonmin::BabSetupBase::NodeComparison initNodeComparison =
00131 couenne_->nodeComparisonMethod();
00132 int initMaxNodes = couenne_->getIntParameter(Bonmin::BabSetupBase::MaxNodes);
00133 double initMaxTime = couenne_->getDoubleParameter(Bonmin::BabSetupBase::MaxTime);
00134 int initMaxSol = couenne_->getIntParameter(Bonmin::BabSetupBase::MaxSolutions);
00135 couenne_->setNodeComparisonMethod(Bonmin::BabSetupBase::bestBound);
00136
00137 couenne_->setIntParameter(Bonmin::BabSetupBase::MaxNodes, maxNodes_);
00138 couenne_->setIntParameter(Bonmin::BabSetupBase::MaxSolutions, COIN_INT_MAX);
00139 problem->setCheckAuxBounds(true);
00140
00142 Bonmin::BabSetupBase::HeuristicMethods heuristics = couenne_->heuristics();
00143 couenne_->heuristics().clear();
00144
00145 double currentBound = (probeLower) ? initLower : initUpper;
00146 double startTime = CoinCpuTime();
00147 int failedSteps = 0;
00148 double intervalSize = 0.0;
00149 double tryBound = 0.0;
00150
00151 int iter = 0;
00152
00153 if (probeLower)
00154 std::cout << "Probing lower on var " << index << std::endl;
00155 else
00156 std::cout << "Probing upper on var " << index << std::endl;
00157
00158 if ((fabs(currentBound) > COUENNE_AGGR_PROBING_FINITE_BOUND) &&
00159 ((probeLower && initUpper > -COUENNE_AGGR_PROBING_FINITE_BOUND) ||
00160 (!probeLower && initLower < COUENNE_AGGR_PROBING_FINITE_BOUND))){
00161
00162
00163
00164
00165 if (probeLower){
00166 tryBound = -COUENNE_AGGR_PROBING_FINITE_BOUND;
00167 lp->setColLower(index, currentBound);
00168 problem->Lb()[index] = currentBound;
00169 lp->setColUpper(index, tryBound);
00170 problem->Ub()[index] = tryBound;
00171 if (index < problem->nOrigVars()){
00172 nlp->setColLower(index, currentBound);
00173 nlp->setColUpper(index, tryBound);
00174 }
00175 }
00176 else{
00177 tryBound = COUENNE_AGGR_PROBING_FINITE_BOUND;
00178 lp->setColLower(index, tryBound);
00179 problem->Lb()[index] = tryBound;
00180 lp->setColUpper(index, currentBound);
00181 problem->Ub()[index] = currentBound;
00182 if (index < problem->nOrigVars()){
00183 nlp->setColLower(index, tryBound);
00184 nlp->setColUpper(index, currentBound);
00185 }
00186 }
00187
00189 couenne_->setDoubleParameter(Bonmin::BabSetupBase::MaxTime,
00190 CoinMin(maxTime_-(CoinCpuTime()-startTime),
00191 maxTime_*0.5));
00192
00193 if (restoreCutoff_){
00194 problem->resetCutOff(initCutoff);
00195 problem->Ub()[indobj] = initCutoff;
00196 problem->installCutOff();
00197 }
00198
00199 std::cout << "Iteration " << iter << ", current bound " << currentBound
00200 << ", try bound " << tryBound << std::endl;
00201
00203
00204
00205
00206 CouenneBab bb;
00207
00208 bb(couenne_);
00209 if (bb.model().isProvenInfeasible()){
00211 currentBound = tryBound;
00212 std::cout << "Probing succeeded; brought to finite" << std::endl;
00213 }
00214 else{
00216 std::cout << "Probing failed; still infinity, exit" << std::endl;
00217 }
00218 iter++;
00219 }
00220
00221
00222
00223
00224
00225 intervalSize = 0.1;
00226
00227 if (intervalSize < COUENNE_AGGR_PROBING_MIN_INTERVAL){
00228 intervalSize = COUENNE_AGGR_PROBING_MIN_INTERVAL;
00229 }
00230
00231 while ((fabs(currentBound) <= COUENNE_AGGR_PROBING_FINITE_BOUND) &&
00232 ((CoinCpuTime() - startTime) < maxTime_) &&
00233 (failedSteps < maxFailedSteps_) &&
00234 (intervalSize >= COUENNE_AGGR_PROBING_MIN_INTERVAL) &&
00235 iter < 100){
00236
00238 if (probeLower){
00239 tryBound = currentBound + intervalSize;
00240 if (tryBound > initUpper){
00241
00242
00243 tryBound = initUpper;
00244 }
00245 if (lp->isInteger(index)){
00246 tryBound = floor(tryBound);
00247 }
00248
00249 lp->setColLower(index, currentBound - COUENNE_AGGR_PROBING_BND_RELAX);
00250 problem->Lb()[index] = currentBound - COUENNE_AGGR_PROBING_BND_RELAX;
00251 lp->setColUpper(index, tryBound + COUENNE_AGGR_PROBING_BND_RELAX);
00252 problem->Ub()[index] = tryBound + COUENNE_AGGR_PROBING_BND_RELAX;
00253 if (index < problem->nOrigVars()){
00254 nlp->setColLower(index, currentBound - COUENNE_AGGR_PROBING_BND_RELAX);
00255 nlp->setColUpper(index, tryBound + COUENNE_AGGR_PROBING_BND_RELAX);
00256 }
00257 }
00258 else{
00259 tryBound = currentBound - intervalSize;
00260 if (tryBound < initLower){
00261
00262
00263 tryBound = initLower;
00264 }
00265 if (lp->isInteger(index)){
00266 tryBound = ceil(tryBound);
00267 }
00268
00269 lp->setColLower(index, tryBound - COUENNE_AGGR_PROBING_BND_RELAX);
00270 problem->Lb()[index] = tryBound - COUENNE_AGGR_PROBING_BND_RELAX;
00271 lp->setColUpper(index, currentBound + COUENNE_AGGR_PROBING_BND_RELAX);
00272 problem->Ub()[index] = currentBound + COUENNE_AGGR_PROBING_BND_RELAX;
00273 if (index < problem->nOrigVars()){
00274 nlp->setColLower(index, tryBound - COUENNE_AGGR_PROBING_BND_RELAX);
00275 nlp->setColUpper(index, currentBound + COUENNE_AGGR_PROBING_BND_RELAX);
00276 }
00277 }
00278
00279 lp->resolve();
00280 problem->domain()->push(numCols_, lp->getColSolution(),
00281 lp->getColLower(), lp->getColUpper());
00282
00284 couenne_->setDoubleParameter(Bonmin::BabSetupBase::MaxTime,
00285 CoinMin(maxTime_-(CoinCpuTime()-startTime),
00286 maxTime_*0.5));
00287
00288 if (restoreCutoff_){
00289 problem->Ub()[indobj] = initCutoff;
00290 problem->resetCutOff(initCutoff);
00291 problem->installCutOff();
00292 }
00293
00294 std::cout << "Iteration " << iter << ", current bound " << currentBound
00295 << ", try bound " << tryBound << std::endl;
00296
00298
00299
00300
00301 CouenneBab bb;
00302 bb(couenne_);
00303
00304 problem->domain()->pop();
00305
00306 double obj = 0.0;
00308 bool intervalSearched = (bb.model().isProvenOptimal() ||
00309 bb.model().isProvenInfeasible());
00310
00311 if ((!intervalSearched) ||
00312 (restoreCutoff_ &&
00313 problem->getCutOffSol() &&
00314 problem->checkNLP(problem->getCutOffSol(), obj, true))){
00316 if (lp->isInteger(index) && fabs(tryBound-currentBound) < 0.5){
00318 failedSteps = maxFailedSteps_;
00319 }
00320 else{
00321 intervalSize /= 2;
00322 }
00323 failedSteps++;
00324 std::cout << "Probing failed; shrinking interval" << std::endl;
00325 }
00326 else{
00331 if (lp->isInteger(index) && fabs(tryBound-currentBound) < 0.5){
00334 intervalSize = 1.0;
00335 }
00336 else{
00337 intervalSize *= 2;
00338 }
00339 currentBound = tryBound;
00340 if (lp->isInteger(index)){
00341 if (probeLower){
00342 currentBound += 1.0;
00343 }
00344 else {
00345 currentBound -= 1.0;
00346 }
00347 }
00348 failedSteps = 0;
00349 std::cout << "Probing succeeded; enlarging interval" << std::endl;
00350 }
00351
00352
00353
00354 if ((probeLower && fabs(currentBound-initUpper) < COUENNE_EPS) ||
00355 (!probeLower && fabs(currentBound-initLower) < COUENNE_EPS)){
00356 failedSteps = maxFailedSteps_;
00357 }
00358
00359
00360 if (restoreCutoff_){
00361 problem->Ub()[indobj] = initCutoff;
00362 problem->resetCutOff(initCutoff);
00363 problem->installCutOff();
00364 }
00365
00366 problem->domain()->pop();
00367
00368 iter++;
00369 }
00370
00373 lp->setColLower(initLowerLp);
00374 lp->setColUpper(initUpperLp);
00375 nlp->setColLower(initLowerLp);
00376 nlp->setColUpper(initUpperLp);
00377 memcpy(problem->Lb(), initLowerLp, numCols_*sizeof(double));
00378 memcpy(problem->Ub(), initUpperLp, numCols_*sizeof(double));
00379
00381 problem->setCheckAuxBounds(false);
00382
00383 couenne_->setNodeComparisonMethod(initNodeComparison);
00384 couenne_->setIntParameter(Bonmin::BabSetupBase::MaxSolutions, initMaxSol);
00385 couenne_->setIntParameter(Bonmin::BabSetupBase::MaxNodes, initMaxNodes);
00386 couenne_->setDoubleParameter(Bonmin::BabSetupBase::MaxTime, initMaxTime);
00387 couenne_->heuristics() = heuristics;
00388
00390 if (restoreCutoff_){
00391 problem->resetCutOff();
00392 problem->setCutOff(initCutoff, initCutoffSol);
00393 if (initCutoffSol){
00394 delete[] initCutoffSol;
00395 }
00396 }
00397
00398 delete[] initLowerLp;
00399 delete[] initUpperLp;
00400
00402 return currentBound;
00403
00404 }
00405
00406 double CouenneAggrProbing::probeVariable2(int index, bool probeLower){
00407
00408
00409
00410
00411 OsiSolverInterface* lp = couenne_->continuousSolver();
00412 CouenneProblem* problem = couenne_->couennePtr()->Problem();
00413
00414
00415 double initUpper = lp->getColUpper()[index];
00416 double initLower = lp->getColLower()[index];
00417
00418 if (initUpper < initLower + COUENNE_EPS){
00419
00420 return ((probeLower) ? initLower : initUpper);
00421 }
00422
00426 Bonmin::BabSetupBase::NodeComparison initNodeComparison =
00427 couenne_->nodeComparisonMethod();
00428 int initMaxNodes = couenne_->getIntParameter(Bonmin::BabSetupBase::MaxNodes);
00429 double initMaxTime = couenne_->getDoubleParameter(Bonmin::BabSetupBase::MaxTime);
00430 int initMaxSol = couenne_->getIntParameter(Bonmin::BabSetupBase::MaxSolutions);
00431 couenne_->setNodeComparisonMethod (Bonmin::BabSetupBase::bestBound);
00432 couenne_->setIntParameter(Bonmin::BabSetupBase::MaxNodes, maxNodes_);
00433 couenne_->setIntParameter(Bonmin::BabSetupBase::MaxSolutions, COIN_INT_MAX);
00434
00438 Bonmin::BabSetupBase::HeuristicMethods heuristics = couenne_->heuristics();
00439 couenne_->heuristics().clear();
00440
00442 double* initLpObj = new double[numCols_];
00443 memcpy(initLpObj, lp->getObjCoefficients(), numCols_*sizeof(double));
00444 expression* initProbObj = problem->Obj(0)->Body();
00445
00446 double* newLpObj = new double[numCols_];
00447 memset(newLpObj, 0, numCols_*sizeof(double));
00448
00449
00450 expression* extraVar = NULL;
00451
00452 lp->writeLp("before");
00453
00454 if (probeLower){
00455 std::cout << "Probing LOWER" << std::endl;
00456
00457 newLpObj[index] = 1.0;
00458 lp->setObjective(newLpObj);
00459
00460 lp->writeLp("lower");
00461
00462
00463 problem->Obj(0)->Body(problem->Variables()[index]);
00464
00465
00466
00467
00468 }
00469 else{
00470
00471
00472
00473
00474
00475 int extraCol = numCols_;
00476 lp->setObjective(newLpObj);
00477 lp->addCol(0, NULL, NULL, -initUpper, -initLower, 1.0);
00478
00479
00480 int rowIndices[2] = {index, extraCol};
00481 double rowElements[2] = {1.0, 1.0};
00482 lp->addRow(2, rowIndices, rowElements, 0.0, 0.0);
00483 lp->resolve();
00484
00485
00486 extraVar = problem->addVariable(lp->isInteger(index), NULL);
00487
00488
00489 problem->Obj(0)->Body(extraVar);
00490
00491
00492
00493
00494
00495 lp->writeLp("upper");
00496 }
00497
00498 couenne_->setNodeComparisonMethod (Bonmin::BabSetupBase::bestBound);
00499 couenne_->setIntParameter(Bonmin::BabSetupBase::MaxNodes, maxNodes_);
00500 couenne_->setDoubleParameter(Bonmin::BabSetupBase::MaxTime,
00501 maxTime_);
00502
00503
00504
00505
00506 CouenneBab bb;
00507 bb(couenne_);
00508
00509 double bestBound = bb.model().getBestPossibleObjValue();
00510
00511 std::cout << "Obtained bound: " << bb.model().getBestPossibleObjValue() << std::endl;
00512
00513
00515 couenne_->setNodeComparisonMethod (initNodeComparison);
00516 couenne_->setIntParameter(Bonmin::BabSetupBase::MaxNodes, initMaxNodes);
00517 couenne_->setDoubleParameter(Bonmin::BabSetupBase::MaxTime, initMaxTime);
00518 couenne_->setIntParameter(Bonmin::BabSetupBase::MaxSolutions, initMaxSol);
00519 couenne_->heuristics() = heuristics;
00520
00521 if (!probeLower){
00522 int extra = lp->getNumCols()-1;
00523 lp->deleteCols(1, &extra);
00524 extra = lp->getNumRows()-1;
00525 lp->deleteRows(1, &extra);
00526 problem->Variables().pop_back();
00527 delete extraVar;
00528
00529 }
00530
00531 lp->setObjective(initLpObj);
00532 problem->Obj(0)->Body(initProbObj);
00533
00534 delete[] initLpObj;
00535 delete[] newLpObj;
00536
00537 return ((probeLower) ? bestBound : -bestBound);
00538
00539 }