23 #define FM_SORT_STRONG
24 #define FM_SEC_SORT_USEFUL
25 #define USE_NOT_TRUSTED
33 using namespace Ipopt;
34 using namespace Couenne;
45 Bonmin::BonChooseVariable (b, b.continuousSolver()),
52 b.
options () -> GetStringValue (
"pseudocost_mult_lp", s,
"couenne.");
55 b.
options () -> GetStringValue (
"estimate_select", s,
"couenne.");
58 b.
options () -> GetStringValue (
"trust_strong", s,
"couenne.");
62 setTrustStrongForSolution (s ==
"yes");
63 setTrustStrongForBound (s ==
"yes");
68 Bonmin::BonChooseVariable (rhs),
69 problem_ (rhs.problem_),
70 pseudoUpdateLP_ (rhs.pseudoUpdateLP_),
71 estimateProduct_ (rhs.estimateProduct_),
73 branchtime_ (rhs.branchtime_)
107 OsiBranchingInformation *
info,
108 OsiObject **
object,
const int iObject,
111 int vInd =
object [iObject] -> columnNumber ();
113 if (vInd < 0)
return 4;
115 bool varIsInt = solver ->
isInteger (vInd);
153 if((vInd >= 0) && varIsInt) {
154 double vUp = solver->getColUpper()[vInd];
155 double vLow = solver->getColLower()[vInd];
156 double infoVal = info->solution_[vInd];
157 double distToInt = fabs(infoVal - floor(infoVal + 0.5));
158 if(distToInt > 0.5) {
159 distToInt = 1 - distToInt;
173 if(vUp > vLow + prec) {
185 const double upEstimate,
186 const double downEstimate,
188 double &bestVal2,
int &bestIndex,
191 if(value > bestVal1) {
195 bestWay = upEstimate > downEstimate ? 0 : 1;
197 const OsiObject * obj =
object[iObject];
198 if (obj->preferredWay() >= 0 && obj->infeasibility()) {
199 bestWay = obj->preferredWay();
222 OsiBranchingInformation *
info,
239 printf(
"CCS: beg: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
240 pv, solver->getColSolution()[pv], solver->getColLower()[pv], solver->getColUpper()[pv]);
241 printf(
"CCS: info: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
242 pv, info->solution_[pv], info->lower_[pv], info->upper_[pv]);
243 printf(
"CCS: problem: lb: %10.4f ub: %10.4f\n",
261 int numberStrong = numberStrong_;
267 if (numberUnsatisfied_) {
268 int cardIndForPseudo = 0,
269 *indForPseudo =
new int[numberUnsatisfied_];
270 OsiObject **
object = solver->objects();
271 const double* upTotalChange =
pseudoCosts_.upTotalChange();
272 const double* downTotalChange =
pseudoCosts_.downTotalChange();
275 int numberBeforeTrusted =
pseudoCosts_.numberBeforeTrusted();
278 int numberLeft = CoinMin (numberStrong - numberStrongDone_, numberUnsatisfied_);
286 int returnCodeSB = 0;
287 bestObjectIndex_ = -1;
289 firstForcedObjectIndex_ = -1;
290 firstForcedWhichWay_ =-1;
291 double bestTrustedVal1 = -COIN_DBL_MAX;
292 double bestTrustedVal2 = -COIN_DBL_MAX;
294 bool smallGap =
false;
295 bool sbObjPosImp =
false;
301 int objInd =
problem_ -> Obj (0) -> Body () -> Index ();
302 double lbGap = objInd >= 0 ? info -> lower_ [objInd] :
problem_ -> Obj (0) -> Body () -> Value ();
303 double ubGap =
problem_ -> getCutOff ();
307 fabs (ubGap - lbGap) / (1.e-3 + CoinMin (fabs (ubGap), fabs (lbGap)));
309 if(currentGap < 1
e-3) {
320 for (
int i=0;i<numberLeft;i++) {
321 int iObject = list_[i];
322 if (numberBeforeTrusted == 0||
326 ( !isRoot && (upNumber[iObject]<numberBeforeTrusted ||
327 downNumber[iObject]<numberBeforeTrusted ))||
328 ( isRoot && (!upNumber[iObject] && !downNumber[iObject])) ) {
332 printf(
"Push object %d for strong branch\n", iObject);
341 printf(
"Use pseudo cost for object %d\n", iObject);
344 indForPseudo[cardIndForPseudo] = iObject;
360 const char* stat_msg[] = {
"NOTDON",
"FEAS",
"INFEAS",
"NOFINI"};
362 for (
unsigned int i = 0; i<
results_.size(); i++) {
363 double up_change =
results_[i].upChange();
364 double down_change =
results_[i].downChange();
365 int up_status =
results_[i].upStatus();
366 int down_status =
results_[i].downStatus();
368 <<stat_msg[up_status+1]<< up_change<< CoinMessageEol;
372 if (returnCodeSB >= 0 && returnCodeSB <= 2) {
373 if(returnCodeSB > 0) {
379 for (
unsigned int i=0;i <
results_.size (); i++) {
388 int iObject =
results_[i].whichObject();
389 const OsiObject * obj =
object[iObject];
390 int needBranch =
goodCandidate(solver, info,
object, iObject, prec);
398 upEstimate =
results_[i].upChange();
402 if (info->cutoff_<1.0e50)
403 upEstimate = 2.0*(info->cutoff_-info->objectiveValue_);
405 upEstimate = 2.0*fabs(info->objectiveValue_);
406 if (firstForcedObjectIndex_ <0) {
408 firstForcedObjectIndex_ = iObject;
409 firstForcedWhichWay_ =0;
414 if(needBranch >= 2) {
417 OsiBranchingObject * branch =
418 obj->createBranch(solver, info, 0);
419 branch -> branch (solver);
430 assert (
results_[i].downStatus()>=0);
431 downEstimate =
results_[i].downChange();
435 if (info->cutoff_<1.0e50)
436 downEstimate = 2.0*(info->cutoff_-info->objectiveValue_);
438 downEstimate = 2.0*fabs(info->objectiveValue_);
439 if (firstForcedObjectIndex_ <0) {
440 firstForcedObjectIndex_ = iObject;
441 firstForcedWhichWay_ =1;
445 if(needBranch >= 2) {
448 OsiBranchingObject * branch =
449 obj->createBranch(solver, info, 1);
450 branch -> branch (solver);
458 minVal, maxVal, value;
460 if (downEstimate < upEstimate) {
461 minVal = downEstimate;
465 maxVal = downEstimate;
475 ( MAXMIN_CRITERION * minVal +
476 (1.0 - MAXMIN_CRITERION) * maxVal);
479 if((needBranch >= 3) &&
480 saveBestCand(
object, iObject, value, upEstimate, downEstimate,
482 bestTrustedVal2, bestObjectIndex_, bestWhichWay_)) {
488 if(smallGap && (minVal > 1
e-3)) {
497 if (returnCodeSB == 3) {
498 if(bestObjectIndex_ < 0) {
501 bestObjectIndex_ = list_[0];
511 if(bestObjectIndex_ < 0) {
512 bestObjectIndex_ = list_[0];
514 cardIndForPseudo = 0;
518 if((returnCodeSB != -1) &&
519 ((returnCode != 0) || (!sbObjPosImp))) {
527 int bestObjectIndex2 = -1;
528 int bestWhichWay2 = 0;
529 double bestTrusted2Val1 = -COIN_DBL_MAX;
530 double bestTrusted2Val2 = -COIN_DBL_MAX;
532 for(
int ips=0; ips<cardIndForPseudo; ips++) {
533 int iObject = indForPseudo[ips];
534 const OsiObject * obj =
object[iObject];
535 int needBranch =
goodCandidate(solver, info,
object, iObject, prec);
538 upEstimate = (upTotalChange [iObject] * obj -> upEstimate ()) / upNumber [iObject],
539 downEstimate = (downTotalChange [iObject] * obj -> downEstimate ()) / downNumber [iObject],
541 minVal, maxVal, value;
543 if (downEstimate < upEstimate) {
544 minVal = downEstimate;
548 maxVal = downEstimate;
554 ( MAXMIN_CRITERION * minVal +
555 (1.0 - MAXMIN_CRITERION) * maxVal);
561 upEstimate, downEstimate,
563 bestTrusted2Val2, bestObjectIndex2,
570 printf(
"Object %d skip pseudocost\n", iObject);
576 upEstimate, downEstimate,
578 bestTrustedVal2, bestObjectIndex_, bestWhichWay_)) {
579 if(returnCode == 1) {
584 returnCode = (returnCode ? 3 : 0);
590 printf(
"Object %d use pseudocost\n", iObject);
596 if((bestObjectIndex_ < 0) && (bestObjectIndex2 >= 0)) {
597 bestObjectIndex_ = bestObjectIndex2;
598 bestWhichWay_ = bestWhichWay2;
599 bestTrustedVal1 = bestTrusted2Val1;
601 bestObjectIndex_, prec) != 4) {
610 int objectVarInd = -1;
611 if(bestObjectIndex_ >= 0) {
612 OsiObject * obj =
object[bestObjectIndex_];
613 obj->setWhichWay(bestWhichWay_);
619 objectVarInd = obj->columnNumber();
626 if(objectVarInd >= 0) {
627 double vUb = solver->getColUpper()[objectVarInd];
628 char strUb[400], strLb[400];
630 sprintf(strUb,
"+inf");
633 sprintf(strUb,
"%f", vUb);
635 double vLb = solver->getColLower()[objectVarInd];
637 sprintf(strLb,
"-inf");
640 sprintf(strLb,
"%f", vLb);
642 double vSolI = info->solution_[objectVarInd];
643 double vSolS = solver->getColSolution()[objectVarInd];
644 printf(
"Branch on object %d (var: %d): solInfo: %10.4f SolSolver: %10.4f low: %s up: %s\n",
645 bestObjectIndex_, objectVarInd, vSolI, vSolS, strLb, strU
650 printf(
"Branch on object %d (var: -1)\n", bestObjectIndex_);
657 if((numberFixed==numberUnsatisfied_&&numberFixed) &&
658 (
goodCandidate(solver, info,
object, bestObjectIndex_, prec) != 4)) {
662 if((returnCode == 2) || (returnCode == 3)) {
663 if((objectVarInd > -1) &&
664 (
goodCandidate(solver, info,
object, bestObjectIndex_, prec) != 4)) {
673 delete[] indForPseudo;
685 printf(
"CCS: end: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
686 pv, solver->getColSolution()[pv], solver->getColLower()[pv], solver->getColUpper()[pv]);
687 printf(
"CCS: info: x[%d]: %10.4f lb: %10.4f ub: %10.4f\n",
688 pv, info->solution_[pv], info->lower_[pv], info->upper_[pv]);
689 printf(
"CCS: problem: lb: %10.4f ub: %10.4f\n",
697 printf(
"CouenneChooseStrong::ChooseVariable(): retval: %d\n", retval);
735 "----------------- (strong) setup list\n");
738 for (
int i=0; i<
problem_ -> domain () -> current () -> Dimension (); i++)
739 printf (
"%4d %20.4g [%20.4g %20.4g]\n", i,
740 info -> solution_ [i], info -> lower_ [i], info -> upper_ [i]);
744 printf(
"Start CouenneChooseStrong::setupList()\n");
745 OsiObject **
object = info->solver_->objects();
769 info->objectiveValue_,
true,
775 printf(
"CouenneChooseStrong::setupList(): ### WARNING: checkNLP2() returns infeasible, no branching object selected\n");
780 double ckObj = info->objectiveValue_;
783 printf(
"CouenneChooseStrong::setupList(): ### WARNING: checkNLP() returns infeasible, no branching object selected\n");
789 #ifdef FM_TRACE_OPTSOL
801 printf(
"Strong list: (obj_ind var_ind priority useful viol)\n");
802 printf(
"numberStrong: %d numberStrongRoot: %d retval: %d\n",
804 for(
int i=0; i<retval; i++) {
811 objectInd =
object[list_[i]]->columnNumber();
815 double violprint =
object[list_[i]]->infeasibility(info, wayprint);
816 if(violprint < COIN_DBL_MAX / 100) {
817 printf(
" (%d %d %d %6.4f %6.4f)", list_[i], objectInd,
818 object[list_[i]]->priority(), useful_[i],
822 printf(
" (%d %d %d %6.4f +inf)", list_[i], objectInd,
823 object[list_[i]]->priority(), useful_[i]);
835 "----------------- (strong) setup list done - %d infeasibilities\n", retval);
837 #if (defined TRACE_STRONG)
838 printf(
"Done CouenneChooseStrong::setupList()\n");
849 roptions -> AddStringOption6
851 "Multipliers of pseudocosts for estimating and update estimation of bound",
854 "infeasibility",
"infeasibility returned by object",
856 "projectDist",
"distance between current LP point and resulting branches' LP points",
858 "interval_lp",
"width of the interval between bound and current lp point",
859 "interval_lp_rev",
"similar to interval_lp, reversed",
861 "interval_br",
"width of the interval between bound and branching point",
862 "interval_br_rev",
"similar to interval_br, reversed");
864 roptions -> AddStringOption2
865 (
"pseudocost_mult_lp",
866 "Use distance between LP points to update multipliers of pseudocosts "
867 "after simulating branching",
872 roptions -> AddStringOption2
874 "How the min/max estimates of the subproblems' bounds are used in strong branching",
876 "normal",
"as usual in literature",
877 "product",
"use their product");
879 roptions -> AddStringOption2
881 "Fathom strong branching LPs when their bound is above the cutoff",
890 const double * solution,
892 const OsiObject ** objects) {
895 return problem_ -> checkNLP2 (solution, 0,
false,
true,
true,
898 int indobj =
problem_ -> Obj (0) -> Body () -> Index ();
899 return problem_ -> checkNLP (solution, indobj >= 0 ? solution [indobj] :
problem_ -> Obj (0) -> Body () -> Value ());
906 OsiObject **
object = info->solver_->objects();
907 int numberObjects = info->solver_->numberObjects();
909 printf(
"CouenneChooseStrong::printObjViol(): Object violations: (obj_ind var_ind violation)");
911 double minPosViol = 1e50;
912 for(
int i=0; i<numberObjects; i++) {
919 indVar =
object[i]->columnNumber();
922 double value =
object[i]->infeasibility(info,way);
924 maxViol = (value > maxViol ? value : maxViol);
926 printf(
"(%d %d %f)", i, indVar, value);
927 minPosViol = (value < minPosViol ? value : minPosViol);
930 printf(
"\nmaxViol: %g minPosViol: %g\n", maxViol, minPosViol);
CouNumber & Ub(int i) const
upper bound on
virtual int setupList(OsiBranchingInformation *info, bool initialize)
Sets up strong list and clears all if initialize is true.
int nVars() const
Total number of variables.
virtual ~CouenneChooseStrong()
Destructor.
void update(const double *givenSol, const int givenCard, const double givenVal, const double givenMaxViol)
CouenneChooseStrong & operator=(const CouenneChooseStrong &rhs)
Assignment operator.
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
bool only_pseudo_when_trusted_
Flag indicating whether we don't want to mix strong branching and pseudo costs during the decision wh...
bool isRootNode(const OsiBranchingInformation *info) const
detecting if this is root node
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Add list of options to be read from file.
double maxminCrit(const OsiBranchingInformation *info) const
Helper functions for setupList and chooseVariable.
const double Couenne_large_bound
used to declare LP unbounded
bool checkNLP2(const double *solution, const double obj, const bool careAboutObj, const bool stopAtFirstViol, const bool checkAll, const double precision) const
Return true if either solution or recomputed_solution obtained using getAuxs() from the original vari...
CouNumber & Lb(int i) const
lower bound on
const Ipopt::EJournalCategory J_BRANCHING(Ipopt::J_USER1)
int minNumberStrongBranch_
Always strong branch that many first candidate in the list regardless of numberTrusted.
CouenneProblem * problem_
Pointer to the associated MINLP problem.
vector< HotInfo > results_
Stores strong branching results.
int gutsOfSetupList(OsiBranchingInformation *info, bool initialize)
CoinMessageHandler & message(Messages_Types type) const
virtual int doStrongBranching(OsiSolverInterface *OsiSolver, OsiBranchingInformation *info, int numberToDo, int returnCriterion)
This is a utility function which does strong branching on a list of objects and stores the results in...
void fint fint fint real fint real real real real real real real real real * e
A class to have all elements necessary to setup a branch-and-bound.
virtual int chooseVariable(OsiSolverInterface *solver, OsiBranchingInformation *info, bool fixVariables)
choose object to branch based on earlier setup
bool estimateProduct_
Normally, a convex combination of the min/max lower bounds' estimates is taken to select a branching ...
CouenneRecordBestSol * getRecordBestSol() const
returns recorded best solution
bool pseudoUpdateLP_
should we update the pseudocost multiplier with the distance between the LP point and the solution of...
int bb_log_level_
verbosity level
void printObjViol(OsiBranchingInformation *info)
Class for MINLP problems with symbolic information.
int number_not_trusted_
Number of variables put into the list because there were not trusted.
int goodCandidate(OsiSolverInterface *solver, OsiBranchingInformation *info, OsiObject **object, const int iObject, const double prec)
void fint fint fint fint fint fint fint fint fint fint real real real real real real real real * s
double CouNumber
main number type in Couenne
const CouNumber estProdEps
JnlstPtr jnlst_
pointer to journalist for detailed information
virtual OsiChooseVariable * clone() const
Clone.
OsiPseudoCosts pseudoCosts_
Stores the pseudo costs.
virtual bool feasibleSolution(const OsiBranchingInformation *info, const double *solution, int numberObjects, const OsiObject **objects)
Returns true if solution looks feasible against given objects.
CouenneChooseStrong()
Default Constructor, forbidden for some reason.
double getFeasTol()
returns feasibility tolerance
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
bool checkNLP(const double *solution, double &obj, bool recompute=false) const
Check if solution is MINLP feasible.
int numberStrongRoot_
number of strong branching points at root node
double branchtime_
total time spent in strong branching
void eliminateIntegerObjects(OsiSolverInterface *model)
bool saveBestCand(OsiObject **object, const int iObject, const double value, const double upEstimate, const double downEstimate, double &bestVal1, double &bestVal2, int &bestIndex, int &bestWay)
Save best candidate.
BonChooseVariable & operator=(const BonChooseVariable &rhs)
Assignment operator.
bool isInteger(CouNumber x)
is this number integer?