9 #include "CoinHelperFunctions.hpp"
21 #ifndef BM_DEBUG_PRINT
22 #define BM_DEBUG_PRINT 0
50 BM_lp: At node %i : WARNING: nlp reached iter limit. Will force branching\n",
54 BM_lp: At node %i : WARNING: nlp is abandoned. Will force branching\n",
61 print(
ifprint,
"WARNING! Too many (%i) NLP failures in a row. Abandoning node.",
70 OsiBranchingInformation brInfo(nlp,
false,
true);
72 brInfo.objectiveValue_ = lpres.
objval();
75 brInfo.numberSolutions_ = 0;
76 brInfo.numberBranchingSolutions_ = 0;
82 brDecision =
bbBranch(brInfo, cands);
106 OsiPseudoCosts& pseudoCosts = choose->
pseudoCosts();
107 int numObj = pseudoCosts.numberObjects();
108 double* upTotalChange = pseudoCosts.upTotalChange();
109 int* upNumber = pseudoCosts.upNumber();
110 double* downTotalChange = pseudoCosts.downTotalChange();
111 int* downNumber = pseudoCosts.downNumber();
113 buf.
unpack(upTotalChange, numObj,
false);
114 buf.
unpack(upNumber, numObj,
false);
115 buf.
unpack(downTotalChange, numObj,
false);
116 buf.
unpack(downNumber, numObj,
false);
130 for (
int i = 0; i <
objNum_; ++i) {
137 objchange = sbres.
objval[0] - branchInfo.objectiveValue_;
139 if (branchInfo.cutoff_ < 1e50) {
140 objchange = 2*(branchInfo.cutoff_-branchInfo.objectiveValue_);
142 objchange = 2*fabs(branchInfo.objectiveValue_);
152 objchange = sbres.
objval[1] - branchInfo.objectiveValue_;
154 if (branchInfo.cutoff_ < 1e50) {
155 objchange = 2*(branchInfo.cutoff_-branchInfo.objectiveValue_);
157 objchange = 2*fabs(branchInfo.objectiveValue_);
174 const OsiObject*
const * objects = branchInfo.solver_->objects();
175 double upMult, downMult;
177 const double MAXMIN = choose->
maxminCrit(&branchInfo);
180 int lastPriority = objects[
objInd_[0]]->priority();
181 int infBlockStart = 0;
182 int feasBlockStart = 0;
193 for (
int i = 0; i <
objNum_; ++i) {
195 const OsiObject*
object = objects[ind];
196 double value =
object->infeasibility(&branchInfo, way);
201 if (! disregardPriorities) {
202 int priorityLevel =
object->priority();
203 if (lastPriority < priorityLevel) {
209 CoinFirstGreater_2<double,int>());
216 lastPriority = priorityLevel;
221 if (usePseudoCosts) {
233 const OsiSOS* sos =
dynamic_cast<const OsiSOS*
>(object);
238 const int iCol =
object->columnNumber();
239 const double lb = branchInfo.lower_[iCol];
240 const double ub = branchInfo.upper_[iCol];
241 if (fabs(ub - lb) < 0.1) {
244 value = branchInfo.solution_[iCol];
246 if (floor(value+0.5) > lb && ceil(value-0.5) < ub) {
251 if (! disregardPriorities) {
252 int priorityLevel =
object->priority();
253 if (lastPriority < priorityLevel) {
259 CoinFirstGreater_2<double,int>());
265 lastPriority = priorityLevel;
271 upMult, downMult, value,
280 CoinFirstGreater_2<double,int>());
290 CoinFirstGreater_2<double,int>());
297 #if (BM_DEBUG_PRINT != 0)
298 const double t = CoinWallclockTime();
299 printf(
"LP %.3f: node: %i depth: %i obj: %f infNum: %i feasNum: %i soltime: %.3f\n",
301 branchInfo.objectiveValue_,
314 for (
int i = 0; i <
objNum_; ++i) {
324 OsiSolverInterface* solver,
330 for (i = 0; i <
infNum_; ++i) {
333 const int colInd = solver->object(objInd)->columnNumber();
334 const double val = branchInfo.solution_[colInd];
339 branchData[
b].
bd = floor(val);
344 if (b == branchNum) {
351 branchData[
b].
bd = ceil(val);
354 if (b == branchNum) {
360 const int colInd = solver->object(objInd)->columnNumber();
361 const double val = branchInfo.solution_[colInd];
362 const double lb = branchInfo.lower_[colInd];
363 const double ub = branchInfo.upper_[colInd];
364 if (floor(val+0.5) > lb) {
369 branchData[
b].
bd = floor(val - 0.5);
371 if (b == branchNum) {
375 if (ceil(val-0.5) < ub) {
380 branchData[
b].
bd = ceil(val + 0.5);
382 if (b == branchNum) {
395 for (
int i = 0; i < numBranch; ++i) {
396 double t = CoinWallclockTime();
397 const int ind = bD[i].
colInd;
399 const double old_lb = solver->getColLower()[ind];
400 const double old_ub = solver->getColUpper()[ind];
402 solver->setColUpper(ind, bD[i].bd);
404 solver->setColLower(ind, bD[i].bd);
407 solver->setWarmStart(cws);
410 solver->initialSolve();
418 bD[i].
iter = solver->getIterationCount();
419 solver->setColBounds(ind, old_lb, old_ub);
420 bD[i].
time = CoinWallclockTime() -
t;
430 for (
int i = 0; i < numBranch; ++i) {
433 sbres.
objInd = bD[i].objInd;
435 sbres.
status[field] = bD[i].status;
436 sbres.
objval[field] = bD[i].objval;
437 sbres.
iter[field] = bD[i].iter;
438 sbres.
varChange[field] = fabs(bD[i].solval - bD[i].bd);
446 OsiSolverInterface* solver,
447 const CoinWarmStart* cws,
449 const int* pids,
const int pidNum)
451 const double * clb = solver->getColLower();
452 const double * cub = solver->getColUpper();
453 const int numCols = solver->getNumCols();
461 bool has_ws = cws != NULL;
465 CoinWarmStart* cws_tmp = cws->clone();
479 int branchLeft = branchNum;
481 for (
int pidLeft = pidNum; pidLeft > 0; --pidLeft) {
482 int numSend = branchLeft / pidLeft;
483 if (numSend * pidLeft < branchLeft) {
488 int location = bD - branchData;
491 for (
int s = 0;
s < numSend; ++
s) {
500 branchLeft -= numSend;
502 assert(branchNum/(pidNum+1) == branchLeft);
512 int numResults = branchLeft;
513 while (numResults < branchNum) {
523 for (
int i = 0; i < numRes; ++i) {
530 numResults += numRes;
547 OsiSolverInterface* solver,
549 OsiBranchingObject*& branchObject)
553 #if defined(DEBUG_PRINT)
557 #if 0 // defined(DEBUG_PRINT)
558 const double t = CoinWallclockTime()-
start_time();
559 for (i = 0; i <
infNum_; ++i) {
564 printf(
"LP %.3f: SB: node: %i inf col: %i stati: %i %i, obj: %f %f time: %.3f %.3f\n",
574 printf(
"LP %.3f: SB: node: %i feas col: %i stati: %i %i, obj: %f %f time: %.3f %.3f\n",
582 for (i = 0; i <
infNum_; ++i) {
590 #if (BM_DEBUG_PRINT != 0)
591 const double wallclock = CoinWallclockTime();
593 printf(
"LP %.3f: SBres: node: %i FATHOM inf/eval/cand: time: %.3f\n",
598 printf(
"LP %.3f: SBres: node: %i FATHOM time: %.3f\n",
611 for (i = 0; i <
infNum_; ++i) {
618 const int colInd = sbres.
colInd;
619 solver->setColLower(colInd, ceil(branchInfo.solution_[colInd]));
624 const int colInd = sbres.
colInd;
625 solver->setColUpper(colInd, floor(branchInfo.solution_[colInd]));
639 const int colInd = sbres.
colInd;
640 solver->setColLower(colInd, ceil(branchInfo.solution_[colInd] - 0.5));
647 const int colInd = sbres.
colInd;
648 solver->setColUpper(colInd, floor(branchInfo.solution_[colInd] + 0.5));
653 if ((fixedStat & 2) != 0) {
654 #if (BM_DEBUG_PRINT != 0)
655 printf(
"LP %.3f: SBres: node: %i RESOLVE time: %.3f\n",
668 int bestWhichWay = 1;
669 double bestTrusted = preferHigh ? -COIN_DBL_MAX : COIN_DBL_MAX;
670 const double MAXMIN = choose->
maxminCrit(&branchInfo);
672 for (i = 0; i <
infNum_; ++i) {
682 double upEst = sbres.
objval[1] - branchInfo.objectiveValue_;
683 double downEst = sbres.
objval[0] - branchInfo.objectiveValue_;
685 MAXMIN*CoinMin(upEst,downEst) + (1.0-MAXMIN)*CoinMax(upEst,downEst);
686 const bool better = ( ( preferHigh && (value > bestTrusted)) ||
687 ( !preferHigh && (value < bestTrusted)) );
691 bestWhichWay = upEst > downEst ? 0 : 1;
693 const OsiObject*
object = solver->object(objInd);
694 if (object->preferredWay() >= 0 &&
object->infeasibility()) {
695 bestWhichWay =
object->preferredWay();
704 for (i = 0; i <
infNum_; ++i) {
712 for (i = 0; i <
infNum_; ++i) {
728 const OsiObject *
object = solver->object(
infInd_[best]);
729 branchObject =
object->createBranch(solver, &branchInfo, bestWhichWay);
731 #if (BM_DEBUG_PRINT != 0)
732 const int ind =
object->columnNumber();
733 printf(
"LP %.3f: SBres: node: %i depth: %i BRANCH time: %.3f evaluated: %i bvar: %i val: %f obj0: %f obj1: %f way: %i\n",
735 evaluated, ind, branchInfo.solution_[ind],
740 return (fixedStat & 1) != 0 ? -1 : 0;
747 OsiSolverInterface* solver,
749 OsiBranchingObject*& branchObject,
752 int returnStatus = 0;
761 const bool do_distributed_branching =
true;
763 if (do_distributed_branching) {
777 CoinWarmStart* cws = solver->getWarmStart();
779 if (iws && iws->
empty()) {
785 if (nodeIndex == 0) {
791 branchNum = CoinMin(branchNum,
795 branchNum = pidNum > 0 ? pidNum + 1 : 0;
808 branchObject, allowVarFix);
833 nlp->
getDblParam(OsiPrimalTolerance, brInfo.integerTolerance_);
836 OsiBranchingObject* brObj = NULL;
839 double* clb_old =
new double[numCols];
840 double* cub_old =
new double[numCols];
841 CoinDisjointCopyN(nlp->
getColLower(), numCols, clb_old);
842 CoinDisjointCopyN(nlp->
getColUpper(), numCols, cub_old);
847 options->GetIntegerValue(
"number_strong_branch",numSB,
"bonmin.");
849 const bool sbRootIsSet =
850 options->GetIntegerValue(
"number_strong_branch_root",numSBroot,
"bonmin.");
852 if (sbRootIsSet && brInfo.depth_ == 0) {
863 if (choose->goodSolution()) {
865 const double* sol = choose->goodSolution();
866 BM_solution* bmsol =
new BM_solution;
869 for (
int i = 0 ; i < numCols ; i++) {
870 if (fabs(sol[i]) > ptol)
871 bmsol->add_entry(i, sol[i]);
873 bmsol->setObjective(choose->goodObjectiveValue());
874 choose->clearGoodSolution();
907 BM: BCP_lp_user::try_to_branch returned with unknown return code.\n");
921 for (
int i = 0; i < numCols; ++i) {
922 if (clb_old[i] != clb[i] || cub_old[i] != cub[i]) {
923 vars[i]->change_bounds(clb[i], cub[i]);
924 nlp->setColBounds(i, clb[i], cub[i]);
931 int order[2] = {0, 1};
933 OsiIntegerBranchingObject* intBrObj =
934 dynamic_cast<OsiIntegerBranchingObject*
>(brObj);
936 if (intBrObj->firstBranch() == 1) {
952 print(
ifprint2,
"BM_lp: branching on variable %i value: %f\n",
953 intBrObj->originalObject()->columnNumber(),
957 OsiSOSBranchingObject* sosBrObj =
958 dynamic_cast<OsiSOSBranchingObject*
>(brObj);
960 if (sosBrObj->firstBranch() == 1) {
977 sosBrObj->originalObject()->columnNumber(),
1021 buf.
unpack(clb, numCols);
1023 buf.
unpack(cub, numCols);
1038 for (i = 0; i < numBranch; ++i) {
1039 buf.
unpack(branchData[i].changeType);
1040 buf.
unpack(branchData[i].objInd);
1041 buf.
unpack(branchData[i].colInd);
1042 buf.
unpack(branchData[i].solval);
1043 buf.
unpack(branchData[i].bd);
1055 for (i = 0; i < numBranch; ++i) {
1067 delete[] branchData;
BM_SB_result * bestSbResult_
A pointer to the entry that got selected.
char get_param(const BCP_lp_par::chr_params key) const
BCP_branching_decision bbBranch(OsiBranchingInformation &brInfo, BCP_vec< BCP_lp_branching_object * > &cands)
BCP_buffer & pack(const T &value)
Pack a single object of type T.
virtual void set_user_data_for_children(BCP_presolved_lp_brobj *best, const int selected)
For each child create a user data object and put it into the appropriate entry in best->user_data()...
BCP_lp_node * node
Description he current search tree node.
The minimum difference between the objective value of any two feasible solution (with different objec...
void print(const bool ifprint, const char *format,...) const
A method to print a message with the process id.
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
int parent() const
the process id of the parent
virtual const double * getColLower() const
Get pointer to array[getNumCols()] of column lower bounds.
This class chooses a variable to branch on.
void BCP_pack_warmstart(const BCP_warmstart *ws, BCP_buffer &buf)
Class for storing warm start informations for Ipopt.
void BM_register_branch_results(const int numBranch, const BM_BranchData *bD, BM_SB_result *sbResults)
Request a list of process ids the LP can use to do distributed strong branching.
void updateStrongBrachingInfo(int chosenIndex, int listLength)
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
int branchEval
0: Not done 1: Only down 2: only up 3: both ways
double computeUsefulness(const double MAXMIN_CRITERION, const double upMult, const double dowMult, const double value, const OsiObject *object, int i, double &value2) const
void forceBranchable()
Force current solution to be branched on (make it fractionnal with small objective) ...
This class exist only so that we can extract information from OsiIntegerBranchingObject.
void collect_branch_data(OsiBranchingInformation &branchInfo, OsiSolverInterface *solver, const int branchNum, BM_BranchData *branchData)
double maxminCrit(const OsiBranchingInformation *info) const
Helper functions for setupList and chooseVariable.
char entry(const chr_params key) const
Maximum allowed running time.
int process_SB_results(OsiBranchingInformation &branchInfo, OsiSolverInterface *solver, Bonmin::BonChooseVariable *choose, OsiBranchingObject *&branchObject)
double node_start_time
The time when we started to process the node.
int current_level() const
Return the level of the search tree node being processed.
int sender() const
Return a const pointer to the process id of the sender of the message in the buffer.
int current_index() const
Return the internal index of the search tree node being processed.
BCP should continue to work on this node.
double start_time() const
Return when the LP process started.
BCP_warmstart * BCP_lp_convert_CoinWarmStart(BCP_lp_prob &p, CoinWarmStart *&ws)
void BM_solve_branches(OsiSolverInterface *solver, const CoinWarmStart *cws, const int numBranch, BM_BranchData *bD)
void do_distributed_SB(OsiBranchingInformation &branchInfo, OsiSolverInterface *solver, const CoinWarmStart *cws, const int branchNum, const int *pids, const int pidNum)
reference back()
Return a reference to the last entry.
virtual int getNumCols() const
Get number of columns.
Warmstarting information for the LP solver.
void push_back(const_reference x)
Append x to the end of the vector.
BCP_branching_decision hybridBranch()
BM_stats bm_stats
Class for collecting statistics.
void send_message(const int target, const BCP_buffer &buf, BCP_message_tag tag=BCP_Msg_User)
Send a message to a particular process.
void unpack_pseudo_costs(BCP_buffer &buf)
int numNlpFailed_
A counter for how many times in a row did the NLP code fail.
const OsiPseudoCosts & pseudoCosts() const
Access to pseudo costs storage.
virtual void setColUpper(int elementIndex, double elementValue)
Set a single column upper bound.
Bonmin::Algorithm getAlgorithm()
Get the algorithm used.
Bonmin::BonminAmplSetup bonmin_
This contains the setup for running Bonmin in particular nlp solver, continuous solver, cut generators,...
virtual void process_message(BCP_buffer &buf)
Process a message that has been sent by another process' user part to this process' user part...
int * infInd_
Every time when branching decisions are to be made, we create 6 arrays, 3 for those objects that are ...
int numNlpFailed_
A counter for how many times in a row did the NLP code fail.
BCP_vec< BCP_user_data * > & user_data()
Return a reference to the user data vector.
BCP_lp_prob * getLpProblemPointer()
Get the pointer.
An LP process (that is used as a strong branching node) indicates that it's finished.
OsiSolverInterface * lp_solver
A class that holds the methods about how to pack things.
void set_presolve_result(const BCP_vec< double > &objval, const BCP_vec< int > &termcode)
The constructor makes a copy of each vector passed to it.
OsiChooseVariable * branchingMethod()
branching method to use.
virtual BCP_branching_decision select_branching_candidates(const BCP_lp_result &lpres, const BCP_vec< BCP_var * > &vars, const BCP_vec< BCP_cut * > &cuts, const BCP_lp_var_pool &local_var_pool, const BCP_lp_cut_pool &local_cut_pool, BCP_vec< BCP_lp_branching_object * > &cans, bool force_branch=false)
Decide whether to branch or not and select a set of branching candidates if branching is decided upon...
This class describes a generic branching object.
void fint fint fint fint fint fint fint fint fint fint real real real real real real real real * s
virtual CoinWarmStart * convert_to_CoinWarmStart() const =0
Return an OsiWarmStart object that can be fed to the LP engine.
virtual bool isIterationLimitReached() const
Iteration limit reached?
BCP_branching_decision
This enumerative constant is the return value of the select_branching_candidates() method in [BCP_lp_...
void clear()
Completely clear the buffer.
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real * ws
void computeMultipliers(double &upMult, double &downMult) const
void send_pseudo_cost_update(OsiBranchingInformation &branchInfo)
Methods invoked from bbBranch()
void set_size(const int s)
Cut off the end of the buffer.
int * objInd_
These are the indices of the integral (i.e., things that can be branched on) objects in the solver...
double upper_bound() const
Return what is the best known upper bound (might be BCP_DBL_MAX)
Currently there isn't any error handling in BCP.
The node should be fathomed without even trying to branch.
A presolved branching object candidate.
virtual int try_to_branch(OsiBranchingInformation &branchInfo, OsiSolverInterface *solver, OsiChooseVariable *choose, OsiBranchingObject *&branchObject, bool allowVarFix)
Select the "close-to-half" variables for strong branching.
void receive_message(const int sender, BCP_buffer &buf, BCP_message_tag tag=BCP_Msg_User)
Wait for a message and receive it.
void incNumberSbSolves(int cnt)
int try_to_branch(OsiBranchingInformation &branchInfo, OsiSolverInterface *solver, Bonmin::BonChooseVariable *choose, OsiBranchingObject *&branchObject, bool allowVarFix)
BCP_parameter_set< BM_par > par
This class describes the message buffer used for all processes of BCP.
BCP_warmstart * BCP_unpack_warmstart(BCP_buffer &buf)
virtual const double * getColUpper() const
Get pointer to array[getNumCols()] of column upper bounds.
OsiTMINLPInterface * nonlinearSolver()
Pointer to the non-linear solver used.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
Used by the user to send a message to the user portion of the other process.
BM_SB_result * sbResult_
This is where we keep the results in case of distributed strong branching.
This class exist only so that we can extract information from OsiIntegerBranchingObject.
void incNumberNodeSolves()
This class holds the results after solving an LP relaxation.
bool empty() const
Is this an empty warm start?
bool over_ub(double lb) const
Return true / false depending on whether the lb argument is over the current upper bound or not...
Send a list of process ids the LP can use to do distributed strong branching.
virtual void setColLower(int elementIndex, double elementValue)
Set a single column lower bound.
bool isBranchFathomable(int status, double obj)
void send_feasible_solution(const BCP_solution *sol)
int sort_objects(OsiBranchingInformation &branchInfo, Bonmin::BonChooseVariable *choose, int &branchNum)
bool getDblParam(OsiDblParam key, double &value) const
int size() const
Return the size of the current message in the buffer.