/* Choose a variable Returns - -1 Node is infeasible 0 Normal termination - we have a candidate 1 All looks satisfied - no candidate 2 We can change the bound on a variable - but we also have a strong branching candidate 3 We can change the bound on a variable - but we have a non-strong branching candidate 4 We can change the bound on a variable - no other candidates We can pick up branch from whichObject() and whichWay() We can pick up a forced branch (can change bound) from whichForcedObject() and whichForcedWay() If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() */ int BonNWayChoose::chooseVariable( OsiSolverInterface * solver, OsiBranchingInformation *info, bool fixVariables) { if(!numberUnsatisfied_) return 1;//Node is feasible double cutoff = info->cutoff_; double obj_val = info->objectiveValue_; if(info->depth_ > br_depth_ && ( (- useful_[0] > pseudocost_trust_value_ )|| num_eval_[list_[0] - start_nway_] >= 18) ){ const double * lower = info->lower_; const double * upper = info->upper_; // See if quick variable fixing can be done int n_fixed = 0; if(do_fixings_ > 1){ for(int i = 0 ; i < numberUnsatisfied_ ; i++){ int iObject = list_[i]; int nwayIndex = iObject - start_nway_; const BonNWayObject * nway = ASSERTED_CAST<const BonNWayObject *>(solver->object(iObject)); size_t n = nway->numberMembers(); const int * vars = nway->members(); for(size_t j = 0 ; j < n ; j++){ int iCol = vars[j]; if(upper[iCol] < lower[iCol] + 0.5) continue;//variable already fixed to lower buund if(bounds_[nwayIndex][j] > cutoff){//It can be fixed solver->setColUpper(iCol, lower[iCol]); n_fixed ++; } } } if(n_fixed && log_ > 1) printf("NWAY: Fixed %i variables\n", n_fixed); } assert(bounds_.size() == unit_changes_.size()); assert(unit_changes_.size() == info->solver_->numberObjects() - start_nway_); //Just take the most usefull bestObjectIndex_ = list_[0]; bestWhichWay_ = 1; OsiObject * obj = solver->objects()[bestObjectIndex_]; obj->setWhichWay(bestWhichWay_); if(log_ > 1){ printf("level %i branch on %i bound %g usefullness %g.\n", info->depth_, bestObjectIndex_ - start_nway_, obj_val, - useful_[0]); } if(n_fixed) return 2; return 0; } if(log_ > 0) printf("Restarting strong branching loop....\n\n"); numberStrongIterations_ = 0; numberStrongDone_ = 0; int numberLeft = numberOnList_;//Always do full strong at root int returnCode=0; bestObjectIndex_ = -1; bestWhichWay_ = -1; firstForcedObjectIndex_ = -1; firstForcedWhichWay_ =-1; double best_score = -COIN_DBL_MAX; int bestPriority=0; int n = solver->getNumCols(); std::vector<double> saveLower(n); std::vector<double> saveUpper(n); std::copy(info->lower_, info->lower_ + n, saveLower.begin()); std::copy(info->upper_, info->upper_ + n, saveUpper.begin()); solver->markHotStart(); for (int i=0;i<numberLeft;i++) { int iObject = list_[i]; const int objectPriority = solver->object(iObject)->priority(); if (objectPriority >= bestPriority){ bestPriority = objectPriority; } else break; double score; int r_val = doStrongBranching(solver, info, iObject, saveLower.data(), saveUpper.data(), score); if(r_val == -1) { if(log_ > 0) std::cout<<"This is Infeasible"<<std::endl; returnCode = -1; break; } if(do_fixings_ > 1 && r_val == 1 && info->depth_ == 0) returnCode=2; //Compute Score if(log_ > 0) printf("Usefullness from strong branching on %i : %g\n", iObject - start_nway_, score); if(score > best_score){//We have a winner best_score = score; bestObjectIndex_ = iObject; bestWhichWay_ = 0; } if (r_val==3) { returnCode = 3; // max time - just choose one if(bestObjectIndex_ < 0){ bestObjectIndex_ = list_[0]; bestWhichWay_ = 0; } break; } } solver->unmarkHotStart(); return returnCode; }
/* Choose a variable Returns - -1 Node is infeasible 0 Normal termination - we have a candidate 1 All looks satisfied - no candidate 2 We can change the bound on a variable - but we also have a strong branching candidate 3 We can change the bound on a variable - but we have a non-strong branching candidate 4 We can change the bound on a variable - no other candidates We can pick up branch from whichObject() and whichWay() We can pick up a forced branch (can change bound) from whichForcedObject() and whichForcedWay() If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() */ int OsiChooseStrong::chooseVariable( OsiSolverInterface * solver, OsiBranchingInformation *info, bool fixVariables) { if (numberUnsatisfied_) { const double* upTotalChange = pseudoCosts_.upTotalChange(); const double* downTotalChange = pseudoCosts_.downTotalChange(); const int* upNumber = pseudoCosts_.upNumber(); const int* downNumber = pseudoCosts_.downNumber(); int numberBeforeTrusted = pseudoCosts_.numberBeforeTrusted(); // Somehow we can get here with it 0 ! if (!numberBeforeTrusted) { numberBeforeTrusted=5; pseudoCosts_.setNumberBeforeTrusted(numberBeforeTrusted); } int numberLeft = CoinMin(numberStrong_-numberStrongDone_,numberUnsatisfied_); int numberToDo=0; resetResults(numberLeft); int returnCode=0; bestObjectIndex_ = -1; bestWhichWay_ = -1; firstForcedObjectIndex_ = -1; firstForcedWhichWay_ =-1; double bestTrusted=-COIN_DBL_MAX; for (int i=0;i<numberLeft;i++) { int iObject = list_[i]; if (upNumber[iObject]<numberBeforeTrusted||downNumber[iObject]<numberBeforeTrusted) { results_[numberToDo++] = OsiHotInfo(solver, info, solver->objects(), iObject); } else { const OsiObject * obj = solver->object(iObject); double upEstimate = (upTotalChange[iObject]*obj->upEstimate())/upNumber[iObject]; double downEstimate = (downTotalChange[iObject]*obj->downEstimate())/downNumber[iObject]; double value = MAXMIN_CRITERION*CoinMin(upEstimate,downEstimate) + (1.0-MAXMIN_CRITERION)*CoinMax(upEstimate,downEstimate); if (value > bestTrusted) { bestObjectIndex_=iObject; bestWhichWay_ = upEstimate>downEstimate ? 0 : 1; bestTrusted = value; } } } int numberFixed=0; if (numberToDo) { returnCode = doStrongBranching(solver, info, numberToDo, 1); if (returnCode>=0&&returnCode<=2) { if (returnCode) { returnCode=4; if (bestObjectIndex_>=0) returnCode=3; } for (int i=0;i<numResults_;i++) { int iObject = results_[i].whichObject(); double upEstimate; if (results_[i].upStatus()!=1) { assert (results_[i].upStatus()>=0); upEstimate = results_[i].upChange(); } else { // infeasible - just say expensive if (info->cutoff_<1.0e50) upEstimate = 2.0*(info->cutoff_-info->objectiveValue_); else upEstimate = 2.0*fabs(info->objectiveValue_); if (firstForcedObjectIndex_ <0) { firstForcedObjectIndex_ = iObject; firstForcedWhichWay_ =0; } numberFixed++; if (fixVariables) { const OsiObject * obj = solver->object(iObject); OsiBranchingObject * branch = obj->createBranch(solver,info,0); branch->branch(solver); delete branch; } } double downEstimate; if (results_[i].downStatus()!=1) { assert (results_[i].downStatus()>=0); downEstimate = results_[i].downChange(); } else { // infeasible - just say expensive if (info->cutoff_<1.0e50) downEstimate = 2.0*(info->cutoff_-info->objectiveValue_); else downEstimate = 2.0*fabs(info->objectiveValue_); if (firstForcedObjectIndex_ <0) { firstForcedObjectIndex_ = iObject; firstForcedWhichWay_ =1; } numberFixed++; if (fixVariables) { const OsiObject * obj = solver->object(iObject); OsiBranchingObject * branch = obj->createBranch(solver,info,1); branch->branch(solver); delete branch; } } double value = MAXMIN_CRITERION*CoinMin(upEstimate,downEstimate) + (1.0-MAXMIN_CRITERION)*CoinMax(upEstimate,downEstimate); if (value>bestTrusted) { bestTrusted = value; bestObjectIndex_ = iObject; bestWhichWay_ = upEstimate>downEstimate ? 0 : 1; // but override if there is a preferred way const OsiObject * obj = solver->object(iObject); if (obj->preferredWay()>=0&&obj->infeasibility()) bestWhichWay_ = obj->preferredWay(); if (returnCode) returnCode=2; } } } else if (returnCode==3) { // max time - just choose one bestObjectIndex_ = list_[0]; bestWhichWay_ = 0; returnCode=0; } } else { bestObjectIndex_=list_[0]; } if ( bestObjectIndex_ >=0 ) { OsiObject * obj = solver->objects()[bestObjectIndex_]; obj->setWhichWay( bestWhichWay_); } if (numberFixed==numberUnsatisfied_&&numberFixed) returnCode=4; return returnCode; } else { return 1; } }