00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "CouenneObject.hpp"
00014 #include "BonChooseVariable.hpp"
00015 #include "CouenneChooseStrong.hpp"
00016 #include "CouenneProblem.hpp"
00017 #include "CouenneProblemElem.hpp"
00018 #include "CouenneBranchingObject.hpp"
00019
00020 #include "CouenneRecordBestSol.hpp"
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 using namespace Ipopt;
00032 using namespace Couenne;
00033
00034 const CouNumber estProdEps = 1e-6;
00035
00036
00038 CouenneChooseStrong::CouenneChooseStrong (Bonmin::BabSetupBase &b, CouenneProblem* p, JnlstPtr jnlst) :
00039
00040 Bonmin::BonChooseVariable (b, b.continuousSolver()),
00041 problem_ (p),
00042 jnlst_ (jnlst),
00043 branchtime_ (0.) {
00044
00045 std::string s;
00046
00047 b.options () -> GetStringValue ("pseudocost_mult_lp", s, "couenne.");
00048 pseudoUpdateLP_ = (s == "yes");
00049
00050 b.options () -> GetStringValue ("estimate_select", s, "couenne.");
00051 estimateProduct_ = (s == "product");
00052
00053 b.options () -> GetStringValue ("trust_strong", s, "couenne.");
00054
00055
00056
00057 setTrustStrongForSolution (s == "yes");
00058 setTrustStrongForBound (s == "yes");
00059 }
00060
00062 CouenneChooseStrong::CouenneChooseStrong (const CouenneChooseStrong& rhs) :
00063 Bonmin::BonChooseVariable (rhs),
00064 problem_ (rhs.problem_),
00065 pseudoUpdateLP_ (rhs.pseudoUpdateLP_),
00066 estimateProduct_ (rhs.estimateProduct_),
00067 jnlst_ (rhs.jnlst_),
00068 branchtime_ (rhs.branchtime_)
00069 {}
00070
00072 CouenneChooseStrong::~CouenneChooseStrong()
00073 {if (branchtime_ > 1e-9) jnlst_ -> Printf (J_ERROR, J_BRANCHING, "Strong branching: total time %g\n", branchtime_);}
00074
00076 OsiChooseVariable *
00077 CouenneChooseStrong::clone() const
00078 {return new CouenneChooseStrong(*this);}
00079
00081 CouenneChooseStrong&
00082 CouenneChooseStrong::operator=(const CouenneChooseStrong & rhs)
00083 {
00084 if (this != &rhs) {
00085 Bonmin::BonChooseVariable::operator=(rhs);
00086 problem_ = rhs.problem_;
00087 pseudoUpdateLP_ = rhs.pseudoUpdateLP_;
00088 estimateProduct_ = rhs.estimateProduct_;
00089 jnlst_ = rhs.jnlst_;
00090 branchtime_ = rhs.branchtime_;
00091 }
00092 return *this;
00093 }
00094
00095
00096 int CouenneChooseStrong::goodCandidate(OsiSolverInterface *solver,
00097 OsiBranchingInformation *info,
00098 OsiObject **object, const int iObject,
00099 const double prec) {
00100 CouenneObject *co = dynamic_cast <CouenneObject *>(object[iObject]);
00101 OsiSimpleInteger *simpl = dynamic_cast <OsiSimpleInteger *>(object[iObject]);
00102
00103 int vInd = -1;
00104 bool varIsInt = false;
00105 if(co) {
00106 vInd = co->Reference()->Index();
00107 if(vInd >= 0) {
00108 varIsInt = co->Reference()->isInteger();
00109 }
00110 }
00111 else {
00112 if(simpl) {
00113 vInd = object[iObject]->columnNumber();
00114 varIsInt = true;
00115 }
00116 else {
00117
00118
00119
00120
00121
00122
00123
00124 return 3;
00125 }
00126 }
00127
00128 int goodCand = 3;
00129
00130
00131
00132
00133 if((vInd >= 0) && varIsInt) {
00134 double vUp = solver->getColUpper()[vInd];
00135 double vLow = solver->getColLower()[vInd];
00136 double infoVal = info->solution_[vInd];
00137 double distToInt = fabs(infoVal - floor(infoVal + 0.5));
00138 if(distToInt > 0.5) {
00139 distToInt = 1 - distToInt;
00140 }
00141 if(simpl) {
00142 goodCand = 0;
00143 if((distToInt > info->integerTolerance_) &&
00144 (vUp > vLow + prec)) {
00145 goodCand = 3;
00146 if((vUp + prec < infoVal) || (infoVal < vLow - prec)) {
00147 goodCand = 1;
00148 }
00149 }
00150 }
00151 if(co) {
00152 goodCand = 2;
00153 if(vUp > vLow + prec) {
00154 goodCand = 3;
00155 }
00156 }
00157 }
00158
00159 return(goodCand);
00160 }
00161
00162
00163 bool CouenneChooseStrong::saveBestCand(OsiObject **object, const int iObject,
00164 const double value,
00165 const double upEstimate,
00166 const double downEstimate,
00167 double &bestVal1,
00168 double &bestVal2, int &bestIndex,
00169 int &bestWay) {
00170 bool retval = false;
00171 if(value > bestVal1) {
00172 retval = true;
00173 bestVal1 = value;
00174 bestIndex = iObject;
00175 bestWay = upEstimate > downEstimate ? 0 : 1;
00176
00177 const OsiObject * obj = object[iObject];
00178 if (obj->preferredWay() >= 0 && obj->infeasibility()) {
00179 bestWay = obj->preferredWay();
00180 }
00181 }
00182 return(retval);
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 int CouenneChooseStrong::chooseVariable (OsiSolverInterface * solver,
00200 OsiBranchingInformation *info,
00201 bool fixVariables) {
00202
00206
00207 problem_ -> domain () -> push
00208 (problem_ -> nVars (),
00209 info -> solution_,
00210 info -> lower_,
00211 info -> upper_);
00212
00213 #ifdef TRACE_STRONG2
00214 int pv = -1;
00215 if(problem_->doPrint_) {
00216 if(pv > -1) {
00217 printf("CCS: beg: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00218 pv, solver->getColSolution()[pv], solver->getColLower()[pv], solver->getColUpper()[pv]);
00219 printf("CCS: info: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00220 pv, info->solution_[pv], info->lower_[pv], info->upper_[pv]);
00221 printf("CCS: problem: lb: %10.4f ub: %10.4f\n",
00222 problem_->Lb(pv), problem_->Ub(pv));
00223 }
00224 }
00225 #endif
00226
00227 int retval;
00228 const double prec = problem_->getFeasTol();
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 bool isRoot = isRootNode(info);
00239 int numberStrong = numberStrong_;
00240 if (isRoot) {
00241 numberStrong = CoinMax(numberStrong_, numberStrongRoot_);
00242 }
00243 if (numberUnsatisfied_) {
00244 int cardIndForPseudo = 0, *indForPseudo = new int[numberUnsatisfied_];
00245 OsiObject ** object = solver->objects();
00246 const double* upTotalChange = pseudoCosts_.upTotalChange();
00247 const double* downTotalChange = pseudoCosts_.downTotalChange();
00248 const int* upNumber = pseudoCosts_.upNumber();
00249 const int* downNumber = pseudoCosts_.downNumber();
00250 int numberBeforeTrusted = pseudoCosts_.numberBeforeTrusted();
00251 int numberLeft = CoinMin(numberStrong -numberStrongDone_,numberUnsatisfied_);
00252 results_.clear();
00253 int returnCode = 0;
00254 int returnCodeSB = 0;
00255 bestObjectIndex_ = -1;
00256 bestWhichWay_ = -1;
00257 firstForcedObjectIndex_ = -1;
00258 firstForcedWhichWay_ =-1;
00259 double bestTrustedVal1 = -COIN_DBL_MAX;
00260 double bestTrustedVal2 = -COIN_DBL_MAX;
00261
00262 bool smallGap = false;
00263 bool sbObjPosImp = false;
00264
00265
00266
00267
00268 #ifdef USE_SMALL_GAP
00269 int objInd = problem_ -> Obj (0) -> Body () -> Index ();
00270 double lbGap = objInd >= 0 ? info -> lower_ [objInd] : problem_ -> Obj (0) -> Body () -> Value ();
00271 double ubGap = problem_ -> getCutOff ();
00272 double currentGap =
00273 (ubGap > COUENNE_INFINITY / 10 ||
00274 lbGap < -Couenne_large_bound / 10) ? 1e3 :
00275 fabs (ubGap - lbGap) / (1.e-3 + CoinMin (fabs (ubGap), fabs (lbGap)));
00276
00277 if(currentGap < 1e-3) {
00278 smallGap = true;
00279 }
00280 #endif
00281
00282 #ifdef TRACE_STRONG
00283 if((problem_->doPrint_) && (number_not_trusted_ > 0)) {
00284 printf("number_not_trusted: %d\n", number_not_trusted_);
00285 }
00286 #endif
00287
00288 for (int i=0;i<numberLeft;i++) {
00289 int iObject = list_[i];
00290 if (numberBeforeTrusted == 0||
00291 i < minNumberStrongBranch_ ||
00292 (
00293 only_pseudo_when_trusted_ && number_not_trusted_>0 ) ||
00294 ( !isRoot && (upNumber[iObject]<numberBeforeTrusted ||
00295 downNumber[iObject]<numberBeforeTrusted ))||
00296 ( isRoot && (!upNumber[iObject] && !downNumber[iObject])) ) {
00297
00298 #ifdef TRACE_STRONG
00299 if(problem_->doPrint_) {
00300 printf("Push object %d for strong branch\n", iObject);
00301 }
00302 #endif
00303 results_.push_back(Bonmin::HotInfo(solver, info,
00304 object, iObject));
00305 }
00306 else {
00307
00308 #ifdef TRACE_STRONG
00309 if(problem_->doPrint_) {
00310 printf("Use pseudo cost for object %d\n", iObject);
00311 }
00312 #endif
00313 indForPseudo[cardIndForPseudo] = iObject;
00314 cardIndForPseudo++;
00315 }
00316 }
00317
00318 int numberFixed=0;
00319
00320 if (results_.size() > 0) {
00321
00322
00323 returnCodeSB = doStrongBranching (solver, info, results_.size(), 1);
00324
00325 if (bb_log_level_>=3) {
00326 const char* stat_msg[] = {"NOTDON", "FEAS", "INFEAS", "NOFINI"};
00327 message(SB_HEADER)<<CoinMessageEol;
00328 for (unsigned int i = 0; i< results_.size(); i++) {
00329 double up_change = results_[i].upChange();
00330 double down_change = results_[i].downChange();
00331 int up_status = results_[i].upStatus();
00332 int down_status = results_[i].downStatus();
00333 message(SB_RES)<<(int) i<<stat_msg[down_status+1]<<down_change
00334 <<stat_msg[up_status+1]<< up_change<< CoinMessageEol;
00335 }
00336 }
00337
00338 if (returnCodeSB >= 0 && returnCodeSB <= 2) {
00339 if(returnCodeSB > 0) {
00340 returnCode = 4;
00341 }
00342 else {
00343 returnCode = 0;
00344 }
00345 for (unsigned int i=0;i < results_.size (); i++) {
00346
00347 if((results_[i].upStatus() < 0) || (results_[i].downStatus() < 0))
00348 continue;
00349
00350
00351 if((results_[i].upStatus() < 0) || (results_[i].downStatus() < 0)) {
00352 continue;
00353 }
00354
00355 int iObject = results_[i].whichObject();
00356 const OsiObject * obj = object[iObject];
00357 int needBranch = goodCandidate(solver, info, object, iObject, prec);
00358
00360
00361 double upEstimate;
00362
00363 if (results_[i].upStatus()!=1) {
00364 assert (results_[i].upStatus()>=0);
00365 upEstimate = results_[i].upChange();
00366 }
00367 else {
00368
00369 if (info->cutoff_<1.0e50)
00370 upEstimate = 2.0*(info->cutoff_-info->objectiveValue_);
00371 else
00372 upEstimate = 2.0*fabs(info->objectiveValue_);
00373 if (firstForcedObjectIndex_ <0) {
00374
00375 firstForcedObjectIndex_ = iObject;
00376 firstForcedWhichWay_ =0;
00377 }
00378
00379 numberFixed++;
00380 if (fixVariables) {
00381 if(needBranch >= 2) {
00382
00383
00384 OsiBranchingObject * branch =
00385 obj->createBranch(solver, info, 0);
00386 branch -> branch (solver);
00387 delete branch;
00388 }
00389 }
00390 }
00391
00393
00394 double downEstimate;
00395
00396 if (results_[i].downStatus()!=1) {
00397 assert (results_[i].downStatus()>=0);
00398 downEstimate = results_[i].downChange();
00399 }
00400 else {
00401
00402 if (info->cutoff_<1.0e50)
00403 downEstimate = 2.0*(info->cutoff_-info->objectiveValue_);
00404 else
00405 downEstimate = 2.0*fabs(info->objectiveValue_);
00406 if (firstForcedObjectIndex_ <0) {
00407 firstForcedObjectIndex_ = iObject;
00408 firstForcedWhichWay_ =1;
00409 }
00410 numberFixed++;
00411 if (fixVariables) {
00412 if(needBranch >= 2) {
00413
00414
00415 OsiBranchingObject * branch =
00416 obj->createBranch(solver, info, 1);
00417 branch -> branch (solver);
00418 delete branch;
00419 }
00420 }
00421 }
00422
00423 double
00424 MAXMIN_CRITERION = maxminCrit (info),
00425 minVal, maxVal, value;
00426
00427 if (downEstimate < upEstimate) {
00428 minVal = downEstimate;
00429 maxVal = upEstimate;
00430 } else {
00431 minVal = upEstimate;
00432 maxVal = downEstimate;
00433 }
00434
00435 if(smallGap) {
00436 value = minVal;
00437 }
00438 else {
00439 value =
00440 estimateProduct_ ?
00441 ((estProdEps + minVal) * maxVal) :
00442 ( MAXMIN_CRITERION * minVal +
00443 (1.0 - MAXMIN_CRITERION) * maxVal);
00444 }
00445
00446 if((needBranch == 3) &&
00447 saveBestCand(object, iObject, value, upEstimate, downEstimate,
00448 bestTrustedVal1,
00449 bestTrustedVal2, bestObjectIndex_, bestWhichWay_)) {
00450 if(returnCodeSB) {
00451 returnCode = 2;
00452 }
00453
00454 #ifdef USE_SMALL_GAP
00455 if(smallGap && (minVal > 1e-3)) {
00456 sbObjPosImp = true;
00457 }
00458 #endif
00459
00460 }
00461 }
00462 }
00463 else {
00464 if (returnCodeSB == 3) {
00465 if(bestObjectIndex_ < 0) {
00466
00467
00468 bestObjectIndex_ = list_[0];
00469 bestWhichWay_ = 0;
00470 returnCode = 0;
00471 }
00472 }
00473 else {
00474 returnCode = -1;
00475 }
00476 }
00477 #ifdef OLD_STYLE
00478 if(bestObjectIndex_ < 0) {
00479 bestObjectIndex_ = list_[0];
00480 }
00481 cardIndForPseudo = 0;
00482 #endif
00483 }
00484
00485 if((returnCodeSB != -1) &&
00486 ((returnCode != 0) || (!sbObjPosImp))) {
00487
00488
00489
00490
00491
00492
00493
00494 int bestObjectIndex2 = -1;
00495 int bestWhichWay2 = 0;
00496 double bestTrusted2Val1 = -COIN_DBL_MAX;
00497 double bestTrusted2Val2 = -COIN_DBL_MAX;
00498
00499 for(int ips=0; ips<cardIndForPseudo; ips++) {
00500 int iObject = indForPseudo[ips];
00501 const OsiObject * obj = object[iObject];
00502 int needBranch = goodCandidate(solver, info, object, iObject, prec);
00503
00504 double
00505 upEstimate = (upTotalChange[iObject]*obj->upEstimate())/upNumber[iObject],
00506 downEstimate = (downTotalChange[iObject]*obj->downEstimate())/downNumber[iObject],
00507 MAXMIN_CRITERION = maxminCrit (info),
00508 minVal, maxVal, value;
00509
00510 if (downEstimate < upEstimate) {
00511 minVal = downEstimate;
00512 maxVal = upEstimate;
00513 } else {
00514 minVal = upEstimate;
00515 maxVal = downEstimate;
00516 }
00517
00518 value =
00519 estimateProduct_ ?
00520 ((estProdEps + minVal) * maxVal) :
00521 ( MAXMIN_CRITERION * minVal +
00522 (1.0 - MAXMIN_CRITERION) * maxVal);
00523
00524
00525
00526 if(needBranch != 3) {
00527 if(saveBestCand(object, iObject, value,
00528 upEstimate, downEstimate,
00529 bestTrusted2Val1,
00530 bestTrusted2Val2, bestObjectIndex2,
00531 bestWhichWay2)) {
00532
00533 }
00534
00535 #ifdef TRACE_STRONG
00536 if(problem_->doPrint_) {
00537 printf("Object %d skip pseudocost\n", iObject);
00538 }
00539 #endif
00540 }
00541 else {
00542 if(saveBestCand(object, iObject, value,
00543 upEstimate, downEstimate,
00544 bestTrustedVal1,
00545 bestTrustedVal2, bestObjectIndex_, bestWhichWay_)) {
00546 returnCode = (returnCode ? 3 : 0);
00547
00548 }
00549
00550 #ifdef TRACE_STRONG
00551 if(problem_->doPrint_) {
00552 printf("Object %d use pseudocost\n", iObject);
00553 }
00554 #endif
00555 }
00556 }
00557
00558 delete[] indForPseudo;
00559
00560 if((bestObjectIndex_ < 0) && (bestObjectIndex2 >= 0)) {
00561 bestObjectIndex_ = bestObjectIndex2;
00562 bestWhichWay_ = bestWhichWay2;
00563 bestTrustedVal1 = bestTrusted2Val1;
00564 returnCode = 4;
00565 }
00566 }
00567
00568 int objectVarInd = -1;
00569 if(bestObjectIndex_ >= 0) {
00570 OsiObject * obj = object[bestObjectIndex_];
00571 obj->setWhichWay(bestWhichWay_);
00572 CouenneObject *co = dynamic_cast <CouenneObject *>(object[bestObjectIndex_]);
00573 if(co) {
00574 objectVarInd = co->Reference()->Index();
00575 }
00576 else {
00577 objectVarInd = obj->columnNumber();
00578 }
00579
00580 message(BRANCH_VAR)<<bestObjectIndex_<< bestWhichWay_ <<CoinMessageEol;
00581
00582 #ifdef TRACE_STRONG
00583 if(problem_->doPrint_) {
00584 if(objectVarInd >= 0) {
00585 double vUb = solver->getColUpper()[objectVarInd];
00586 double vLb = solver->getColLower()[objectVarInd];
00587 double vSolI = info->solution_[objectVarInd];
00588 double vSolS = solver->getColSolution()[objectVarInd];
00589 printf("Branch on object %d (var: %d): solInfo: %10.4f SolSolver: %10.4f low: %10.4f up: %10.4f\n",
00590 bestObjectIndex_, objectVarInd, vSolI, vSolS, vLb, vUb);
00591 }
00592 else {
00593 printf("Branch on object %d (var: -1)\n", bestObjectIndex_);
00594 }
00595 }
00596 #endif
00597 }
00598 message(CHOSEN_VAR)<<bestObjectIndex_<<CoinMessageEol;
00599
00600 if (numberFixed==numberUnsatisfied_&&numberFixed)
00601 returnCode=4;
00602
00603 if((returnCode == 2) || (returnCode == 3)) {
00604 if((objectVarInd > -1) &&
00605 (goodCandidate(solver, info, object, bestObjectIndex_, prec) != 2)) {
00606
00607
00608
00609 returnCode = 4;
00610 }
00611 }
00612 retval = returnCode;
00613 }
00614 else {
00615 retval = 1;
00616 }
00617
00618
00619
00620
00621 #ifdef TRACE_STRONG2
00622 if(problem_->doPrint_) {
00623 if(pv > -1) {
00624 printf("CCS: end: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00625 pv, solver->getColSolution()[pv], solver->getColLower()[pv], solver->getColUpper()[pv]);
00626 printf("CCS: info: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00627 pv, info->solution_[pv], info->lower_[pv], info->upper_[pv]);
00628 printf("CCS: problem: lb: %10.4f ub: %10.4f\n",
00629 problem_->Lb(pv), problem_->Ub(pv));
00630 }
00631 }
00632 #endif
00633
00634 #ifdef TRACE_STRONG
00635 if(problem_->doPrint_) {
00636 printf("CouenneChooseStrong::ChooseVariable(): retval: %d\n", retval);
00637 }
00638 #endif
00639
00640 problem_ -> domain () -> pop ();
00641
00642 return retval;
00643 }
00644
00645
00646
00647
00648 int CouenneChooseStrong::setupList (OsiBranchingInformation *info, bool initialize) {
00649 static bool warned = false;
00650
00651 initialize = true;
00652
00653 problem_ -> domain () -> push
00654 (problem_ -> nVars (),
00655 info -> solution_,
00656 info -> lower_,
00657 info -> upper_);
00658
00659 #ifdef COIN_HAS_NTY
00660
00661 if (problem_ -> orbitalBranching ()) {
00662
00663 problem_ -> ChangeBounds (info -> lower_,
00664 info -> upper_,
00665 problem_ -> nVars ());
00666
00667 problem_ -> Compute_Symmetry();
00668 }
00669
00670 #endif
00671
00672
00673 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING,
00674 "----------------- (strong) setup list\n");
00675
00676 if (jnlst_ -> ProduceOutput (J_DETAILED, J_BRANCHING)) {
00677 for (int i=0; i<problem_ -> domain () -> current () -> Dimension (); i++)
00678 printf ("%4d %20.4g [%20.4g %20.4g]\n", i,
00679 info -> solution_ [i], info -> lower_ [i], info -> upper_ [i]);
00680 }
00681
00682 #ifdef TRACE_STRONG
00683 OsiObject ** object = info->solver_->objects();
00684 #endif
00685
00686 #ifdef TRACE_STRONG
00687 if(problem_->doPrint_) {
00688 printObjViol(info);
00689 }
00690 #endif
00691
00692
00693
00694
00695
00696 int retval = gutsOfSetupList(info, initialize);
00697
00698 if(retval == 0) {
00699
00700 #ifdef FM_CHECKNLP2
00701 if(!(problem_->checkNLP2(info->solution_,
00702 info->objectiveValue_, true,
00703 false,
00704 true,
00705 problem_->getFeasTol()))) {
00706
00707 if (!warned) {
00708 printf("CouenneChooseStrong::setupList(): ### WARNING: checkNLP2() returns infeasible, no branching object selected\n");
00709 warned = true;
00710 }
00711 }
00712 #else
00713 double ckObj = info->objectiveValue_;
00714 if(!(problem_->checkNLP(info->solution_, ckObj, true))) {
00715 if (!warned) {
00716 printf("CouenneChooseStrong::setupList(): ### WARNING: checkNLP() returns infeasible, no branching object selected\n");
00717 warned = true;
00718 }
00719 }
00720 #endif
00721
00722 #ifdef FM_TRACE_OPTSOL
00723 #ifdef FM_CHECKNLP2
00724 problem_->getRecordBestSol()->update();
00725 #else
00726 problem_->getRecordBestSol()->update(info->solution_, problem_->nVars(),
00727 ckObj, problem_->getFeasTol());
00728 #endif
00729 #endif
00730 }
00731
00732 #ifdef TRACE_STRONG
00733 if(problem_->doPrint_) {
00734 printf("Strong list: (obj_ind var_ind priority useful)\n");
00735 printf("numberStrong: %d numberStrongRoot: %d retval: %d\n",
00736 numberStrong_, numberStrongRoot_, retval);
00737 for(int i=0; i<retval; i++) {
00738 CouenneObject *co = dynamic_cast <CouenneObject *>(object[list_[i]]);
00739 int objectInd = -1;
00740 if(co) {
00741 objectInd = co->Reference()->Index();
00742 }
00743 else {
00744 objectInd = object[list_[i]]->columnNumber();
00745 }
00746 printf(" (%d %d %d %6.4f)", list_[i], objectInd,
00747 object[list_[i]]->priority(), useful_[i]);
00748 }
00749 printf("\n");
00750 }
00751 #endif
00752
00753
00754 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING,
00755 "----------------- (strong) setup list done - %d infeasibilities\n", retval);
00756
00757 problem_ -> domain () -> pop ();
00758 return retval;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 int CouenneChooseStrong::gutsOfSetupList(OsiBranchingInformation *info,
00796 bool initialize)
00797 {
00798 if (numberBeforeTrustedList_ < 0) {
00799 number_not_trusted_ = 1;
00800 printf("CouenneChooseStrong::gutsOfSetupList(): Did not think we were using this; Please double check ...\n");
00801 exit(1);
00802 return OsiChooseVariable::setupList(info, initialize);
00803 }
00804 if (initialize) {
00805 status_=-2;
00806 delete [] goodSolution_;
00807 bestObjectIndex_=-1;
00808 numberStrongDone_=0;
00809 numberStrongIterations_ = 0;
00810 numberStrongFixed_ = 0;
00811 goodSolution_ = NULL;
00812 goodObjectiveValue_ = COIN_DBL_MAX;
00813 number_not_trusted_=0;
00814 }
00815 else {
00816 throw CoinError(CNAME,"setupList","Should not be called with initialize==false");
00817 }
00818 numberOnList_=0;
00819 numberUnsatisfied_=0;
00820 int numberObjects = solver_->numberObjects();
00821 assert (numberObjects);
00822 if (numberObjects>pseudoCosts_.numberObjects()) {
00823
00824
00825
00826
00827
00828 int saveNumberBeforeTrusted = pseudoCosts_.numberBeforeTrusted();
00829 pseudoCosts_.initialize(numberObjects);
00830 pseudoCosts_.setNumberBeforeTrusted(saveNumberBeforeTrusted);
00831 }
00832 int bestPriority = COIN_INT_MAX;
00833 int i;
00834 #ifdef FM_SORT_STRONG
00835 int numStr = numberStrong_;
00836 if(isRootNode(info)) {
00837 numStr = numberStrongRoot_;
00838 }
00839 int maximumStrong = CoinMin(numStr, numberObjects) ;
00840 int lastPrio = problem_->getLastPrioSort();
00841 int card_vPriority = 0;
00842 int posEnd_vPriority = numberObjects;
00843 double *vPriority = new double[numberObjects];
00844 double *infeasVal = new double[numberObjects];
00845 int max_most_fra = setup_pseudo_frac_ > 0. ? (int)floor(setup_pseudo_frac_*(double)maximumStrong): 0;
00846 if (setup_pseudo_frac_ > 0.) {
00847 max_most_fra = CoinMax(1, max_most_fra);
00848 }
00849 #else
00850 int putOther = numberObjects;
00851 double check = -COIN_DBL_MAX;
00852 int checkIndex = 0;
00853 int maximumStrong = CoinMin(CoinMax(numberStrong_,numberStrongRoot_),
00854 numberObjects) ;
00855 for (i=0;i<numberObjects;i++) {
00856 list_[i]=-1;
00857 useful_[i]=0.0;
00858 }
00859
00860 int* list2 = NULL;
00861 double* useful2 = NULL;
00862 double check2 = -COIN_DBL_MAX;
00863 int checkIndex2=0;
00864 int max_most_fra = setup_pseudo_frac_ > 0. ? (int)floor(setup_pseudo_frac_*(double)maximumStrong): 0;
00865 if (setup_pseudo_frac_ > 0.) {
00866 max_most_fra = CoinMax(1, max_most_fra);
00867 }
00868 if (max_most_fra) {
00869 list2 = new int[max_most_fra];
00870 useful2 = new double[max_most_fra];
00871 for (i=0;i<max_most_fra;i++) {
00872 list2[i]=-1;
00873 useful2[i]=0.0;
00874 }
00875 }
00876 #endif
00877
00878 #ifdef FM_CHECK
00879 const double* upTotalChange = pseudoCosts_.upTotalChange();
00880 const double* downTotalChange = pseudoCosts_.downTotalChange();
00881 int pseudoNum = pseudoCosts_.numberObjects();
00882 for(i=0; i<pseudoNum; i++) {
00883 if(isnan(upTotalChange[i]) || isinf(upTotalChange[i])) {
00884 printf("CouenneChooseStrong::gutsOfSetupList(): upTotalChange[%d]: not a number or infinite\n", i);
00885 exit(1);
00886 }
00887 if(isnan(downTotalChange[i]) || isinf(downTotalChange[i])) {
00888 printf("CouenneChooseStrong::gutsOfSetupList(): downTotalChange[%d]: not a number or infinite\n", i);
00889 exit(1);
00890 }
00891 }
00892 #endif
00893
00894 OsiObject ** object = info->solver_->objects();
00895 double upMultiplier, downMultiplier;
00896 computeMultipliers(upMultiplier, downMultiplier);
00897
00898
00899 bool feasible = true;
00900 const double MAXMIN_CRITERION = maxminCrit(info);
00901
00902 bool firstPass = false;
00903
00904
00905 while(numberOnList_ == 0) {
00906 for(i=0;i<numberObjects;i++) {
00907 int way;
00908 double value = object[i]->infeasibility(info, way);
00909
00910 #ifdef FM_SORT_STRONG
00911 infeasVal[i] = value;
00912 #endif
00913
00914 double lbForInfeas = 0.0;
00915 if(value > lbForInfeas) {
00916 numberUnsatisfied_++;
00917 if(value >= 1e50) {
00918
00919 feasible=false;
00920 break;
00921 }
00922 int priorityLevel = object[i]->priority();
00923
00924 #ifdef FM_SORT_STRONG
00925 if(priorityLevel < bestPriority) {
00926 bestPriority = priorityLevel;
00927 }
00928 if(priorityLevel > lastPrio) {
00929 posEnd_vPriority--;
00930 vPriority[posEnd_vPriority] = priorityLevel;
00931 list_[posEnd_vPriority] = i;
00932 }
00933 else {
00934 vPriority[card_vPriority] = priorityLevel;
00935 list_[card_vPriority] = i;
00936 card_vPriority++;
00937 }
00938 #else
00939
00940 if(priorityLevel < bestPriority) {
00941 for (int j=maximumStrong-1; j>=0; j--) {
00942 if(list_[j] >= 0) {
00943 int iObject = list_[j];
00944 list_[j]=-1;
00945 useful_[j]=0.0;
00946 list_[--putOther]=iObject;
00947 }
00948 }
00949 maximumStrong = CoinMin(maximumStrong,putOther);
00950 bestPriority = priorityLevel;
00951 check = -COIN_DBL_MAX;
00952 checkIndex = 0;
00953 check2 = -COIN_DBL_MAX;
00954 checkIndex2 = 0;
00955 number_not_trusted_ = 0;
00956 if(max_most_fra > 0) {
00957 for(int j=0; j<max_most_fra; j++) {
00958 list2[j]=-1;
00959 useful2[j]=0.0;
00960 }
00961 }
00962 }
00963 if(priorityLevel == bestPriority) {
00964
00965 double value2;
00966 value = computeUsefulness(MAXMIN_CRITERION,
00967 upMultiplier, downMultiplier, value,
00968 object[i], i, value2);
00969 if(value > check) {
00970
00971 int iObject = list_[checkIndex];
00972 if(iObject >= 0) {
00973 assert (list_[putOther-1]<0);
00974 list_[--putOther]=iObject;
00975 }
00976 list_[checkIndex]=i;
00977 assert (checkIndex<putOther);
00978 useful_[checkIndex]=value;
00979
00980 check=COIN_DBL_MAX;
00981 maximumStrong = CoinMin(maximumStrong,putOther);
00982 for (int j=0; j<maximumStrong; j++) {
00983 if(list_[j]>=0) {
00984 if (useful_[j]<check) {
00985 check=useful_[j];
00986 checkIndex=j;
00987 }
00988 }
00989 else {
00990 check=0.0;
00991 checkIndex = j;
00992 break;
00993 }
00994 }
00995 }
00996 else {
00997
00998 assert (list_[putOther-1]<0);
00999 list_[--putOther]=i;
01000 maximumStrong = CoinMin(maximumStrong,putOther);
01001 }
01002
01003 if((max_most_fra > 0) && (value2 > check2)) {
01004
01005 number_not_trusted_++;
01006 list2[checkIndex2]=i;
01007 useful2[checkIndex2]=value2;
01008
01009 check2=COIN_DBL_MAX;
01010 for(int j=0; j<max_most_fra; j++) {
01011 if(list2[j] >= 0) {
01012 if(useful2[j] < check2) {
01013 check2=useful2[j];
01014 checkIndex2=j;
01015 }
01016 }
01017 else {
01018 check2=0.0;
01019 checkIndex2 = j;
01020 break;
01021 }
01022 }
01023 }
01024 }
01025 else {
01026
01027
01028 assert (list_[putOther-1]<0);
01029 list_[--putOther]=i;
01030 maximumStrong = CoinMin(maximumStrong,putOther);
01031 }
01032 #endif
01033 }
01034 }
01035
01036 #ifdef FM_SORT_STRONG
01037
01038 #ifdef FM_CHECK
01039 if(card_vPriority - posEnd_vPriority + numberObjects != numberUnsatisfied_) {
01040 printf("CouenneChooseStrong::gutsOfSetupList(): ### ERROR: card_vPriority: %d posEnd_vPriority: %d numberUnsatisfied: %d numberObjects: %d\n",
01041 card_vPriority, posEnd_vPriority, numberUnsatisfied_, numberObjects);
01042 exit(1);
01043 }
01044 #endif
01045
01046 numberOnList_ = 0;
01047 if(feasible) {
01048 int card_smallerThanPrio = card_vPriority;
01049 if(posEnd_vPriority > card_vPriority) {
01050 for(i=posEnd_vPriority; i<numberObjects; i++) {
01051 list_[card_vPriority] = list_[i];
01052 list_[i] = -1;
01053 vPriority[card_vPriority] = vPriority[i];
01054 card_vPriority++;
01055 }
01056 }
01057 else {
01058 card_vPriority = numberUnsatisfied_;
01059 }
01060
01061 int sortFrom = 0;
01062 int sortUpTo = card_smallerThanPrio;
01063 if(card_smallerThanPrio < maximumStrong) {
01064 sortFrom = card_smallerThanPrio;
01065 sortUpTo = card_vPriority;
01066 }
01067 if(card_vPriority > 0) {
01068 numberOnList_ = (card_vPriority < maximumStrong ? card_vPriority : maximumStrong);
01069
01070 #ifdef FM_ALWAYS_SORT
01071 bool alwaysSort = true;
01072 #else
01073 bool alwaysSort = false;
01074 #endif
01075 if(alwaysSort) {
01076 sortFrom = 0;
01077 sortUpTo = card_vPriority;
01078 }
01079 if((sortUpTo > maximumStrong) || alwaysSort){
01080
01081 CoinSort_2(vPriority + sortFrom, vPriority + sortUpTo,
01082 list_ + sortFrom);
01083 }
01084 for(i=0; i<card_vPriority; i++) {
01085 int indObj = list_[i];
01086 double value = 0, value2;
01087 value = computeUsefulness(MAXMIN_CRITERION,
01088 upMultiplier, downMultiplier, value,
01089 object[indObj], indObj, value2);
01090
01091 #ifdef OLD_USEFULLNESS
01092 useful_[i] = -value;
01093 #else
01094 if ((sortCrit_ & 1) == 0) {
01095 useful_[i] = -value;
01096 }
01097 else {
01098 useful_[i] = value;
01099 }
01100 #endif
01101
01102 #ifdef USE_NOT_TRUSTED
01103 if(value2 < -COIN_DBL_MAX / 10) {
01104 infeasVal[indObj] = -COIN_DBL_MAX;
01105 }
01106 #endif
01107 }
01108
01109 #ifdef USE_NOT_TRUSTED
01110
01111 if((card_vPriority > maximumStrong) &&
01112 (vPriority[maximumStrong] < bestPriority + COUENNE_EPS)) {
01113
01114
01115 int cardFrac = 0;
01116 int *fracInd = new int[card_vPriority];
01117
01118 double *fracVal = new double[card_vPriority];
01119
01120
01121 for(i=0; i<card_vPriority; i++) {
01122 int indObj = list_[i];
01123 if(vPriority[i] < bestPriority + COUENNE_EPS) {
01124 if(infeasVal[indObj] > -COIN_DBL_MAX/10) {
01125 fracInd[cardFrac] = i;
01126 fracVal[cardFrac] = -infeasVal[indObj];
01127 cardFrac++;
01128 }
01129 }
01130 }
01131 if(max_most_fra > 0) {
01132
01133
01134 if(cardFrac > max_most_fra) {
01135 CoinSort_2(fracVal, fracVal+cardFrac, fracInd);
01136 }
01137 for(i=0; i<cardFrac; i++) {
01138 useful_[fracInd[i]] =
01139 -1e150*(1. + infeasVal[list_[fracInd[i]]]);
01140 number_not_trusted_++;
01141 if(i == max_most_fra - 1) {
01142 break;
01143 }
01144 }
01145 }
01146 delete[] fracInd;
01147 delete[] fracVal;
01148 }
01149 #endif
01150 }
01151
01152 #ifdef FM_SEC_SORT_USEFUL
01153 CoinSort_2(useful_, useful_+card_vPriority, list_);
01154 #else
01155 #ifdef FM_ALWAYS_SORT
01156 int from = 0, upto = 1;
01157 while(upto < card_vPriority) {
01158 while(vPriority[upto] == vPriority[from]) {
01159 upto++;
01160 if(upto == card_vPriority) {
01161 break;
01162 }
01163 }
01164 CoinSort_2(useful_+from, useful_+upto, list_+from);
01165 from = upto;
01166 upto = from+1;
01167 }
01168 #else
01169 if(sortUpTo > maximumStrong) {
01170
01171
01172 int from = maximumStrong-1, upto = maximumStrong;
01173 int msPrio = vPriority[maximumStrong-1];
01174 problem_->setLastPrioSort(msPrio);
01175 while((from > -1) && (vPriority[from] == msPrio)) {
01176 from--;
01177 }
01178 from++;
01179 while((upto < sortUpTo) && (vPriority[upto] == msPrio)) {
01180 upto++;
01181 }
01182
01183
01184 CoinSort_2(useful_+from, useful_+upto, list_+from);
01185 }
01186
01187 #endif
01188
01189 #ifdef FM_CHECK
01190
01191 double ckPrio = (card_vPriority < numberUnsatisfied_ ?
01192 vPriority[card_vPriority] : 100000);
01193 double ckUse = (card_vPriority < numberUnsatisfied_ ?
01194 useful_[card_vPriority] : 100000);
01195 for(i=0; i<card_vPriority; i++) {
01196 int indObj = list_[i];
01197 if(object[indObj]->priority() > ckPrio + 1e-3) {
01198 printf("CouenneChooseStrong::gutsOfSetupList(): ### ERROR: object[%d]->priority(): %d > ckPrio: %d\n",
01199 indObj, object[indObj]->priority(), ckPrio);
01200 exit(1);
01201 }
01202 if(fabs(object[indObj]->priority() - ckPrio) < 1e-3) {
01203 if(useful_[i] > ckUse + 1e-3) {
01204 printf("CouenneChooseStrong::gutsOfSetupList(): ### ERROR: object[%d]->useful: %f > ckUse: %d\n",
01205 indObj, useful_[i], ckUse);
01206 exit(1);
01207 }
01208 }
01209 }
01210 for(i=card_vPriority; i<numberUnsatisfied_; i++) {
01211 int indObj = list_[i];
01212 if(object[indObj]->priority() < ckPrio - 1e-3) {
01213 printf("CouenneChooseStrong::gutsOfSetupList(): ### ERROR: object[%d]->priority(): %d < ckPrio: %d\n",
01214 indObj, object[indObj]->priority(), ckPrio);
01215 exit(1);
01216 }
01217 if(fabs(object[indObj]->priority() - ckPrio) < 1e-3) {
01218 if(useful_[i] < ckUse - 1e-3) {
01219 printf("CouenneChooseStrong::gutsOfSetupList(): ### ERROR: object[%d]->useful: %f < ckUse: %d\n",
01220 indObj, useful_[i], ckUse);
01221 exit(1);
01222 }
01223 }
01224 }
01225 #endif
01226 #endif
01227 }
01228 else {
01229 numberUnsatisfied_ = -1;
01230 }
01231 #else
01232
01233 numberOnList_=0;
01234 if (feasible) {
01235 maximumStrong = CoinMin(maximumStrong,putOther);
01236 for (i=0;i<maximumStrong;i++) {
01237 if (list_[i]>=0) {
01238 #ifdef OLD_USEFULLNESS
01239 list_[numberOnList_]=list_[i];
01240 useful_[numberOnList_++]=-useful_[i];
01241
01242 #else
01243 list_[numberOnList_]=list_[i];
01244 if ((sortCrit_ & 1) == 0) {
01245 useful_[numberOnList_++]=-useful_[i];
01246 }
01247 else useful_[numberOnList_++] = useful_[i];
01248 #endif
01249 message(CANDIDATE_LIST2)<<numberOnList_-1
01250 <<list_[numberOnList_-1]<<numberOnList_-1<<useful_[numberOnList_-1]
01251 <<CoinMessageEol;
01252 }
01253 }
01254 if (numberOnList_) {
01255 int tmp_on_list = 0;
01256 if (max_most_fra > 0 && numberOnList_ >= maximumStrong) {
01257
01258
01259 number_not_trusted_=0;
01260 for (i=0;i<max_most_fra;i++) {
01261 if (list2[i]>=0) {
01262 list2[number_not_trusted_] = list2[i];
01263 useful2[number_not_trusted_++] = useful2[i];
01264 message(CANDIDATE_LIST3)<<number_not_trusted_-1
01265 <<list2[number_not_trusted_-1]<<number_not_trusted_-1
01266 <<useful2[number_not_trusted_-1]<<CoinMessageEol;
01267 }
01268 }
01269 if (number_not_trusted_) {
01270 CoinSort_2(list_,list_+numberOnList_,useful_);
01271 CoinSort_2(list2,list2+number_not_trusted_,useful2);
01272 int i1=0;
01273 int i2=0;
01274 for (i=0; i<numberObjects; i++) {
01275 bool found1 = (list_[i1]==i);
01276 bool found2 = (list2[i2]==i);
01277 if (found1 && found2) {
01278
01279 #ifdef OLD_USEFULLNESS
01280 useful_[i1] = 1e150*(1.+useful2[i2]);
01281 #else
01282 useful_[i1] = -1e150*(1.+useful2[i2]);
01283 #endif
01284 list2[i2] = -1;
01285 }
01286 if (found1) i1++;
01287 if (found2) i2++;
01288 if (i2==max_most_fra) break;
01289 }
01290 for (i=0; i<number_not_trusted_; i++) {
01291 if (list2[i] >= 0) {
01292 list_[numberOnList_+tmp_on_list] = list2[i];
01293
01294 #ifdef OLD_USEFULLNESS
01295 useful_[numberOnList_+tmp_on_list] = 1e150*(1.+useful2[i]);
01296 #else
01297 useful_[numberOnList_+tmp_on_list] = -1e150*(1.+useful2[i]);
01298 #endif
01299 tmp_on_list++;
01300 }
01301 }
01302 }
01303 }
01304
01305 CoinSort_2(useful_,useful_+numberOnList_+tmp_on_list,list_);
01306
01307 i = numberOnList_;
01308 for (;putOther<numberObjects;putOther++)
01309 list_[i++]=list_[putOther];
01310 assert (i==numberUnsatisfied_);
01311 if (!CoinMax(numberStrong_,numberStrongRoot_))
01312 numberOnList_=0;
01313 }
01314 }
01315 else {
01316
01317 numberUnsatisfied_=-1;
01318 }
01319 #endif
01320
01321 if(!firstPass) {
01322 break;
01323 }
01324 firstPass = false;
01325 }
01326
01327 #ifdef TRACE_STRONG
01328 if(problem_->doPrint_) {
01329 printf("numberStrong_: %d maximumStrong: %d\n",
01330 numberStrong_, maximumStrong);
01331 }
01332 #endif
01333
01334 #ifdef FM_SORT_STRONG
01335 delete [] vPriority;
01336 delete [] infeasVal;
01337 #else
01338 delete [] list2;
01339 delete [] useful2;
01340 #endif
01341
01342
01343 info->defaultDual_ = -1.0;
01344 delete [] info->usefulRegion_;
01345 delete [] info->indexRegion_;
01346
01347 int way;
01348 if (bb_log_level_>3) {
01349
01350 for (int i=0; i<numberOnList_; i++){
01351 message(CANDIDATE_LIST)<<i<< list_[i]<< i<< useful_[i]
01352 <<object[list_[i]]->infeasibility(info,way)
01353 <<CoinMessageEol;
01354 }
01355 }
01356
01357
01358
01359 if(numberUnsatisfied_ == -1) {
01360 return(-1);
01361 }
01362 return numberOnList_;
01363 }
01364
01365
01367 void CouenneChooseStrong::registerOptions (Ipopt::SmartPtr <Bonmin::RegisteredOptions> roptions) {
01368
01369 roptions -> AddStringOption6
01370 ("pseudocost_mult",
01371 "Multipliers of pseudocosts for estimating and update estimation of bound",
01372 "interval_br_rev",
01373
01374 "infeasibility", "infeasibility returned by object",
01375
01376 "projectDist", "distance between current LP point and resulting branches' LP points",
01377
01378 "interval_lp", "width of the interval between bound and current lp point",
01379 "interval_lp_rev", "similar to interval_lp, reversed",
01380
01381 "interval_br", "width of the interval between bound and branching point",
01382 "interval_br_rev", "similar to interval_br, reversed");
01383
01384 roptions -> AddStringOption2
01385 ("pseudocost_mult_lp",
01386 "Use distance between LP points to update multipliers of pseudocosts "
01387 "after simulating branching",
01388 "no",
01389 "yes", "",
01390 "no", "");
01391
01392 roptions -> AddStringOption2
01393 ("estimate_select",
01394 "How the min/max estimates of the subproblems' bounds are used in strong branching",
01395 "normal",
01396 "normal", "as usual in literature",
01397 "product", "use their product");
01398
01399 roptions -> AddStringOption2
01400 ("trust_strong",
01401 "Fathom strong branching LPs when their bound is above the cutoff",
01402 "yes",
01403 "yes", "",
01404 "no", "");
01405 }
01406
01407
01408
01409 bool CouenneChooseStrong::feasibleSolution (const OsiBranchingInformation * info,
01410 const double * solution,
01411 int numberObjects,
01412 const OsiObject ** objects) {
01413
01414 #ifdef FM_CHECKNLP2
01415 return problem_ -> checkNLP2 (solution, 0, false, true, true,
01416 problem_->getFeasTol());
01417 #else
01418 int indobj = problem_ -> Obj (0) -> Body () -> Index ();
01419 return problem_ -> checkNLP (solution, indobj >= 0 ? solution [indobj] : problem_ -> Obj (0) -> Body () -> Value ());
01420 #endif
01421 }
01422
01423
01424 void CouenneChooseStrong::printObjViol(OsiBranchingInformation *info) {
01425
01426 OsiObject ** object = info->solver_->objects();
01427 int numberObjects = info->solver_->numberObjects();
01428
01429 printf("CouenneChooseStrong::printObjViol(): Object violations: (obj_ind var_ind violation)");
01430 double maxViol = 0;
01431 double minPosViol = 1e50;
01432 for(int i=0; i<numberObjects; i++) {
01433 CouenneObject *co = dynamic_cast <CouenneObject *>(object[i]);
01434 int indVar = -1;
01435 if(co) {
01436 indVar = co->Reference()->Index();
01437 }
01438 else {
01439 indVar = object[i]->columnNumber();
01440 }
01441 int way;
01442 double value = object[i]->infeasibility(info,way);
01443 maxViol = (value > maxViol ? value : maxViol);
01444 if(value > 0.0) {
01445 printf("(%d %d %f)", i, indVar, value);
01446 minPosViol = (value < minPosViol ? value : minPosViol);
01447 }
01448 }
01449 printf("\nmaxViol: %g minPosViol: %g\n", maxViol, minPosViol);
01450
01451 }
01452
01453