00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "BonChooseVariable.hpp"
00014
00015 #include "CouenneObject.hpp"
00016 #include "CouenneChooseStrong.hpp"
00017 #include "CouenneProblem.hpp"
00018 #include "CouenneProblemElem.hpp"
00019 #include "CouenneBranchingObject.hpp"
00020 #include "CouenneRecordBestSol.hpp"
00021
00022
00023 #define FM_SORT_STRONG
00024 #define FM_SEC_SORT_USEFUL
00025 #define USE_NOT_TRUSTED
00026
00027
00028
00029
00030
00031
00032
00033 using namespace Ipopt;
00034 using namespace Couenne;
00035
00036 const CouNumber estProdEps = 1e-6;
00037
00038 #ifdef COIN_HAS_NTY
00039 #include "Nauty.h"
00040 #endif
00041
00043 CouenneChooseStrong::CouenneChooseStrong (Bonmin::BabSetupBase &b, CouenneProblem* p, JnlstPtr jnlst) :
00044
00045 Bonmin::BonChooseVariable (b, b.continuousSolver()),
00046 problem_ (p),
00047 jnlst_ (jnlst),
00048 branchtime_ (0.) {
00049
00050 std::string s;
00051
00052 b.options () -> GetStringValue ("pseudocost_mult_lp", s, "couenne.");
00053 pseudoUpdateLP_ = (s == "yes");
00054
00055 b.options () -> GetStringValue ("estimate_select", s, "couenne.");
00056 estimateProduct_ = (s == "product");
00057
00058 b.options () -> GetStringValue ("trust_strong", s, "couenne.");
00059
00060
00061
00062 setTrustStrongForSolution (s == "yes");
00063 setTrustStrongForBound (s == "yes");
00064 }
00065
00067 CouenneChooseStrong::CouenneChooseStrong (const CouenneChooseStrong& rhs) :
00068 Bonmin::BonChooseVariable (rhs),
00069 problem_ (rhs.problem_),
00070 pseudoUpdateLP_ (rhs.pseudoUpdateLP_),
00071 estimateProduct_ (rhs.estimateProduct_),
00072 jnlst_ (rhs.jnlst_),
00073 branchtime_ (rhs.branchtime_)
00074 {}
00075
00077 CouenneChooseStrong::~CouenneChooseStrong()
00078 {if (branchtime_ > 1e-9) jnlst_ -> Printf (J_ERROR, J_BRANCHING, "Strong branching: total time %g\n", branchtime_);}
00079
00081 OsiChooseVariable *
00082 CouenneChooseStrong::clone() const
00083 {return new CouenneChooseStrong(*this);}
00084
00086 CouenneChooseStrong&
00087 CouenneChooseStrong::operator=(const CouenneChooseStrong & rhs)
00088 {
00089 if (this != &rhs) {
00090 Bonmin::BonChooseVariable::operator=(rhs);
00091 problem_ = rhs.problem_;
00092 pseudoUpdateLP_ = rhs.pseudoUpdateLP_;
00093 estimateProduct_ = rhs.estimateProduct_;
00094 jnlst_ = rhs.jnlst_;
00095 branchtime_ = rhs.branchtime_;
00096 }
00097 return *this;
00098 }
00099
00100
00101
00102
00103
00104
00105
00106 int CouenneChooseStrong::goodCandidate(OsiSolverInterface *solver,
00107 OsiBranchingInformation *info,
00108 OsiObject **object, const int iObject,
00109 const double prec) {
00110
00111 int vInd = object [iObject] -> columnNumber ();
00112
00113 if (vInd < 0) return 4;
00114
00115 bool varIsInt = solver -> isInteger (vInd);
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 int goodCand = 3;
00149
00150
00151
00152
00153 if((vInd >= 0) && varIsInt) {
00154 double vUp = solver->getColUpper()[vInd];
00155 double vLow = solver->getColLower()[vInd];
00156 double infoVal = info->solution_[vInd];
00157 double distToInt = fabs(infoVal - floor(infoVal + 0.5));
00158 if(distToInt > 0.5) {
00159 distToInt = 1 - distToInt;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 goodCand = 2;
00173 if(vUp > vLow + prec) {
00174 goodCand = 3;
00175 }
00176
00177 }
00178
00179 return(goodCand);
00180 }
00181
00182
00183 bool CouenneChooseStrong::saveBestCand(OsiObject **object, const int iObject,
00184 const double value,
00185 const double upEstimate,
00186 const double downEstimate,
00187 double &bestVal1,
00188 double &bestVal2, int &bestIndex,
00189 int &bestWay) {
00190 bool retval = false;
00191 if(value > bestVal1) {
00192 retval = true;
00193 bestVal1 = value;
00194 bestIndex = iObject;
00195 bestWay = upEstimate > downEstimate ? 0 : 1;
00196
00197 const OsiObject * obj = object[iObject];
00198 if (obj->preferredWay() >= 0 && obj->infeasibility()) {
00199 bestWay = obj->preferredWay();
00200 }
00201 }
00202 return(retval);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 int CouenneChooseStrong::chooseVariable (OsiSolverInterface * solver,
00222 OsiBranchingInformation *info,
00223 bool fixVariables) {
00224
00228
00229 problem_ -> domain () -> push
00230 (problem_ -> nVars (),
00231 info -> solution_,
00232 info -> lower_,
00233 info -> upper_);
00234
00235 #ifdef TRACE_STRONG2
00236 int pv = -1;
00237 if(problem_->doPrint_) {
00238 if(pv > -1) {
00239 printf("CCS: beg: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00240 pv, solver->getColSolution()[pv], solver->getColLower()[pv], solver->getColUpper()[pv]);
00241 printf("CCS: info: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00242 pv, info->solution_[pv], info->lower_[pv], info->upper_[pv]);
00243 printf("CCS: problem: lb: %10.4f ub: %10.4f\n",
00244 problem_->Lb(pv), problem_->Ub(pv));
00245 }
00246 }
00247 #endif
00248
00249 int retval;
00250 const double prec = problem_->getFeasTol();
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 bool isRoot = isRootNode(info);
00261 int numberStrong = numberStrong_;
00262
00263 if (isRoot) {
00264 numberStrong = numberStrongRoot_;
00265 }
00266
00267 if (numberUnsatisfied_) {
00268 int cardIndForPseudo = 0,
00269 *indForPseudo = new int[numberUnsatisfied_];
00270 OsiObject ** object = solver->objects();
00271 const double* upTotalChange = pseudoCosts_.upTotalChange();
00272 const double* downTotalChange = pseudoCosts_.downTotalChange();
00273 const int* upNumber = pseudoCosts_.upNumber();
00274 const int* downNumber = pseudoCosts_.downNumber();
00275 int numberBeforeTrusted = pseudoCosts_.numberBeforeTrusted();
00276
00277
00278 int numberLeft = CoinMin (numberStrong - numberStrongDone_, numberUnsatisfied_);
00279
00280 results_.clear();
00281
00282
00283
00284 int returnCode = 1;
00285
00286 int returnCodeSB = 0;
00287 bestObjectIndex_ = -1;
00288 bestWhichWay_ = -1;
00289 firstForcedObjectIndex_ = -1;
00290 firstForcedWhichWay_ =-1;
00291 double bestTrustedVal1 = -COIN_DBL_MAX;
00292 double bestTrustedVal2 = -COIN_DBL_MAX;
00293
00294 bool smallGap = false;
00295 bool sbObjPosImp = false;
00296
00297
00298
00299
00300 #ifdef USE_SMALL_GAP
00301 int objInd = problem_ -> Obj (0) -> Body () -> Index ();
00302 double lbGap = objInd >= 0 ? info -> lower_ [objInd] : problem_ -> Obj (0) -> Body () -> Value ();
00303 double ubGap = problem_ -> getCutOff ();
00304 double currentGap =
00305 (ubGap > COUENNE_INFINITY / 10 ||
00306 lbGap < -Couenne_large_bound / 10) ? 1e3 :
00307 fabs (ubGap - lbGap) / (1.e-3 + CoinMin (fabs (ubGap), fabs (lbGap)));
00308
00309 if(currentGap < 1e-3) {
00310 smallGap = true;
00311 }
00312 #endif
00313
00314 #ifdef TRACE_STRONG
00315 if((problem_->doPrint_) && (number_not_trusted_ > 0)) {
00316 printf("number_not_trusted: %d\n", number_not_trusted_);
00317 }
00318 #endif
00319
00320 for (int i=0;i<numberLeft;i++) {
00321 int iObject = list_[i];
00322 if (numberBeforeTrusted == 0||
00323 i < minNumberStrongBranch_ ||
00324 (
00325 only_pseudo_when_trusted_ && number_not_trusted_>0 ) ||
00326 ( !isRoot && (upNumber[iObject]<numberBeforeTrusted ||
00327 downNumber[iObject]<numberBeforeTrusted ))||
00328 ( isRoot && (!upNumber[iObject] && !downNumber[iObject])) ) {
00329
00330 #ifdef TRACE_STRONG
00331 if(problem_->doPrint_) {
00332 printf("Push object %d for strong branch\n", iObject);
00333 }
00334 #endif
00335 results_.push_back (Bonmin::HotInfo (solver, info, object, iObject));
00336 }
00337 else {
00338
00339 #ifdef TRACE_STRONG
00340 if(problem_->doPrint_) {
00341 printf("Use pseudo cost for object %d\n", iObject);
00342 }
00343 #endif
00344 indForPseudo[cardIndForPseudo] = iObject;
00345 cardIndForPseudo++;
00346 }
00347 }
00348
00349 int numberFixed=0;
00350
00351 if (results_.size() > 0) {
00352
00353
00354
00355
00356
00357 returnCodeSB = doStrongBranching (solver, info, results_.size(), 1);
00358
00359 if (bb_log_level_>=3) {
00360 const char* stat_msg[] = {"NOTDON", "FEAS", "INFEAS", "NOFINI"};
00361 message(SB_HEADER)<<CoinMessageEol;
00362 for (unsigned int i = 0; i< results_.size(); i++) {
00363 double up_change = results_[i].upChange();
00364 double down_change = results_[i].downChange();
00365 int up_status = results_[i].upStatus();
00366 int down_status = results_[i].downStatus();
00367 message(SB_RES)<<(int) i<<stat_msg[down_status+1]<<down_change
00368 <<stat_msg[up_status+1]<< up_change<< CoinMessageEol;
00369 }
00370 }
00371
00372 if (returnCodeSB >= 0 && returnCodeSB <= 2) {
00373 if(returnCodeSB > 0) {
00374 returnCode = 4;
00375 }
00376 else {
00377 returnCode = 0;
00378 }
00379 for (unsigned int i=0;i < results_.size (); i++) {
00380
00381 if((results_[i].upStatus() < 0) || (results_[i].downStatus() < 0))
00382 continue;
00383
00384
00385
00386
00387
00388 int iObject = results_[i].whichObject();
00389 const OsiObject * obj = object[iObject];
00390 int needBranch = goodCandidate(solver, info, object, iObject, prec);
00391
00393
00394 double upEstimate;
00395
00396 if (results_[i].upStatus()!=1) {
00397 assert (results_[i].upStatus()>=0);
00398 upEstimate = results_[i].upChange();
00399 }
00400 else {
00401
00402 if (info->cutoff_<1.0e50)
00403 upEstimate = 2.0*(info->cutoff_-info->objectiveValue_);
00404 else
00405 upEstimate = 2.0*fabs(info->objectiveValue_);
00406 if (firstForcedObjectIndex_ <0) {
00407
00408 firstForcedObjectIndex_ = iObject;
00409 firstForcedWhichWay_ =0;
00410 }
00411
00412 numberFixed++;
00413 if (fixVariables) {
00414 if(needBranch >= 2) {
00415
00416
00417 OsiBranchingObject * branch =
00418 obj->createBranch(solver, info, 0);
00419 branch -> branch (solver);
00420 delete branch;
00421 }
00422 }
00423 }
00424
00426
00427 double downEstimate;
00428
00429 if (results_[i].downStatus()!=1) {
00430 assert (results_[i].downStatus()>=0);
00431 downEstimate = results_[i].downChange();
00432 }
00433 else {
00434
00435 if (info->cutoff_<1.0e50)
00436 downEstimate = 2.0*(info->cutoff_-info->objectiveValue_);
00437 else
00438 downEstimate = 2.0*fabs(info->objectiveValue_);
00439 if (firstForcedObjectIndex_ <0) {
00440 firstForcedObjectIndex_ = iObject;
00441 firstForcedWhichWay_ =1;
00442 }
00443 numberFixed++;
00444 if (fixVariables) {
00445 if(needBranch >= 2) {
00446
00447
00448 OsiBranchingObject * branch =
00449 obj->createBranch(solver, info, 1);
00450 branch -> branch (solver);
00451 delete branch;
00452 }
00453 }
00454 }
00455
00456 double
00457 MAXMIN_CRITERION = maxminCrit (info),
00458 minVal, maxVal, value;
00459
00460 if (downEstimate < upEstimate) {
00461 minVal = downEstimate;
00462 maxVal = upEstimate;
00463 } else {
00464 minVal = upEstimate;
00465 maxVal = downEstimate;
00466 }
00467
00468 if(smallGap) {
00469 value = minVal;
00470 }
00471 else {
00472 value =
00473 estimateProduct_ ?
00474 ((estProdEps + minVal) * maxVal) :
00475 ( MAXMIN_CRITERION * minVal +
00476 (1.0 - MAXMIN_CRITERION) * maxVal);
00477 }
00478
00479 if((needBranch >= 3) &&
00480 saveBestCand(object, iObject, value, upEstimate, downEstimate,
00481 bestTrustedVal1,
00482 bestTrustedVal2, bestObjectIndex_, bestWhichWay_)) {
00483 if(returnCodeSB) {
00484 returnCode = 2;
00485 }
00486
00487 #ifdef USE_SMALL_GAP
00488 if(smallGap && (minVal > 1e-3)) {
00489 sbObjPosImp = true;
00490 }
00491 #endif
00492
00493 }
00494 }
00495 }
00496 else {
00497 if (returnCodeSB == 3) {
00498 if(bestObjectIndex_ < 0) {
00499
00500
00501 bestObjectIndex_ = list_[0];
00502 bestWhichWay_ = 0;
00503 returnCode = 0;
00504 }
00505 }
00506 else {
00507 returnCode = -1;
00508 }
00509 }
00510 #ifdef OLD_STYLE
00511 if(bestObjectIndex_ < 0) {
00512 bestObjectIndex_ = list_[0];
00513 }
00514 cardIndForPseudo = 0;
00515 #endif
00516 }
00517
00518 if((returnCodeSB != -1) &&
00519 ((returnCode != 0) || (!sbObjPosImp))) {
00520
00521
00522
00523
00524
00525
00526
00527 int bestObjectIndex2 = -1;
00528 int bestWhichWay2 = 0;
00529 double bestTrusted2Val1 = -COIN_DBL_MAX;
00530 double bestTrusted2Val2 = -COIN_DBL_MAX;
00531
00532 for(int ips=0; ips<cardIndForPseudo; ips++) {
00533 int iObject = indForPseudo[ips];
00534 const OsiObject * obj = object[iObject];
00535 int needBranch = goodCandidate(solver, info, object, iObject, prec);
00536
00537 double
00538 upEstimate = (upTotalChange [iObject] * obj -> upEstimate ()) / upNumber [iObject],
00539 downEstimate = (downTotalChange [iObject] * obj -> downEstimate ()) / downNumber [iObject],
00540 MAXMIN_CRITERION = maxminCrit (info),
00541 minVal, maxVal, value;
00542
00543 if (downEstimate < upEstimate) {
00544 minVal = downEstimate;
00545 maxVal = upEstimate;
00546 } else {
00547 minVal = upEstimate;
00548 maxVal = downEstimate;
00549 }
00550
00551 value =
00552 estimateProduct_ ?
00553 ((estProdEps + minVal) * maxVal) :
00554 ( MAXMIN_CRITERION * minVal +
00555 (1.0 - MAXMIN_CRITERION) * maxVal);
00556
00557
00558
00559 if(needBranch < 3) {
00560 if(saveBestCand(object, iObject, value,
00561 upEstimate, downEstimate,
00562 bestTrusted2Val1,
00563 bestTrusted2Val2, bestObjectIndex2,
00564 bestWhichWay2)) {
00565
00566 }
00567
00568 #ifdef TRACE_STRONG
00569 if(problem_->doPrint_) {
00570 printf("Object %d skip pseudocost\n", iObject);
00571 }
00572 #endif
00573 }
00574 else {
00575 if(saveBestCand(object, iObject, value,
00576 upEstimate, downEstimate,
00577 bestTrustedVal1,
00578 bestTrustedVal2, bestObjectIndex_, bestWhichWay_)) {
00579 if(returnCode == 1) {
00580
00581 returnCode = 0;
00582 }
00583
00584 returnCode = (returnCode ? 3 : 0);
00585
00586 }
00587
00588 #ifdef TRACE_STRONG
00589 if(problem_->doPrint_) {
00590 printf("Object %d use pseudocost\n", iObject);
00591 }
00592 #endif
00593 }
00594 }
00595
00596 if((bestObjectIndex_ < 0) && (bestObjectIndex2 >= 0)) {
00597 bestObjectIndex_ = bestObjectIndex2;
00598 bestWhichWay_ = bestWhichWay2;
00599 bestTrustedVal1 = bestTrusted2Val1;
00600 if(goodCandidate(solver, info, object,
00601 bestObjectIndex_, prec) != 4) {
00602 returnCode = 4;
00603 }
00604 else {
00605 returnCode = 3;
00606 }
00607 }
00608 }
00609
00610 int objectVarInd = -1;
00611 if(bestObjectIndex_ >= 0) {
00612 OsiObject * obj = object[bestObjectIndex_];
00613 obj->setWhichWay(bestWhichWay_);
00614
00615
00616
00617
00618
00619 objectVarInd = obj->columnNumber();
00620
00621
00622 message(BRANCH_VAR)<<bestObjectIndex_<< bestWhichWay_ <<CoinMessageEol;
00623
00624 #ifdef TRACE_STRONG
00625 if(problem_->doPrint_) {
00626 if(objectVarInd >= 0) {
00627 double vUb = solver->getColUpper()[objectVarInd];
00628 char strUb[400], strLb[400];
00629 if(vUb > 1e50) {
00630 sprintf(strUb, "+inf");
00631 }
00632 else {
00633 sprintf(strUb, "%f", vUb);
00634 }
00635 double vLb = solver->getColLower()[objectVarInd];
00636 if(vLb < -1e50) {
00637 sprintf(strLb, "-inf");
00638 }
00639 else {
00640 sprintf(strLb, "%f", vLb);
00641 }
00642 double vSolI = info->solution_[objectVarInd];
00643 double vSolS = solver->getColSolution()[objectVarInd];
00644 printf("Branch on object %d (var: %d): solInfo: %10.4f SolSolver: %10.4f low: %s up: %s\n",
00645 bestObjectIndex_, objectVarInd, vSolI, vSolS, strLb, strU
00646
00647 b);
00648 }
00649 else {
00650 printf("Branch on object %d (var: -1)\n", bestObjectIndex_);
00651 }
00652 }
00653 #endif
00654 }
00655 message(CHOSEN_VAR)<<bestObjectIndex_<<CoinMessageEol;
00656
00657 if((numberFixed==numberUnsatisfied_&&numberFixed) &&
00658 (goodCandidate(solver, info, object, bestObjectIndex_, prec) != 4)) {
00659 returnCode = 4;
00660 }
00661
00662 if((returnCode == 2) || (returnCode == 3)) {
00663 if((objectVarInd > -1) &&
00664 (goodCandidate(solver, info, object, bestObjectIndex_, prec) != 4)) {
00665
00666
00667
00668 returnCode = 4;
00669 }
00670 }
00671 retval = returnCode;
00672
00673 delete[] indForPseudo;
00674 }
00675 else {
00676 retval = 1;
00677 }
00678
00679
00680
00681
00682 #ifdef TRACE_STRONG2
00683 if(problem_->doPrint_) {
00684 if(pv > -1) {
00685 printf("CCS: end: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00686 pv, solver->getColSolution()[pv], solver->getColLower()[pv], solver->getColUpper()[pv]);
00687 printf("CCS: info: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
00688 pv, info->solution_[pv], info->lower_[pv], info->upper_[pv]);
00689 printf("CCS: problem: lb: %10.4f ub: %10.4f\n",
00690 problem_->Lb(pv), problem_->Ub(pv));
00691 }
00692 }
00693 #endif
00694
00695 #ifdef TRACE_STRONG
00696 if(problem_->doPrint_) {
00697 printf("CouenneChooseStrong::ChooseVariable(): retval: %d\n", retval);
00698 }
00699 #endif
00700
00701 problem_ -> domain () -> pop ();
00702
00703 return retval;
00704 }
00705
00706 void eliminateIntegerObjects (OsiSolverInterface *model);
00707 void eliminateIntegerObjects (CbcModel *model);
00708
00709
00710
00711
00712 int CouenneChooseStrong::setupList (OsiBranchingInformation *info, bool initialize) {
00713
00714 static bool
00715 firstCall = true,
00716 warned = false;
00717
00718 if (firstCall) {
00719
00720 eliminateIntegerObjects (const_cast <OsiSolverInterface *> (solver_));
00721 eliminateIntegerObjects (const_cast <OsiSolverInterface *> (info -> solver_));
00722
00723 firstCall = false;
00724 }
00725
00726 initialize = true;
00727
00728 problem_ -> domain () -> push
00729 (problem_ -> nVars (),
00730 info -> solution_,
00731 info -> lower_,
00732 info -> upper_);
00733
00734 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING,
00735 "----------------- (strong) setup list\n");
00736
00737 if (jnlst_ -> ProduceOutput (J_DETAILED, J_BRANCHING)) {
00738 for (int i=0; i<problem_ -> domain () -> current () -> Dimension (); i++)
00739 printf ("%4d %20.4g [%20.4g %20.4g]\n", i,
00740 info -> solution_ [i], info -> lower_ [i], info -> upper_ [i]);
00741 }
00742
00743 #ifdef TRACE_STRONG
00744 printf("Start CouenneChooseStrong::setupList()\n");
00745 OsiObject ** object = info->solver_->objects();
00746 if(problem_->doPrint_) {
00747 printObjViol(info);
00748 }
00749 #endif
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 int retval = gutsOfSetupList (info, initialize);
00764
00765 if (retval == 0) {
00766
00767 #ifdef FM_CHECKNLP2
00768 if(!(problem_->checkNLP2(info->solution_,
00769 info->objectiveValue_, true,
00770 false,
00771 true,
00772 problem_->getFeasTol()))) {
00773
00774 if (!warned) {
00775 printf("CouenneChooseStrong::setupList(): ### WARNING: checkNLP2() returns infeasible, no branching object selected\n");
00776 warned = true;
00777 }
00778 }
00779 #else
00780 double ckObj = info->objectiveValue_;
00781 if(!(problem_->checkNLP(info->solution_, ckObj, true))) {
00782 if (!warned) {
00783 printf("CouenneChooseStrong::setupList(): ### WARNING: checkNLP() returns infeasible, no branching object selected\n");
00784 warned = true;
00785 }
00786 }
00787 #endif
00788
00789 #ifdef FM_TRACE_OPTSOL
00790 #ifdef FM_CHECKNLP2
00791 problem_->getRecordBestSol()->update();
00792 #else
00793 problem_->getRecordBestSol()->update(info->solution_, problem_->nVars(),
00794 ckObj, problem_->getFeasTol());
00795 #endif
00796 #endif
00797 }
00798
00799 #ifdef TRACE_STRONG
00800 if(problem_->doPrint_) {
00801 printf("Strong list: (obj_ind var_ind priority useful viol)\n");
00802 printf("numberStrong: %d numberStrongRoot: %d retval: %d\n",
00803 numberStrong_, numberStrongRoot_, retval);
00804 for(int i=0; i<retval; i++) {
00805
00806 int objectInd = -1;
00807
00808
00809
00810
00811 objectInd = object[list_[i]]->columnNumber();
00812
00813
00814 int wayprint;
00815 double violprint = object[list_[i]]->infeasibility(info, wayprint);
00816 if(violprint < COIN_DBL_MAX / 100) {
00817 printf(" (%d %d %d %6.4f %6.4f)", list_[i], objectInd,
00818 object[list_[i]]->priority(), useful_[i],
00819 violprint);
00820 }
00821 else {
00822 printf(" (%d %d %d %6.4f +inf)", list_[i], objectInd,
00823 object[list_[i]]->priority(), useful_[i]);
00824 }
00825 printf("\n");
00826 }
00827 #endif
00828
00829
00830
00831
00832
00833
00834 jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING,
00835 "----------------- (strong) setup list done - %d infeasibilities\n", retval);
00836
00837 #if (defined TRACE_STRONG)
00838 printf("Done CouenneChooseStrong::setupList()\n");
00839 #endif
00840
00841 problem_ -> domain () -> pop ();
00842 return retval;
00843 }
00844
00845
00847 void CouenneChooseStrong::registerOptions (Ipopt::SmartPtr <Bonmin::RegisteredOptions> roptions) {
00848
00849 roptions -> AddStringOption6
00850 ("pseudocost_mult",
00851 "Multipliers of pseudocosts for estimating and update estimation of bound",
00852 "interval_br_rev",
00853
00854 "infeasibility", "infeasibility returned by object",
00855
00856 "projectDist", "distance between current LP point and resulting branches' LP points",
00857
00858 "interval_lp", "width of the interval between bound and current lp point",
00859 "interval_lp_rev", "similar to interval_lp, reversed",
00860
00861 "interval_br", "width of the interval between bound and branching point",
00862 "interval_br_rev", "similar to interval_br, reversed");
00863
00864 roptions -> AddStringOption2
00865 ("pseudocost_mult_lp",
00866 "Use distance between LP points to update multipliers of pseudocosts "
00867 "after simulating branching",
00868 "no",
00869 "yes", "",
00870 "no", "");
00871
00872 roptions -> AddStringOption2
00873 ("estimate_select",
00874 "How the min/max estimates of the subproblems' bounds are used in strong branching",
00875 "normal",
00876 "normal", "as usual in literature",
00877 "product", "use their product");
00878
00879 roptions -> AddStringOption2
00880 ("trust_strong",
00881 "Fathom strong branching LPs when their bound is above the cutoff",
00882 "yes",
00883 "yes", "",
00884 "no", "");
00885 }
00886
00887
00888
00889 bool CouenneChooseStrong::feasibleSolution (const OsiBranchingInformation * info,
00890 const double * solution,
00891 int numberObjects,
00892 const OsiObject ** objects) {
00893
00894 #ifdef FM_CHECKNLP2
00895 return problem_ -> checkNLP2 (solution, 0, false, true, true,
00896 problem_->getFeasTol());
00897 #else
00898 int indobj = problem_ -> Obj (0) -> Body () -> Index ();
00899 return problem_ -> checkNLP (solution, indobj >= 0 ? solution [indobj] : problem_ -> Obj (0) -> Body () -> Value ());
00900 #endif
00901 }
00902
00903
00904 void CouenneChooseStrong::printObjViol(OsiBranchingInformation *info) {
00905
00906 OsiObject ** object = info->solver_->objects();
00907 int numberObjects = info->solver_->numberObjects();
00908
00909 printf("CouenneChooseStrong::printObjViol(): Object violations: (obj_ind var_ind violation)");
00910 double maxViol = 0;
00911 double minPosViol = 1e50;
00912 for(int i=0; i<numberObjects; i++) {
00913
00914 int indVar = -1;
00915
00916
00917
00918
00919 indVar = object[i]->columnNumber();
00920
00921 int way;
00922 double value = object[i]->infeasibility(info,way);
00923
00924 maxViol = (value > maxViol ? value : maxViol);
00925 if(value > 0.0) {
00926 printf("(%d %d %f)", i, indVar, value);
00927 minPosViol = (value < minPosViol ? value : minPosViol);
00928 }
00929 }
00930 printf("\nmaxViol: %g minPosViol: %g\n", maxViol, minPosViol);
00931 }
00932
00933