/* This is a utility function which does strong branching on a list of objects and stores the results in OsiHotInfo.objects. On entry the object sequence is stored in the OsiHotInfo object and maybe more. It returns - -1 - one branch was infeasible both ways 0 - all inspected - nothing can be fixed 1 - all inspected - some can be fixed (returnCriterion==0) 2 - may be returning early - one can be fixed (last one done) (returnCriterion==1) 3 - returning because max time */ int OsiChooseStrong::doStrongBranching( OsiSolverInterface * solver, OsiBranchingInformation *info, int numberToDo, int returnCriterion) { // Might be faster to extend branch() to return bounds changed double * saveLower = NULL; double * saveUpper = NULL; int numberColumns = solver->getNumCols(); solver->markHotStart(); const double * lower = info->lower_; const double * upper = info->upper_; saveLower = CoinCopyOfArray(info->lower_,numberColumns); saveUpper = CoinCopyOfArray(info->upper_,numberColumns); numResults_=0; int returnCode=0; double timeStart = CoinCpuTime(); for (int iDo=0;iDo<numberToDo;iDo++) { OsiHotInfo * result = results_ + iDo; // For now just 2 way OsiBranchingObject * branch = result->branchingObject(); assert (branch->numberBranches()==2); /* Try the first direction. Each subsequent call to branch() performs the specified branch and advances the branch object state to the next branch alternative.) */ OsiSolverInterface * thisSolver = solver; if (branch->boundBranch()) { // ordinary branch->branch(solver); // maybe we should check bounds for stupidities here? solver->solveFromHotStart() ; } else { // adding cuts or something thisSolver = solver->clone(); branch->branch(thisSolver); // set hot start iterations int limit; thisSolver->getIntParam(OsiMaxNumIterationHotStart,limit); thisSolver->setIntParam(OsiMaxNumIteration,limit); thisSolver->resolve(); } // can check if we got solution // status is 0 finished, 1 infeasible and 2 unfinished and 3 is solution int status0 = result->updateInformation(thisSolver,info,this); numberStrongIterations_ += thisSolver->getIterationCount(); if (status0==3) { // new solution already saved if (trustStrongForSolution_) { info->cutoff_ = goodObjectiveValue_; status0=0; } } if (solver!=thisSolver) delete thisSolver; // Restore bounds for (int j=0;j<numberColumns;j++) { if (saveLower[j] != lower[j]) solver->setColLower(j,saveLower[j]); if (saveUpper[j] != upper[j]) solver->setColUpper(j,saveUpper[j]); } /* Try the next direction */ thisSolver = solver; if (branch->boundBranch()) { // ordinary branch->branch(solver); // maybe we should check bounds for stupidities here? solver->solveFromHotStart() ; } else { // adding cuts or something thisSolver = solver->clone(); branch->branch(thisSolver); // set hot start iterations int limit; thisSolver->getIntParam(OsiMaxNumIterationHotStart,limit); thisSolver->setIntParam(OsiMaxNumIteration,limit); thisSolver->resolve(); } // can check if we got solution // status is 0 finished, 1 infeasible and 2 unfinished and 3 is solution int status1 = result->updateInformation(thisSolver,info,this); numberStrongDone_++; numberStrongIterations_ += thisSolver->getIterationCount(); if (status1==3) { // new solution already saved if (trustStrongForSolution_) { info->cutoff_ = goodObjectiveValue_; status1=0; } } if (solver!=thisSolver) delete thisSolver; // Restore bounds for (int j=0;j<numberColumns;j++) { if (saveLower[j] != lower[j]) solver->setColLower(j,saveLower[j]); if (saveUpper[j] != upper[j]) solver->setColUpper(j,saveUpper[j]); } /* End of evaluation for this candidate variable. Possibilities are: * Both sides below cutoff; this variable is a candidate for branching. * Both sides infeasible or above the objective cutoff: no further action here. Break from the evaluation loop and assume the node will be purged by the caller. * One side below cutoff: Install the branch (i.e., fix the variable). Possibly break from the evaluation loop and assume the node will be reoptimised by the caller. */ numResults_++; if (status0==1&&status1==1) { // infeasible returnCode=-1; break; // exit loop } else if (status0==1||status1==1) { numberStrongFixed_++; if (!returnCriterion) { returnCode=1; } else { returnCode=2; break; } } bool hitMaxTime = ( CoinCpuTime()-timeStart > info->timeRemaining_); if (hitMaxTime) { returnCode=3; break; } } delete [] saveLower; delete [] saveUpper; // Delete the snapshot solver->unmarkHotStart(); return returnCode; }