5 #include "CoinPragma.hpp"
8 #include "CoinTime.hpp"
11 #define ASSERTED_CAST static_cast
13 #define ASSERTED_CAST dynamic_cast
20 OsiChooseVariable(solver),
33 options->GetIntegerValue(
"nway_branch_log_level",
log_, b.
prefix());
37 int numberObjects = solver_->numberObjects();
38 std::cout<<
"Number objects "<<numberObjects<<std::endl;
40 OsiObject **
object = solver->objects();
41 for (
int i=0;i<numberObjects;i++) {
51 OsiChooseVariable(rhs),
52 br_depth_(rhs.br_depth_),
53 do_fixings_(rhs.do_fixings_),
54 cutoff_multiplier_(rhs.cutoff_multiplier_),
55 pseudocost_trust_value_(rhs.pseudocost_trust_value_),
56 time_limit_(rhs.time_limit_),
57 start_time_(rhs.start_time_),
58 start_nway_(rhs.start_nway_),
61 unit_changes_(rhs.unit_changes_),
62 num_ps_costs_(rhs.num_ps_costs_),
63 num_eval_(rhs.num_eval_),
64 geo_means_(rhs.geo_means_)
80 OsiChooseVariable::operator=(rhs);
104 roptions->AddLowerBoundedIntegerOption(
"nway_branch_log_level",
105 "Log level for the branching on nways",
109 roptions->AddLowerBoundedIntegerOption(
"strong_branch_depth",
110 "To which level do we perform strong-branching",
114 roptions->AddLowerBoundedNumberOption(
"cutoff_multiplier",
115 "multiplier applied to cutoff_ for computing pseudo-cost of infeasible sub-problems",
119 roptions->AddLowerBoundedNumberOption(
"pseudocost_trust_value",
120 "Trust pseudo cost of best nway object if it is above this value",
124 roptions->AddStringOption2(
"use_geo_means",
"Use geometrical means to average pseudo-costs",
126 "no",
"Use artihmetical means",
127 "yes",
"Use geometrical means",
"");
129 roptions->AddStringOption4(
"do_fixings",
130 "Do we fix variables in strong branching?",
132 "none",
"Don't do any.",
133 "in-tree",
"Fix only variables in the tree",
134 "strong-branching",
"Fix variable in strong branching only",
135 "all",
"Fix whenever possible",
146 BonNWayObject * nway = ASSERTED_CAST<BonNWayObject *>(info->solver_->objects()[objectIndex]);
149 const int * vars = nway->
members();
153 for(
size_t k = 0 ;
k < unit_changes.size() ;
k++) unit_changes[
k] = (
num_ps_costs_[nwayIndex][
k]) ? pow(unit_changes[k], 1./(
double)
num_ps_costs_[nwayIndex][k]): unit_changes[
k];
156 for(
size_t k = 0 ;
k < unit_changes.size() ;
k++) unit_changes[
k] = (
num_ps_costs_[nwayIndex][
k]) ? unit_changes[
k]/(double)
num_ps_costs_[nwayIndex][k]: unit_changes[k];
166 size_t n,
const int * vars,
const std::vector<double> &bounds,
const std::vector<double> &unit_changes)
const
168 const double * solution = info->solution_;
169 double obj_val = info->objectiveValue_;
170 const double * lower = info->lower_;
171 const double * upper = info->upper_;
172 double integerTolerance = info->integerTolerance_;
176 for(
size_t i = 0 ; i <
n ; i++){
178 if(fabs(lower[iCol] - upper[iCol]) < integerTolerance) {
182 assert(lower[iCol] < upper[iCol]);
183 double residual = upper[iCol] - solution[iCol];
184 double score = std::min(cutoff - obj_val, std::max(residual*unit_changes[i],bounds[i] - obj_val));
199 delete [] goodSolution_;
201 goodSolution_ = NULL;
202 goodObjectiveValue_ = COIN_DBL_MAX;
207 numberUnsatisfied_=0;
208 int numberObjects = info->solver_->numberObjects() -
start_nway_;
209 double cutoff = info->cutoff_;
210 if(info->depth_ == 0){
213 bounds_.resize(numberObjects, std::vector<double>(numberObjects,cutoff));
214 unit_changes_.resize(numberObjects, std::vector<double>(numberObjects,0));
216 num_ps_costs_.resize(numberObjects, std::vector<int>(numberObjects,0));
223 int maximumStrong = numberObjects;
225 double check = -COIN_DBL_MAX;
227 int bestPriority=COIN_INT_MAX;
228 int putOther = numberObjects;
230 for (i=0;i<numberObjects;i++) {
235 OsiObject **
object = info->solver_->objects();
239 bool feasible =
true;
240 for ( i=0;i<numberObjects;i++) {
242 double value =
object[i]->infeasibility(info,way);
244 numberUnsatisfied_++;
245 int priorityLevel =
object[i]->priority();
247 if (priorityLevel<bestPriority) {
248 for (
int j=maximumStrong-1;
j>=0;
j--) {
250 int iObject = list_[
j];
253 list_[--putOther]=iObject;
256 bestPriority = priorityLevel;
260 if (priorityLevel==bestPriority) {
263 if(info->depth_ != 0){
269 int iObject = list_[checkIndex];
271 assert (list_[putOther-1]<0);
272 list_[--putOther]=iObject;
275 assert (checkIndex<putOther);
276 useful_[checkIndex]=value;
279 maximumStrong = CoinMin(maximumStrong,putOther);
280 for (
int j=0;
j<maximumStrong;
j++) {
282 if (useful_[
j]<check) {
296 assert (list_[putOther-1]<0);
298 maximumStrong = CoinMin(maximumStrong,putOther);
304 assert (list_[putOther-1]<0);
306 maximumStrong = CoinMin(maximumStrong,putOther);
314 maximumStrong = CoinMin(maximumStrong,putOther);
315 for (i=0;i<maximumStrong;i++) {
317 list_[numberOnList_]=list_[i];
318 useful_[numberOnList_++]=-useful_[i];
323 CoinSort_2(useful_,useful_+numberOnList_,list_);
326 for (;putOther<numberObjects;putOther++)
327 list_[i++]=list_[putOther];
328 assert (i==numberUnsatisfied_);
335 numberUnsatisfied_=-1;
338 info->defaultDual_ = -1.0;
339 delete [] info->usefulRegion_;
340 delete [] info->indexRegion_;
342 return numberUnsatisfied_;
359 OsiSolverInterface * solver,
360 OsiBranchingInformation *
info,
363 if(!numberUnsatisfied_)
return 1;
366 double cutoff = info->cutoff_;
367 double obj_val = info->objectiveValue_;
369 const double * lower = info->lower_;
370 const double * upper = info->upper_;
376 for(
int i = 0 ; i < numberUnsatisfied_ ; i++){
377 int iObject = list_[i];
379 const BonNWayObject * nway = ASSERTED_CAST<const BonNWayObject *>(solver->object(iObject));
382 const int * vars = nway->
members();
383 for(
size_t j = 0 ;
j <
n ;
j++){
385 if(upper[iCol] < lower[iCol] + 0.5)
continue;
387 solver->setColUpper(iCol, lower[iCol]);
392 if(n_fixed &&
log_ > 1)
393 printf(
"NWAY: Fixed %i variables\n", n_fixed);
399 bestObjectIndex_ = list_[0];
401 OsiObject * obj = solver->objects()[bestObjectIndex_];
402 obj->setWhichWay(bestWhichWay_);
405 printf(
"level %i branch on %i bound %g usefullness %g.\n",
406 info->depth_, bestObjectIndex_ -
start_nway_, obj_val, - useful_[0]);
408 if(n_fixed)
return 2;
414 printf(
"Restarting strong branching loop....\n\n");
416 numberStrongIterations_ = 0;
417 numberStrongDone_ = 0;
418 int numberLeft = numberOnList_;
420 bestObjectIndex_ = -1;
422 firstForcedObjectIndex_ = -1;
423 firstForcedWhichWay_ =-1;
424 double best_score = -COIN_DBL_MAX;
427 int n = solver->getNumCols();
428 std::vector<double> saveLower(n);
429 std::vector<double> saveUpper(n);
430 std::copy(info->lower_, info->lower_ + n, saveLower.begin());
431 std::copy(info->upper_, info->upper_ + n, saveUpper.begin());
434 solver->markHotStart();
435 for (
int i=0;i<numberLeft;i++) {
436 int iObject = list_[i];
437 const int objectPriority = solver->object(iObject)->priority();
438 if (objectPriority >= bestPriority){
439 bestPriority = objectPriority;
444 saveUpper.data(), score);
447 std::cout<<
"This is Infeasible"<<std::endl;
452 if(
do_fixings_ > 1 && r_val == 1 && info->depth_ == 0) returnCode=2;
455 printf(
"Usefullness from strong branching on %i : %g\n", iObject -
start_nway_, score);
456 if(score > best_score){
458 bestObjectIndex_ = iObject;
464 if(bestObjectIndex_ < 0){
465 bestObjectIndex_ = list_[0];
471 solver->unmarkHotStart();
486 OsiBranchingInformation *
info,
489 double * saveUpper,
double & score)
492 const double * lower = info->lower_;
493 const double * upper = info->upper_;
495 int numberColumns = solver->getNumCols();
496 double timeStart = CoinCpuTime();
498 int numberObjects = info->solver_->numberObjects();
499 const BonNWayObject * nway = ASSERTED_CAST<const BonNWayObject *>(solver->object(objectIndex));
503 int branches_left = branch->numberBranchesLeft();
504 int number_branches = branch->numberBranchesLeft();
505 int n_can_be_fixed = 0;
508 if(big_val > 1e10){ big_val = 10*info->objectiveValue_;}
509 big_val += fabs(big_val)*1
e-5;
510 std::vector<double> unit_changes(numberObjects - start_nway_, -DBL_MAX);
512 while(branches_left){
517 double residual = upper[v_br] - info->solution_[v_br];
518 solver->solveFromHotStart() ;
519 numberStrongIterations_ += solver->getIterationCount();
522 double obj_val = solver->getObjValue();
524 if(solver->isProvenPrimalInfeasible() ||
525 (solver->isProvenOptimal() && obj_val > info->cutoff_)){
526 if(info->depth_ == 0){
527 bounds_[nwayIndex][s_br] = big_val;
529 unit_changes[s_br] = (big_val - info->objectiveValue_)/residual;
533 printf(
"Fixing variable %i to 0 the cutoff is %g\n", v_br, big_val);
534 saveUpper[v_br] = saveLower[v_br];
538 if(info->depth_ == 0){
539 bounds_[nwayIndex][s_br] = obj_val;
541 unit_changes[s_br] = (obj_val - info->objectiveValue_)/residual;
545 for (
int j=0;
j<numberColumns;
j++) {
546 if (saveLower[
j] != lower[
j])
547 solver->setColLower(j,saveLower[j]);
548 if (saveUpper[j] != upper[j])
549 solver->setColUpper(j,saveUpper[j]);
551 branches_left = branch->numberBranchesLeft();
555 if(info->depth_ == 0){
558 for(
size_t k = 0 ;
k < unit_changes.size() ;
k++){
564 else if (n_can_be_fixed < number_branches -1){
566 for(
size_t k = 0 ;
k < unit_changes.size() ;
k++){
567 if(unit_changes[
k] > 0.){
576 if(n_can_be_fixed == number_branches){
582 bool hitMaxTime = ( CoinCpuTime()-timeStart > info->timeRemaining_)
double start_time_
Starting time of algorithm.
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
double time_limit_
Global time limit for algorithm.
virtual ~BonNWayChoose()
Destructor.
virtual OsiBranchingObject * createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const
Creates a branching object.
This class chooses a variable to branch on.
Ipopt::Index do_fixings_
Do we fix?*.
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Register class options.
std::vector< std::vector< int > > num_ps_costs_
virtual int doStrongBranching(OsiSolverInterface *solver, OsiBranchingInformation *info, int iObject, double *saveLow, double *saveUp, double &score)
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 a variable Returns - -1 Node is infeasible 0 Normal termination - we have a candidate 1 All lo...
virtual OsiChooseVariable * clone() const
Clone.
size_t numberMembers() const
Number of members.
int start_nway_
Start of nway objects in array.
virtual double branch(OsiSolverInterface *solver)
Does next branch and updates state.
double pseudocost_trust_value_
Trust value for the pseudo costs.
virtual int setupList(OsiBranchingInformation *info, bool initialize)
Sets up strong list and clears all if initialize is true.
const int * members() const
Members (indices in range 0 ... numberColumns-1)
double compute_usefulness(int objectIndex, const OsiBranchingInformation *info) const
Helper function for setupList and chooseVariable, compute usefullness of an nway object.
N way branching Object class.
void set_bounds(std::vector< double > &bounds) const
BonNWayChoose & operator=(const BonNWayChoose &rhs)
Assignment operator.
double cutoff_multiplier_
Cutoff multiplier for infeasibles.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
std::vector< int > num_eval_
BonNWayChoose()
Default Constructor, forbiden for some reason.
const char * prefix() const
Get prefix to use for options.
int br_depth_
depth of strong-branching.