/*===========================================================================* Scan through the variables and select those that are binary and are at a fractional level. *===========================================================================*/ void CglClique::selectFractionalBinaries(const OsiSolverInterface& si) { // extract the primal tolerance from the solver double lclPetol = 0.0; si.getDblParam(OsiPrimalTolerance, lclPetol); const int numcols = si.getNumCols(); if (petol<0.0) { // do all if not too many int n=0; for (int i = 0; i < numcols; ++i) { if (si.isBinary(i)) n++; } if (n<5000) lclPetol=-1.0e-5; } const double* x = si.getColSolution(); std::vector<int> fracind; int i; for (i = 0; i < numcols; ++i) { if (si.isBinary(i) && x[i] > lclPetol && x[i] < 1-petol) fracind.push_back(i); } sp_numcols = static_cast<int>(fracind.size()); sp_orig_col_ind = new int[sp_numcols]; sp_colsol = new double[sp_numcols]; for (i = 0; i < sp_numcols; ++i) { sp_orig_col_ind[i] = fracind[i]; sp_colsol[i] = x[fracind[i]]; } }
int main(void) { // Create a problem pointer. We use the base class here. OsiSolverInterface *si; // When we instantiate the object, we need a specific derived class. si = new OsiClpSolverInterface; // Read in an mps file. This one's from the MIPLIB library. si->readMps("../../Data/Sample/p0033"); // Solve the (relaxation of the) problem si->initialSolve(); // Check the solution if ( si->isProvenOptimal() ) { std::cout << "Found optimal solution!" << std::endl; std::cout << "Objective value is " << si->getObjValue() << std::endl; int n = si->getNumCols(); const double *solution; solution = si->getColSolution(); // We could then print the solution or examine it. } else { std::cout << "Didn't find optimal solution." << std::endl; // Could then check other status functions. } return 0; }
//------------------------------------------------------------------- // Generate Stored cuts //------------------------------------------------------------------- void CglStoredUser::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo info) const { // Get basic problem information const double * solution = si.getColSolution(); if (info.inTree&&info.pass>numberPasses_) { // only continue if integer feasible int numberColumns=si.getNumCols(); int i; const double * colUpper = si.getColUpper(); const double * colLower = si.getColLower(); int numberAway=0; for (i=0;i<numberColumns;i++) { double value = solution[i]; // In case slightly away from bounds value = CoinMax(colLower[i],value); value = CoinMin(colUpper[i],value); if (si.isInteger(i)&&fabs(value-fabs(value+0.5))>1.0e-5) numberAway++; } if (numberAway) return; // let code branch } int numberRowCuts = cuts_.sizeRowCuts(); for (int i=0;i<numberRowCuts;i++) { const OsiRowCut * rowCutPointer = cuts_.rowCutPtr(i); double violation = rowCutPointer->violated(solution); if (violation>=requiredViolation_) cs.insert(*rowCutPointer); } }
// Create result void OsiSolverResult::createResult(const OsiSolverInterface &solver, const double *lowerBefore, const double *upperBefore) { delete[] primalSolution_; delete[] dualSolution_; if (solver.isProvenOptimal() && !solver.isDualObjectiveLimitReached()) { objectiveValue_ = solver.getObjValue() * solver.getObjSense(); CoinWarmStartBasis *basis = dynamic_cast< CoinWarmStartBasis * >(solver.getWarmStart()); assert(basis); basis_ = *basis; int numberRows = basis_.getNumArtificial(); int numberColumns = basis_.getNumStructural(); assert(numberColumns == solver.getNumCols()); assert(numberRows == solver.getNumRows()); primalSolution_ = CoinCopyOfArray(solver.getColSolution(), numberColumns); dualSolution_ = CoinCopyOfArray(solver.getRowPrice(), numberRows); fixed_.addBranch(-1, numberColumns, lowerBefore, solver.getColLower(), upperBefore, solver.getColUpper()); } else { // infeasible objectiveValue_ = COIN_DBL_MAX; basis_ = CoinWarmStartBasis(); ; primalSolution_ = NULL; dualSolution_ = NULL; } }
/* Generate cuts for the model data contained in si. The generated cuts are inserted into and returned in the collection of cuts cs. */ bool AbcCutGenerator::generateCuts( OsiCuts & cs , bool fullScan) { int howOften = whenCutGenerator_; if (howOften == -100) return false; if (howOften > 0) howOften = howOften % 1000000; else howOften = 1; if (!howOften) howOften = 1; bool returnCode = false; OsiSolverInterface * solver = model_->solver(); #if defined(ABC_DEBUG_MORE) std::cout << "model_->getNodeCount() = " << model_->getNodeCount() << std::endl; #endif if (fullScan || (model_->getNodeCount() % howOften) == 0 ) { CglProbing* generator = dynamic_cast<CglProbing*>(generator_); if (!generator) { generator_->generateCuts(*solver,cs); } else { // Probing - return tight column bounds CglTreeInfo info; generator->generateCutsAndModify(*solver,cs,&info); const double * tightLower = generator->tightLower(); const double * lower = solver->getColLower(); const double * tightUpper = generator->tightUpper(); const double * upper = solver->getColUpper(); const double * solution = solver->getColSolution(); int j; int numberColumns = solver->getNumCols(); double primalTolerance = 1.0e-8; for (j=0; j<numberColumns; j++) { if (tightUpper[j] == tightLower[j] && upper[j] > lower[j]) { // fix solver->setColLower(j, tightLower[j]); solver->setColUpper(j, tightUpper[j]); if (tightLower[j] > solution[j] + primalTolerance || tightUpper[j] < solution[j] - primalTolerance) returnCode = true; } } } } return returnCode; }
// Creates a branching object from this infeasible object. BcpsBranchObject * BlisObjectInt::createBranchObject(BcpsModel *m, int direction) const { BlisModel *model = dynamic_cast<BlisModel* >(m); OsiSolverInterface * solver = model->solver(); double integerTolerance = model->BlisPar()->entry(BlisParams::integerTol); const double * solution = solver->getColSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnIndex_]; //std::cout << "COL"<< columnIndex_ << ": x = " << value << std::endl; // Force value in bounds. value = CoinMax(value, lower[columnIndex_]); value = CoinMin(value, upper[columnIndex_]); double nearest = floor(value + 0.5); assert (upper[columnIndex_] > lower[columnIndex_]); int hotstartStrategy = model->getHotstartStrategy(); if (hotstartStrategy <= 0) { if (fabs(value - nearest) < integerTolerance) { // Already integeral. std::cout << "ERROR: COL" << columnIndex_ << ": x=" << value << ", nearest=" << nearest << ", intTol=" << integerTolerance << std::endl; assert(0); } } else { const double * incumbent = model->incumbent(); double targetValue = incumbent[columnIndex_]; if (direction > 0) { value = targetValue - 0.1; } else { value = targetValue + 0.1; } } return new BlisBranchObjectInt(model, objectIndex_, direction, value); }
void LinearCutsGenerator::generateCuts(const OsiSolverInterface &solver, OsiCuts &cs, const CglTreeInfo info) const { //const OsiTMINLPInterface * tmp = dynamic_cast<const OsiTMINLPInterface *>(&solver); OsiTMINLPInterface * nlp = dynamic_cast<OsiTMINLPInterface *>(solver.clone());//const_cast<OsiTMINLPInterface *>(tmp); assert(nlp); OuterApprox oa; //si.writeMps("toto"); int numberRows = nlp->getNumRows(); for(int i = 0 ; i < 5 ; i++){ nlp->resolve(); OsiClpSolverInterface si; oa(*nlp, &si, solver.getColSolution(), true); si.resolve(); OsiCuts cuts; for(std::list<Coin::SmartPtr<CuttingMethod> >::const_iterator i = methods_.begin() ; i != methods_.end() ; i++){ (*i)->cgl->generateCuts(si, cuts, info); } std::vector<OsiRowCut *> mycuts(cuts.sizeRowCuts()); for(int i = 0 ; i < cuts.sizeRowCuts() ; i++){ mycuts[i] = cuts.rowCutPtr(i); cs.insert(*mycuts[i]); } nlp->applyRowCuts(mycuts.size(), const_cast<const OsiRowCut **> (&mycuts[0])); } // Take off slack cuts std::vector<int> kept; int numberRowsNow = nlp->getNumRows(); int * del = new int [numberRowsNow-numberRows]; nlp->resolve(); const double * activity = nlp->getRowActivity(); const double * lb = nlp->getRowLower(); const double * ub = nlp->getRowUpper(); CoinRelFltEq eq(1e-06); //int nDelete=0; for (int i=numberRowsNow -1;i>=numberRows;i--) { if ( !(eq(activity[i], lb[i]) || eq(activity[i], ub[i])) ) cs.eraseRowCut(i - numberRows); } delete [] del; delete nlp; }
bool OaDecompositionBase::OaDebug::checkInteger(const OsiSolverInterface &nlp, std::ostream & os) const { const double * colsol = nlp.getColSolution(); int numcols = nlp.getNumCols(); for (int i = 0 ; i < numcols ; i++) { if (nlp.isInteger(i)) { if (fabs(colsol[i]) - floor(colsol[i] + 0.5) > 1e-07) { std::cerr<<"Integer infeasible point (should not be), integer infeasibility for variable "<<i <<" is, "<<fabs(colsol[i] - floor(colsol[i] + 0.5))<<std::endl; } } return true; } }
// Compute the infeasibility based on currently relax solution. double BlisObjectInt::infeasibility(BcpsModel *m, int & preferredWay) const { BlisModel * model = dynamic_cast<BlisModel *>(m); OsiSolverInterface * solver = model->solver(); const double * solution = solver->getColSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnIndex_]; value = std::max(value, lower[columnIndex_]); value = std::min(value, upper[columnIndex_]); //printf("%d %g %g %g %g\n",columnIndex_,value,lower[columnIndex_], // solution[columnIndex_],upper[columnIndex_]); double nearest = floor(value + (1.0 - breakEven_)); double integerTolerance = model->BlisPar()->entry(BlisParams::integerTol); if (nearest > value) { preferredWay = 1; } else { preferredWay = -1; } double weight = fabs(value - nearest); // normalize so weight is 0.5 at break even if (nearest < value) { weight = (0.5/breakEven_) * weight; } else { weight = (0.5/(1.0 - breakEven_)) * weight; } if (fabs(value - nearest) <= integerTolerance) { return 0.0; } else { return weight; } }
// Returns true if current solution satsifies one side of branch bool OsiSolverBranch::feasibleOneWay(const OsiSolverInterface & solver) const { bool feasible = false; int numberColumns = solver.getNumCols(); const double * columnLower = solver.getColLower(); const double * columnUpper = solver.getColUpper(); const double * columnSolution = solver.getColSolution(); double primalTolerance; solver.getDblParam(OsiPrimalTolerance,primalTolerance); for (int base = 0; base<4; base +=2) { feasible=true; int i; for (i=start_[base];i<start_[base+1];i++) { int iColumn = indices_[i]; if (iColumn<numberColumns) { double value = CoinMax(bound_[i],columnLower[iColumn]); if (columnSolution[iColumn]<value-primalTolerance) { feasible=false; break; } } else { abort(); // do later (other stuff messed up anyway - e.g. CBC) } } if (!feasible) break; for (i=start_[base+1];i<start_[base+2];i++) { int iColumn = indices_[i]; if (iColumn<numberColumns) { double value = CoinMin(bound_[i],columnUpper[iColumn]); if (columnSolution[iColumn]>value+primalTolerance) { feasible=false; break; } } else { abort(); // do later (other stuff messed up anyway - e.g. CBC) } } if (feasible) break; // OK this way } return feasible; }
BcpsBranchObject * BlisObjectInt::preferredNewFeasible(BcpsModel *m) const { BlisModel *model = dynamic_cast<BlisModel* >(m); OsiSolverInterface * solver = model->solver(); double value = solver->getColSolution()[columnIndex_]; double nearest = floor(value + 0.5); double integerTolerance = model->BlisPar()->entry(BlisParams::integerTol); assert(fabs(value - nearest) <= integerTolerance); double dj = solver->getObjSense()*solver->getReducedCost()[columnIndex_]; BlisBranchObjectInt * object = NULL; if (dj >= 0.0) { // Better go down if (nearest > originalLower_ + 0.5) { // Has room to go down object = new BlisBranchObjectInt(model, objectIndex_, -1, nearest - 1.0, nearest - 1.0); } } else { // Better go up if (nearest < originalUpper_ - 0.5) { // Has room to go up object = new BlisBranchObjectInt(model, objectIndex_, -1, nearest + 1.0, nearest + 1.0); } } return object; }
// Generate cuts void CglFakeClique::generateCuts(const OsiSolverInterface& si, OsiCuts & cs, const CglTreeInfo info) const { if (fakeSolver_) { assert (si.getNumCols()==fakeSolver_->getNumCols()); fakeSolver_->setColLower(si.getColLower()); fakeSolver_->setColSolution(si.getColSolution()); fakeSolver_->setColUpper(si.getColUpper()); CglClique::generateCuts(*fakeSolver_,cs,info); if (probing_) { // get and set branch and bound cutoff double cutoff; si.getDblParam(OsiDualObjectiveLimit,cutoff); fakeSolver_->setDblParam(OsiDualObjectiveLimit,cutoff); probing_->generateCuts(*fakeSolver_,cs,info); } } else { // just use real solver CglClique::generateCuts(si,cs,info); } }
void CglClique::selectFractionals(const OsiSolverInterface& si) { // extract the primal tolerance from the solver double lclPetol = 0.0; si.getDblParam(OsiPrimalTolerance, lclPetol); const int numcols = si.getNumCols(); const double* x = si.getColSolution(); std::vector<int> fracind; int i; for (i = 0; i < numcols; ++i) { if (x[i] > lclPetol && x[i] < 1-lclPetol) fracind.push_back(i); } sp_numcols = static_cast<int>(fracind.size()); sp_orig_col_ind = new int[sp_numcols]; sp_colsol = new double[sp_numcols]; for (i = 0; i < sp_numcols; ++i) { sp_orig_col_ind[i] = fracind[i]; sp_colsol[i] = x[fracind[i]]; } }
// Force this object within exiting bounds, then fix the bounds at the // the nearest integer value. Assume solution value is within tolerance of // the nearest integer. void BlisObjectInt::feasibleRegion(BcpsModel *m) { BlisModel *model = dynamic_cast<BlisModel* >(m); OsiSolverInterface * solver = model->solver(); const double * solution = solver->getColSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnIndex_]; // 1) Force value to be in bounds. value = CoinMax(value, lower[columnIndex_]); value = CoinMin(value, upper[columnIndex_]); double nearest = floor(value + 0.5); // 2) Fix variable at the nearest integer assert (fabs(value - nearest) <= 0.01); solver->setColLower(columnIndex_, nearest); solver->setColUpper(columnIndex_, nearest); }
//############################################################################# bfSol* MibSHeuristic::getBilevelSolution(const double * sol, double origLower) { /* Find a bilevel feasible solution by solving the LL problem for a fixed UL solution, given by the UL portion of sol */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); OsiSolverInterface * lSolver = model->bS_->setUpModel(oSolver, true, sol); //double uObjSense(model->getSolver()->getObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double etol(etol_); int tCols(uCols + lCols); int i(0); if(0){ lSolver->writeLp("bilevelsolver"); std::cout << "Original Lower-level Solution Value: " << origLower << std::endl; for(i = 0; i < lCols; i++){ std::cout << "lowsol[" << i << "]: " << sol[lColIndices[i]] << std::endl; } } if(0){ dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); } lSolver->branchAndBound(); if(lSolver->isProvenOptimal()){ double objVal(0.0); double lowerObj(lSolver->getObjValue()); double * colsol = new double[tCols]; for(i = 0; i < uCols; i++){ colsol[uColIndices[i]] = sol[uColIndices[i]]; } if(0){ std::cout << "candidate lower solution value: " << origLower << std::endl; std::cout << "actual lower solution value: " << lowerObj << std::endl; } if(fabs(origLower - lowerObj) < etol){ //original solution was bilevel feasible if(0) std::cout << "Original solution was bilevel feasible:" << std::endl; for(i = 0; i < lCols; i++){ if(0){ std::cout << "lowerportion[" << i << "]: " << sol[lColIndices[i]] << std::endl; } colsol[lColIndices[i]] = sol[lColIndices[i]]; } } else{ if(0){ std::cout << "Not bilevel feasible." << std::endl; } for(i = 0; i < lCols; i++){ if(0){ std::cout << "newportion[" << i << "]: " << lSolver->getColSolution()[i] << std::endl; } colsol[lColIndices[i]] = lSolver->getColSolution()[i]; } } for(i = 0; i < tCols; i++) objVal += colsol[i] * oSolver->getObjCoefficients()[i]; bfSol * bfsol = new bfSol(objVal, colsol); delete lSolver; return bfsol; } else{ delete lSolver; return NULL; } }
//############################################################################# void MibSHeuristic::lowerObjHeuristic() { /* optimize wrt to lower-level objective over current feasible lp feasible region */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); //OsiSolverInterface * hSolver = new OsiCbcSolverInterface(); OsiSolverInterface* hSolver = new OsiSymSolverInterface(); double objSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); //int tCols(lCols + uCols); int tCols(oSolver->getNumCols()); //assert(tCols == oSolver->getNumCols()); hSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); int j(0); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) hSolver->setInteger(j); } double * nObjCoeffs = new double[tCols]; int i(0), index(0); CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i]; } //MibS objective sense is the opposite of OSI's! hSolver->setObjSense(objSense); hSolver->setObjective(nObjCoeffs); //double cutoff(model->getCutoff()); double cutoff(model->getKnowledgeBroker()->getIncumbentValue()); if(model->getNumSolutions()){ CoinPackedVector objCon; //double rhs(cutoff * objSense); //double smlTol(1.0); double rhs(cutoff); for(i = 0; i < tCols; i++){ objCon.insert(i, oSolver->getObjCoefficients()[i] * oSolver->getObjSense()); } hSolver->addRow(objCon, - hSolver->getInfinity(), rhs); } if(0) hSolver->writeLp("lobjheurstic"); if(0){ dynamic_cast<OsiCbcSolverInterface *> (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("max_active_nodes", 1); } hSolver->branchAndBound(); if(hSolver->isProvenOptimal()){ double upperObjVal(0.0); /*****************NEW ******************/ MibSSolution *mibSol = NULL; OsiSolverInterface * lSolver = model->bS_->setUpModel(hSolver, true); if(0){ lSolver->writeLp("tmp"); } if(0){ dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); } lSolver->branchAndBound(); if (lSolver->isProvenOptimal()){ const double * sol = hSolver->getColSolution(); double objVal(lSolver->getObjValue() * objSense); double etol(etol_); double lowerObj = getLowerObj(sol, objSense); double * optUpperSolutionOrd = new double[uCols]; double * optLowerSolutionOrd = new double[lCols]; CoinZeroN(optUpperSolutionOrd, uCols); CoinZeroN(optLowerSolutionOrd, lCols); if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ for(i = 0; i < tCols; i++) upperObjVal += hSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; mibSol = new MibSSolution(hSolver->getNumCols(), hSolver->getColSolution(), upperObjVal, model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } else{ /* solution is not bilevel feasible, create one that is */ const double * uSol = hSolver->getColSolution(); const double * lSol = lSolver->getColSolution(); int numElements(hSolver->getNumCols()); int i(0), pos(0), index(0); double * lpSolution = new double[numElements]; double upperObj(0.0); //FIXME: problem is still here. indices may be wrong. //also is all this necessary, or can we just paste together uSol and lSol? //this may be an old comment for(i = 0; i < numElements; i++){ pos = model->bS_->binarySearch(0, lCols - 1, i, lColIndices); if(pos < 0){ pos = model->bS_->binarySearch(0, uCols - 1, i, uColIndices); if (pos >= 0){ optUpperSolutionOrd[pos] = uSol[i]; } } else{ optLowerSolutionOrd[pos] = lSol[pos]; } } for(i = 0; i < uCols; i++){ index = uColIndices[i]; lpSolution[index] = optUpperSolutionOrd[i]; upperObj += optUpperSolutionOrd[i] * oSolver->getObjCoefficients()[index]; } for(i = 0; i < lCols; i++){ index = lColIndices[i]; lpSolution[index] = optLowerSolutionOrd[i]; upperObj += optLowerSolutionOrd[i] * oSolver->getObjCoefficients()[index]; } if(model->checkUpperFeasibility(lpSolution)){ mibSol = new MibSSolution(hSolver->getNumCols(), lpSolution, upperObj * oSolver->getObjSense(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } delete [] lpSolution; } } delete lSolver; } delete hSolver; }
//############################################################################# void MibSHeuristic::objCutHeuristic() { /* Solve the LP relaxation with the new constraint d^2 y <= d^y* */ MibSModel * model = MibSModel_; //OsiSolverInterface * oSolver = model->origLpSolver_; OsiSolverInterface * oSolver = model->getSolver(); //OsiSolverInterface * hSolver = new OsiCbcSolverInterface(); OsiSolverInterface * hSolver = new OsiSymSolverInterface(); double objSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int tCols(lCols + uCols); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); hSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); int j(0); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) hSolver->setInteger(j); } double * optLowerSolutionOrd = model->bS_->optLowerSolutionOrd_; CoinPackedVector objCon; int i(0), index(0); double rhs(0.0); for(i = 0; i < lCols; i++){ index = lColIndices[i]; objCon.insert(index, lObjCoeffs[i] * objSense); //should this be ordered? and should lObjCoeffs by at index? //rhs += optLowerSolutionOrd_[i] * lObjCoeffs[i] * objSense; rhs += optLowerSolutionOrd[i] * lObjCoeffs[i] * objSense; } //Hmm, I think this was wrong before...? // hSolver->addRow(objCon, - hSolver->getInfinity(), rhs); hSolver->addRow(objCon, rhs, hSolver->getInfinity()); /* optimize w.r.t. to the UL objective with the new row */ if(0){ dynamic_cast<OsiCbcSolverInterface *> (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("max_active_nodes", 1); } hSolver->branchAndBound(); if(0) hSolver->writeLp("objcutheuristic"); if(hSolver->isProvenOptimal()){ MibSSolution *mibSol = NULL; OsiSolverInterface * lSolver = model->bS_->setUpModel(hSolver, true); if(0){ dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); } lSolver->branchAndBound(); const double * sol = hSolver->getColSolution(); double objVal(lSolver->getObjValue() * objSense); double etol(etol_); double lowerObj = getLowerObj(sol, objSense); double * optUpperSolutionOrd = new double[uCols]; double * optLowerSolutionOrd = new double[lCols]; CoinZeroN(optUpperSolutionOrd, uCols); CoinZeroN(optLowerSolutionOrd, lCols); if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ mibSol = new MibSSolution(hSolver->getNumCols(), hSolver->getColSolution(), hSolver->getObjValue(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } else{ /* solution is not bilevel feasible, create one that is */ const double * uSol = hSolver->getColSolution(); const double * lSol = lSolver->getColSolution(); //int numElements(lSolver->getNumCols()); int numElements(hSolver->getNumCols()); int i(0), pos(0), index(0); double * lpSolution = new double[numElements]; double upperObj(0.0); //FIXME: problem is still here. indices may be wrong. //also is all this necessary, or can we just paste together uSol and lSol? for(i = 0; i < numElements; i++){ //index = indices[i]; pos = model->bS_->binarySearch(0, lCols - 1, i, lColIndices); if(pos < 0){ pos = model->bS_->binarySearch(0, uCols - 1, i, uColIndices); //optUpperSolutionOrd[pos] = values[i]; //optUpperSolutionOrd[pos] = uSol[pos]; if (pos >= 0){ optUpperSolutionOrd[pos] = uSol[i]; } } else{ //optLowerSolutionOrd[pos] = lSol[i]; optLowerSolutionOrd[pos] = lSol[pos]; } } for(i = 0; i < uCols; i++){ index = uColIndices[i]; lpSolution[index] = optUpperSolutionOrd[i]; upperObj += optUpperSolutionOrd[i] * hSolver->getObjCoefficients()[index]; } for(i = 0; i < lCols; i++){ index = lColIndices[i]; lpSolution[index] = optLowerSolutionOrd[i]; upperObj += optLowerSolutionOrd[i] * hSolver->getObjCoefficients()[index]; } if(model->checkUpperFeasibility(lpSolution)){ mibSol = new MibSSolution(hSolver->getNumCols(), lpSolution, upperObj * hSolver->getObjSense(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } delete [] lpSolution; } delete lSolver; } delete hSolver; }
//############################################################################# mcSol MibSHeuristic::solveSubproblem(double beta) { /* optimize wrt to weighted upper-level objective over current feasible lp feasible region */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); //OsiSolverInterface * sSolver = new OsiCbcSolverInterface(); OsiSolverInterface* sSolver = new OsiSymSolverInterface(); //sSolver = oSolver->clone(); //OsiSolverInterface * sSolver = tmpSolver; //OsiSolverInterface * tmpSolver = new OsiSolverInterface(oSolver); double uObjSense(oSolver->getObjSense()); double lObjSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); const double * uObjCoeffs = oSolver->getObjCoefficients(); double etol(etol_); int tCols(uCols + lCols); assert(tCols == oSolver->getNumCols()); sSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); int j(0); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) sSolver->setInteger(j); } double * nObjCoeffs = new double[tCols]; int i(0), index(0); CoinZeroN(nObjCoeffs, tCols); /* Multiply the UL columns of the UL objective by beta */ for(i = 0; i < uCols; i++){ index = uColIndices[i]; if(fabs(uObjCoeffs[index]) > etol) nObjCoeffs[index] = beta * uObjCoeffs[index] * uObjSense; else nObjCoeffs[index] = 0.0; } /* Multiply the LL columns of the UL objective by beta */ for(i = 0; i < lCols; i++){ index = lColIndices[i]; if(fabs(uObjCoeffs[index]) > etol) nObjCoeffs[index] = beta* uObjCoeffs[index] * uObjSense; else nObjCoeffs[index] = 0.0; } /* Add the LL columns of the LL objective multiplied by (1 - beta) */ for(i = 0; i < lCols; i++){ index = lColIndices[i]; if(fabs(lObjCoeffs[i]) > etol) nObjCoeffs[index] += (1 - beta) * lObjCoeffs[i] * lObjSense; } sSolver->setObjective(nObjCoeffs); //int i(0); if(0){ for(i = 0; i < sSolver->getNumCols(); i++){ std::cout << "betaobj " << sSolver->getObjCoefficients()[i] << std::endl; } } if(0){ sSolver->writeLp("afterbeta"); //sSolver->writeMps("afterbeta"); } if(0){ for(i = 0; i < sSolver->getNumCols(); i++){ std::cout << "obj " << sSolver->getObjCoefficients()[i] << std::endl; std::cout << "upper " << sSolver->getColUpper()[i] << std::endl; std::cout << "lower " << sSolver->getColLower()[i] << std::endl; } } if(0){ dynamic_cast<OsiCbcSolverInterface *> (sSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("max_active_nodes", 1); } //dynamic_cast<OsiSymSolverInterface *> (sSolver)->branchAndBound(); sSolver->branchAndBound(); if(sSolver->isProvenOptimal()){ if(0){ std::cout << "writing lp file." << std::endl; sSolver->writeLp("afterbeta"); //sSolver->writeMps("afterbeta"); } double upperObjVal(0.0); double lowerObjVal(0.0); for(i = 0; i < tCols; i++){ upperObjVal += sSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; if(0){ std::cout << "sSolver->getColSolution()[" << i << "] :" << sSolver->getColSolution()[i] << std::endl; } } lowerObjVal = getLowerObj(sSolver->getColSolution(), lObjSense); if(beta == 1.0){ /* fix upper-level objective to current value and reoptimize wrt to lower-level objective */ //OsiSolverInterface * nSolver = new OsiCbcSolverInterface(); OsiSolverInterface * nSolver = new OsiSymSolverInterface(); nSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) nSolver->setInteger(j); } CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i] * lObjSense; } nSolver->setObjective(nObjCoeffs); CoinPackedVector objCon; for(i = 0; i < tCols; i++){ objCon.insert(i, uObjCoeffs[i] * uObjSense); } nSolver->addRow(objCon, upperObjVal, upperObjVal); nSolver->writeLp("beta1"); if(0){ dynamic_cast<OsiCbcSolverInterface *> (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("max_active_nodes", 1); } nSolver->branchAndBound(); double * colsol = new double[tCols]; if(nSolver->isProvenOptimal()){ lowerObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } else{ //just take the current solution lowerObjVal = sSolver->getObjValue(); CoinCopyN(sSolver->getColSolution(), tCols, colsol); } delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; delete nSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } else if(beta == 0.0){ /* fix lower-level objective to current value and reoptimize wrt to upper-level objective */ //OsiSolverInterface * nSolver = new OsiCbcSolverInterface(); OsiSolverInterface * nSolver = new OsiSymSolverInterface(); nSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) nSolver->setInteger(j); } CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < tCols; i++) nObjCoeffs[i] = uObjCoeffs[i] * uObjSense; nSolver->setObjective(nObjCoeffs); CoinPackedVector objCon; for(i = 0; i < lCols; i++){ index = lColIndices[i]; objCon.insert(index, lObjCoeffs[i] * lObjSense); } nSolver->addRow(objCon, lowerObjVal, lowerObjVal); if(0){ dynamic_cast<OsiCbcSolverInterface *> (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("max_active_nodes", 1); } if(0) nSolver->writeLp("nSolver"); nSolver->branchAndBound(); double * colsol = new double[tCols]; if(nSolver->isProvenOptimal()){ upperObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } else{ upperObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; delete nSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } else{ //no optimality cut needed here. all solutions are supported. double * colsol = new double[tCols]; CoinCopyN(sSolver->getColSolution(), tCols, colsol); delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } } else{ //FIXME:SHOULD JUST TAKE THIS OUT. DELETE sSolver and remove it from above nObjCoeffs = 0; delete[] nObjCoeffs; delete sSolver; std::cout << "Subproblem is not proven optimal." << std::endl; //return NULL; //abort(); } }
//############################################################################# bfSol* MibSHeuristic::getBilevelSolution1(const double * sol) { /* Find a bilevel feasible solution by solving the LL problem for a fixed UL solution, given by the UL portion of sol */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); OsiSolverInterface * lSolver = new OsiCbcSolverInterface(oSolver); //double uObjSense(model->getSolver()->getObjSense()); double lObjSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int uRowNum = model->getUpperRowNum(); int lRowNum = model->getLowerRowNum(); int * uRowIndices = model->getUpperRowInd(); int * lRowIndices = model->getLowerRowInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); int tCols(uCols + lCols); int i(0), index(0); /* delete the UL rows */ lSolver->deleteRows(uRowNum, uRowIndices); /* Fix the UL variables to their current value in sol */ for(i = 0; i < uCols; i++){ index = uColIndices[i]; lSolver->setColLower(index, sol[index]); lSolver->setColUpper(index, sol[index]); } /* Set the objective to the LL objective coefficients */ double * nObjCoeffs = new double[tCols]; CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i] * lObjSense; } lSolver->setObjective(nObjCoeffs); if(0){ dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); } lSolver->branchAndBound(); if(lSolver->isProvenOptimal()){ double objVal(0.0); for(i = 0; i < tCols; i++) objVal += lSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; double * colsol = new double[tCols]; CoinCopyN(lSolver->getColSolution(), tCols, colsol); bfSol * bfsol = new bfSol(objVal, colsol); delete lSolver; return bfsol; } else{ delete lSolver; return NULL; } }
/** Create a set of candidate branching objects. */ int BlisBranchStrategyRel::createCandBranchObjects(int numPassesLeft) { int bStatus = 0; int i, pass, colInd; int preferDir, saveLimit; int numFirsts = 0; int numInfs = 0; int minCount = 0; int numLowerTightens = 0; int numUpperTightens = 0; double lpX, score, infeasibility, downDeg, upDeg, sumDeg = 0.0; bool roundAgain, downKeep, downGood, upKeep, upGood; int *lbInd = NULL; int *ubInd = NULL; double *newLB = NULL; double *newUB = NULL; double * saveUpper = NULL; double * saveLower = NULL; double * saveSolution = NULL; BlisModel *model = dynamic_cast<BlisModel *>(model_); OsiSolverInterface * solver = model->solver(); int numCols = model->getNumCols(); int numObjects = model->numObjects(); //int lookAhead = dynamic_cast<BlisParams*> // (model->blisPar())->entry(BlisParams::lookAhead); //------------------------------------------------------ // Check if max time is reached or no pass is left. //------------------------------------------------------ double timeLimit = model->AlpsPar()->entry(AlpsParams::timeLimit); bool maxTimeReached = (CoinCpuTime() - model->startTime_ > timeLimit); bool selectNow = false; if (maxTimeReached || !numPassesLeft) { selectNow = true; #ifdef BLIS_DEBUG printf("REL: CREATE: maxTimeReached %d, numPassesLeft %d\n", maxTimeReached, numPassesLeft); #endif } // Store first time objects. std::vector<BlisObjectInt *> firstObjects; // Store infeasible objects. std::vector<BlisObjectInt *> infObjects; // TODO: check if sorting is expensive. std::multimap<double, BlisObjectInt*, BlisPseuoGreater> sortedObjects; double objValue = solver->getObjSense() * solver->getObjValue(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); int lookAhead = dynamic_cast<BlisParams*> (model->BlisPar())->entry(BlisParams::lookAhead); BlisObjectInt * intObject = NULL; //------------------------------------------------------ // Backup solver status and mark hot start. //----------------------------------------------------- saveSolution = new double[numCols]; memcpy(saveSolution, solver->getColSolution(), numCols*sizeof(double)); saveLower = new double[numCols]; saveUpper = new double[numCols]; memcpy(saveLower, lower, numCols * sizeof(double)); memcpy(saveUpper, upper, numCols * sizeof(double)); //------------------------------------------------------ // Find the infeasible objects. // NOTE: we might go round this loop twice if we are feed in // a "feasible" solution. //------------------------------------------------------ for (pass = 0; pass < 2; ++pass) { numInfs = 0; BcpsObject * object = NULL; infObjects.clear(); firstObjects.clear(); for (i = 0; i < numObjects; ++i) { object = model->objects(i); infeasibility = object->infeasibility(model, preferDir); if (infeasibility) { ++numInfs; intObject = dynamic_cast<BlisObjectInt *>(object); if (intObject) { //score = object->pseudocost().getScore(); //tempBO = object->createBranchObject(model, preferDir); //candObjects.insert(std::make_pair(score, tempBO)); //tempBO = NULL; infObjects.push_back(intObject); if (!selectNow) { minCount = ALPS_MIN(intObject->pseudocost().getDownCount(), intObject->pseudocost().getUpCount()); if (minCount < 1) { firstObjects.push_back(intObject); } } #ifdef BLIS_DEBUG_MORE if (intObject->columnIndex() == 15) { std::cout << "x[15] = " << saveSolution[15] << std::endl; } #endif intObject = NULL; } else { // TODO: currently all are integer objects. #ifdef BLIS_DEBU assert(0); #endif } } } if (numInfs) { #ifdef BLIS_DEBUG_MORE std::cout << "REL: numInfs = " << numInfs << std::endl; #endif break; } else if (pass == 0) { // The first pass and is IP feasible. #ifdef BLIS_DEBUG std::cout << "REL: given a feasible sol" << std::endl; #endif roundAgain = false; CoinWarmStartBasis * ws = dynamic_cast<CoinWarmStartBasis*>(solver->getWarmStart()); if (!ws) break; // Force solution values within bounds for (i = 0; i < numCols; ++i) { lpX = saveSolution[i]; if (lpX < lower[i]) { saveSolution[i] = lower[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atLowerBound); } else if (lpX > upper[i]) { saveSolution[i] = upper[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atUpperBound); } } if (roundAgain) { // Need resolve and do the second round selection. solver->setWarmStart(ws); delete ws; // Resolve. solver->resolve(); if (!solver->isProvenOptimal()) { // Become infeasible, can do nothing. bStatus = -2; goto TERM_CREATE; } else { // Save new lp solution. memcpy(saveSolution, solver->getColSolution(), numCols * sizeof(double)); objValue = solver->getObjSense() * solver->getObjValue(); } } else { delete ws; break; } } } // EOF 2 pass //-------------------------------------------------- // If we have a set of first time object, // branch up and down to initialize pseudo-cost. //-------------------------------------------------- numFirsts = static_cast<int> (firstObjects.size()); if (numFirsts > 0) { CoinWarmStart * ws = solver->getWarmStart(); solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit); int maxIter = ALPS_MAX(model->getAveIterations(), 50); solver->setIntParam(OsiMaxNumIterationHotStart, maxIter); solver->markHotStart(); lbInd = new int [numFirsts]; ubInd = new int [numFirsts]; newLB = new double [numFirsts]; newUB = new double [numFirsts]; for (i = 0; i < numFirsts && bStatus != -2; ++i) { colInd = firstObjects[i]->columnIndex(); lpX = saveSolution[colInd]; BlisStrongBranch(model, objValue, colInd, lpX, saveLower, saveUpper, downKeep, downGood, downDeg, upKeep, upGood, upDeg); if(!downKeep && !upKeep) { // Both branch can be fathomed bStatus = -2; } else if (!downKeep) { // Down branch can be fathomed. lbInd[numLowerTightens] = colInd; newLB[numLowerTightens++] = ceil(lpX); //break; } else if (!upKeep) { // Up branch can be fathomed. ubInd[numUpperTightens] = colInd; newUB[numUpperTightens++] = floor(lpX); // break; } // Update pseudocost. if(downGood) { firstObjects[i]->pseudocost().update(-1, downDeg, lpX); } if(downGood) { firstObjects[i]->pseudocost().update(1, upDeg, lpX); } } //-------------------------------------------------- // Set new bounds in lp solver for resolving //-------------------------------------------------- if (bStatus != -2) { if (numUpperTightens > 0) { bStatus = -1; for (i = 0; i < numUpperTightens; ++i) { solver->setColUpper(ubInd[i], newUB[i]); } } if (numLowerTightens > 0) { bStatus = -1; for (i = 0; i < numLowerTightens; ++i) { solver->setColLower(lbInd[i], newLB[i]); } } } //-------------------------------------------------- // Unmark hotstart and recover LP solver. //-------------------------------------------------- solver->unmarkHotStart(); solver->setColSolution(saveSolution); solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit); solver->setWarmStart(ws); delete ws; } //std::cout << "REL: bStatus = " << bStatus << std::endl; if (bStatus < 0) { // Infeasible or monotone. goto TERM_CREATE; } else { // All object's pseudocost have been initialized. // Sort them, and do strong branch for the unreliable one // NOTE: it set model->savedLpSolution. // model->feasibleSolution(numIntegerInfs, numObjectInfs); sumDeg = 0.0; for (i = 0; i < numInfs; ++i) { score = infObjects[i]->pseudocost().getScore(); sumDeg += score; std::pair<const double, BlisObjectInt*> sa(score, infObjects[i]); sortedObjects.insert(sa); #ifdef BLIS_DEBUG_MORE std::cout << "col[" << infObjects[i]->columnIndex() << "]=" << score << ", "<< std::endl; #endif } int numNotChange = 0; std::multimap< double, BlisObjectInt*, BlisPseuoGreater >::iterator pos; CoinWarmStart * ws = solver->getWarmStart(); solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit); int maxIter = ALPS_MAX(model->getAveIterations(), 50); solver->setIntParam(OsiMaxNumIterationHotStart, maxIter); solver->markHotStart(); BlisObjectInt *bestObject = NULL; double bestScore = -10.0; for (pos = sortedObjects.begin(); pos != sortedObjects.end(); ++pos) { intObject = pos->second; colInd = intObject->columnIndex(); #ifdef BLIS_DEBUG_MORE std::cout << "col[" << colInd << "]: " << "score=" << pos->first << ", upCount=" << intObject->pseudocost().getUpCount() <<", downCount="<< intObject->pseudocost().getDownCount() << std::endl; #endif // Check if reliable. int objRelibility=ALPS_MIN(intObject->pseudocost().getUpCount(), intObject->pseudocost().getDownCount()); if (objRelibility < relibility_) { // Unrelible object. Do strong branching. lpX = saveSolution[colInd]; BlisStrongBranch(model, objValue, colInd, lpX, saveLower, saveUpper, downKeep, downGood, downDeg, upKeep, upGood, upDeg); // Update pseudocost. if(downGood) { intObject->pseudocost().update(-1, downDeg, lpX); } if(downGood) { intObject->pseudocost().update(1, upDeg, lpX); } } // Compare with the best. if (intObject->pseudocost().getScore() > bestScore) { bestScore = intObject->pseudocost().getScore(); bestObject = intObject; // Reset numNotChange = 0; } else { // If best doesn't change for "lookAhead" comparisons, then // the best is reliable. if (++numNotChange > lookAhead) { if (bestObject->pseudocost().getUpCost() > bestObject->pseudocost().getDownCost()) { preferDir = 1; } else { preferDir = -1; } break; } } } solver->unmarkHotStart(); solver->setColSolution(saveSolution); solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit); solver->setWarmStart(ws); delete ws; model->setSolEstimate(objValue + sumDeg); assert(bestObject != NULL); bestBranchObject_ = bestObject->createBranchObject(model, preferDir); } TERM_CREATE: //------------------------------------------------------ // Cleanup. //------------------------------------------------------ delete [] lbInd; delete [] ubInd; delete [] newLB; delete [] newUB; delete [] saveSolution; delete [] saveLower; delete [] saveUpper; return bStatus; }
/** Perform a branch-and-bound on given setup.*/ void CouenneBab::branchAndBound (Bonmin::BabSetupBase & s) { double remaining_time = s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime) + CoinCpuTime(); /* Put a link to this into solver.*/ OsiBabSolver * babInfo = dynamic_cast<OsiBabSolver *>(s.continuousSolver()->getAuxiliaryInfo()); assert(babInfo); Bonmin::BabInfo * bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(babInfo); if (bonBabInfoPtr == NULL) { //Replace with a Bonmin::babInfo bonBabInfoPtr = new Bonmin::BabInfo(*babInfo); s.continuousSolver()->setAuxiliaryInfo(bonBabInfoPtr); delete bonBabInfoPtr; bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(s.continuousSolver()->getAuxiliaryInfo()); } bonBabInfoPtr->setBabPtr(this); s.nonlinearSolver()->solver()->setup_global_time_limit(s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime)); OsiSolverInterface * solver = s.continuousSolver()->clone(); delete modelHandler_; modelHandler_ = s.continuousSolver()->messageHandler()->clone(); model_.passInMessageHandler(modelHandler_); model_.assignSolver(solver, true); // s.continuousSolver() = model_.solver(); // if(s.continuousSolver()->objects()!=NULL){ // model_.addObjects(s.continuousSolver()->numberObjects(),s.continuousSolver()->objects()); // } int specOpt = s.getIntParameter(Bonmin::BabSetupBase::SpecialOption); if (specOpt) { model_.setSpecialOptions(specOpt); if (specOpt==16) { Bonmin::CbcNlpStrategy strat(s.getIntParameter(Bonmin::BabSetupBase::MaxFailures), s.getIntParameter(Bonmin::BabSetupBase::MaxInfeasible), s.getIntParameter(Bonmin::BabSetupBase::FailureBehavior)); model_.setStrategy(strat); } } model_.setMaximumCutPasses(s.getIntParameter(Bonmin::BabSetupBase::NumCutPasses)); model_.setMaximumCutPassesAtRoot(s.getIntParameter(Bonmin::BabSetupBase::NumCutPassesAtRoot)); //Setup cutting plane methods for (Bonmin::BabSetupBase::CuttingMethods::iterator i = s.cutGenerators().begin() ; i != s.cutGenerators().end() ; i++) { Bonmin::OaDecompositionBase * oa = dynamic_cast<Bonmin::OaDecompositionBase *>(i->cgl); if (oa && oa->reassignLpsolver()) oa->assignLpInterface(model_.solver()); model_.addCutGenerator(i->cgl,i->frequency,i->id.c_str(), i->normal, i->atSolution); if(i->always){ model_.cutGenerators()[model_.numberCutGenerators()-1] ->setMustCallAgain(true); } } for (Bonmin::BabSetupBase::HeuristicMethods::iterator i = s.heuristics().begin() ; i != s.heuristics().end() ; i++) { CbcHeuristic * heu = i->heuristic; heu->setModel(&model_); model_.addHeuristic(heu, i->id.c_str()); } //need to record solver logLevel here int logLevel = s.continuousSolver()->messageHandler()->logLevel(); //Set true branch-and-bound parameters model_.setLogLevel(s.getIntParameter(Bonmin::BabSetupBase::BabLogLevel)); // Put back solver logLevel model_.solver()->messageHandler()->setLogLevel(logLevel); model_.setPrintFrequency(s.getIntParameter(Bonmin::BabSetupBase::BabLogInterval)); bool ChangedObject = false; //Pass over user set branching priorities to Cbc if (s.continuousSolver()->objects()==NULL) { //assert (s.branchingMethod() == NULL); const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver(); //set priorities, prefered directions... const int * priorities = nlpSolver->getPriorities(); const double * upPsCosts = nlpSolver->getUpPsCosts(); const double * downPsCosts = nlpSolver->getDownPsCosts(); const int * directions = nlpSolver->getBranchingDirections(); bool hasPseudo = (upPsCosts!=NULL); model_.findIntegers(true,hasPseudo); OsiObject ** simpleIntegerObjects = model_.objects(); int numberObjects = model_.numberObjects(); if (priorities != NULL || directions != NULL || hasPseudo) { ChangedObject = true; for (int i = 0 ; i < numberObjects ; i++) { CbcObject * object = dynamic_cast<CbcObject *> (simpleIntegerObjects[i]); int iCol = object->columnNumber(); if (priorities) object->setPriority(priorities[iCol]); if (directions) object->setPreferredWay(directions[iCol]); if (upPsCosts) { CbcSimpleIntegerPseudoCost * pscObject = dynamic_cast<CbcSimpleIntegerPseudoCost*> (object); pscObject->setUpPseudoCost(upPsCosts[iCol]); pscObject->setDownPseudoCost(downPsCosts[iCol]); } } } #if 1 // Now pass user set Sos constraints (code inspired from CoinSolve.cpp) const TMINLP::SosInfo * sos = s.nonlinearSolver()->model()->sosConstraints(); if (!s.getIntParameter(Bonmin::BabSetupBase::DisableSos) && sos && sos->num > 0) { // we have some sos constraints const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver(); const int & numSos = sos->num; (*nlpSolver->messageHandler())<<"Adding "<<sos->num<<" sos constraints." <<CoinMessageEol; CbcObject ** objects = new CbcObject*[numSos]; const int * starts = sos->starts; const int * indices = sos->indices; const char * types = sos->types; const double * weights = sos->weights; //verify if model has user set priorities bool hasPriorities = false; const int * varPriorities = nlpSolver->getPriorities(); int numberObjects = model_.numberObjects(); if (varPriorities) { for (int i = 0 ; i < numberObjects ; i++) { if (varPriorities[i]) { hasPriorities = true; break; } } } const int * sosPriorities = sos->priorities; if (sosPriorities) { for (int i = 0 ; i < numSos ; i++) { if (sosPriorities[i]) { hasPriorities = true; break; } } } for (int i = 0 ; i < numSos ; i++) { int start = starts[i]; int length = starts[i + 1] - start; #ifdef DO_IT_NWAY printf("setting nway object\n"), objects[i] = new CbcNWay(&model_, length, &indices[start], i); objects[i]->setPriority(1); #else objects[i] = new CbcSOS(&model_, length, &indices[start], &weights[start], i, types[i]); objects[i]->setPriority(10); #endif if (hasPriorities && sosPriorities && sosPriorities[i]) { objects[i]->setPriority(sosPriorities[i]); } } model_.addObjects (numSos, objects); for (int i = 0 ; i < numSos ; i++) delete objects[i]; delete [] objects; } #endif //If Setup contains more objects add them to Cbc if (s.objects().size()) { CbcObject ** objects = new CbcObject *[s.objects().size()]; for (unsigned int i = 0 ; i < s.objects().size() ; i++) { objects[i] = dynamic_cast<CbcObject *> (s.objects()[i]); assert(objects[i]); objects[i]->setModel(&model_); } model_.addObjects ((int) s.objects().size(), objects); delete [] objects; } replaceIntegers(model_.objects(), model_.numberObjects()); } else { // Pass in objects to Cbc // Redundant definition of default branching (as Default == User) assert (s.branchingMethod() != NULL); // Add nonlinear and integer objects (need to add OsiSOS) model_.addObjects (s.continuousSolver () -> numberObjects (), s.continuousSolver () -> objects ()); // Now model_ has only CouenneObjects and SOS objects // for (int i=0; i<nco; i++) // if (!(dynamic_cast <CbcSimpleInteger *> (s.continuousSolver () -> objects () [i]))) // model_ . objects () [nRealObj++] = s.continuousSolver () -> objects () [i] -> clone (); CbcBranchDefaultDecision branch; s.branchingMethod()->setSolver(model_.solver()); BonChooseVariable * strong2 = dynamic_cast<BonChooseVariable *>(s.branchingMethod()); if (strong2) strong2->setCbcModel(&model_); branch.setChooseMethod(*s.branchingMethod()); model_.setBranchingMethod(&branch); // prevent duplicating object when copying in CbcModel.cpp model_.solver()->deleteObjects(); } model_.setDblParam(CbcModel::CbcCutoffIncrement, s.getDoubleParameter(Bonmin::BabSetupBase::CutoffDecr)); model_.setCutoff(s.getDoubleParameter(Bonmin::BabSetupBase::Cutoff) + CUTOFF_TOL); model_.setDblParam(CbcModel::CbcAllowableGap, s.getDoubleParameter(Bonmin::BabSetupBase::AllowableGap)); model_.setDblParam(CbcModel::CbcAllowableFractionGap, s.getDoubleParameter(Bonmin::BabSetupBase::AllowableFractionGap)); // Definition of node selection strategy if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::bestBound) { CbcCompareObjective compare; model_.setNodeComparison(compare); } else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::DFS) { CbcCompareDepth compare; model_.setNodeComparison(compare); } else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::BFS) { CbcCompareDefault compare; compare.setWeight(0.0); model_.setNodeComparison(compare); } else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::dynamic) { CbcCompareDefault compare; model_.setNodeComparison(compare); } else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::bestGuess) { // Right now, this is a mess. We need a separation of the // pseudo costs from the ChooseVariable method CbcCompareEstimate compare; model_.setNodeComparison(compare); GuessHeuristic * guessHeu = new GuessHeuristic(model_); model_.addHeuristic(guessHeu); delete guessHeu; } if (s.treeTraversalMethod() == Bonmin::BabSetupBase::HeapOnly) { //Do nothing this is the default of Cbc. } else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::DiveFromBest) { CbcDiver treeTraversal; treeTraversal.initialize(s); model_.passInTreeHandler(treeTraversal); } else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::ProbedDive) { CbcProbedDiver treeTraversal; treeTraversal.initialize(s); model_.passInTreeHandler(treeTraversal); } else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::DfsDiveFromBest) { CbcDfsDiver treeTraversal; treeTraversal.initialize(s); model_.passInTreeHandler(treeTraversal); } else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::DfsDiveDynamic) { CbcDfsDiver treeTraversal; treeTraversal.initialize(s); model_.passInTreeHandler(treeTraversal); DiverCompare compare; compare.setComparisonDive(*model_.nodeComparison()); compare.setComparisonBound(CbcCompareObjective()); CbcDfsDiver * dfs = dynamic_cast<CbcDfsDiver *> (model_.tree()); assert(dfs); compare.setDiver(dfs); model_.setNodeComparison(compare); } model_.setNumberStrong(s.getIntParameter(Bonmin::BabSetupBase::NumberStrong)); model_.setNumberBeforeTrust(s.getIntParameter(Bonmin::BabSetupBase::MinReliability)); model_.setNumberPenalties(8); model_.setDblParam(CbcModel::CbcMaximumSeconds, s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime)); model_.setMaximumNodes(s.getIntParameter(Bonmin::BabSetupBase::MaxNodes)); model_.setMaximumNumberIterations(s.getIntParameter(Bonmin::BabSetupBase::MaxIterations)); model_.setMaximumSolutions(s.getIntParameter(Bonmin::BabSetupBase::MaxSolutions)); model_.setIntegerTolerance(s.getDoubleParameter(Bonmin::BabSetupBase::IntTol)); //Get objects from model_ if it is not null means there are some sos constraints or non-integer branching object // pass them to cut generators. OsiObject ** objects = model_.objects(); if (specOpt!=16 && objects) { int numberObjects = model_.numberObjects(); if (objects_ != NULL) { for (int i = 0 ; i < nObjects_; i++) delete objects_[i]; } delete [] objects_; objects_ = new OsiObject*[numberObjects]; nObjects_ = numberObjects; for (int i = 0 ; i < numberObjects; i++) { OsiObject * obj = objects[i]; CbcSimpleInteger * intObj = dynamic_cast<CbcSimpleInteger *> (obj); if (intObj) { objects_[i] = intObj->osiObject(); } else { CbcSOS * sosObj = dynamic_cast<CbcSOS *>(obj); if (sosObj) objects_[i] = sosObj->osiObject(model_.solver()); else {//Maybe an unsupported CbcObject CbcObject * cbcObj = dynamic_cast<CbcObject *>(obj); if (cbcObj) { std::cerr<<"Unsupported CbcObject appears in the code"<<std::endl; throw UNSUPPORTED_CBC_OBJECT; } else {//It has to be an OsiObject. objects_[i]=obj->clone(); } } } } CbcCutGenerator ** gen = model_.cutGenerators(); int numGen = model_.numberCutGenerators(); for (int i = 0 ; i < numGen ; i++) { Bonmin::OaDecompositionBase * oa = dynamic_cast<Bonmin::OaDecompositionBase * >(gen[i]->generator()); // if (oa) // printf ("\n\n\nat least one OADecompBase\n\n\n"); if (oa) // pass objects oa->setObjects(objects_,nObjects_); } } // if (objects_) { // for (int i = 0 ; i < nObjects_; i++) // delete objects_ [i]; // delete [] objects_; // } // OsiObject ** objects = model_.objects(); // int numObjects = model_.numberObjects(); // nObjects_ = 0; // objects_ = new OsiObject* [numObjects]; // for (int i=0; i < numObjects; ++i) // if (objects [i]) // objects_ [nObjects_++] = objects [i] -> clone (); try { //Get the time and start. { OsiTMINLPInterface * tmpOsi = NULL; if(s.nonlinearSolver() == s.continuousSolver()){ tmpOsi = dynamic_cast<OsiTMINLPInterface *> (model_.solver()); tmpOsi->forceSolverOutput(s.getIntParameter(Bonmin::BabSetupBase::RootLogLevel)); } model_.initialSolve(); if(tmpOsi != NULL){ tmpOsi->setSolverOutputToDefault(); } } int ival; s.options()->GetEnumValue("enable_dynamic_nlp", ival, "bonmin."); if(s.nonlinearSolver() == s.continuousSolver() && ival) { if(!model_.solver()->isProvenOptimal() ){//Something went wrong check if objective is linear and alternate model // can be solved OsiTMINLPInterface * tmpOsi = dynamic_cast<OsiTMINLPInterface *> (model_.solver()); TMINLPLinObj * tmp_tminlp = dynamic_cast<TMINLPLinObj *> (tmpOsi->model()); tmpOsi->setModel(tmp_tminlp->tminlp()); model_.initialSolve(); } else { LinearCutsGenerator cgl; cgl.initialize(s); OsiCuts cuts; cgl.generateCuts(*model_.solver(), cuts); std::vector<const OsiRowCut *> mycuts(cuts.sizeRowCuts()); for(int i = 0 ; i < cuts.sizeRowCuts() ; i++){ mycuts[i] = cuts.rowCutPtr(i); } model_. solver () -> applyRowCuts ((int) mycuts.size(), (const OsiRowCut **) &mycuts[0]); } //Added by Claudia OsiTMINLPInterface * nlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver()); if(nlpSolver && nlpSolver->getNewCutoffDecr()!=COIN_DBL_MAX) model_.setDblParam(CbcModel::CbcCutoffIncrement, nlpSolver->getNewCutoffDecr()); model_.solver()->resolve(); } // for Couenne model_.passInSolverCharacteristics (bonBabInfoPtr); continuousRelaxation_ =model_.solver()->getObjValue(); if (specOpt==16)//Set warm start point for Ipopt { #if 1 const double * colsol = model_.solver()->getColSolution(); const double * duals = model_.solver()->getRowPrice(); OsiTMINLPInterface * tnlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver()); // Primal dual point is not copied if one (supposedly a better one) has already been put into the solver. if(tnlpSolver->problem()->has_x_init() != 2){ model_.solver()->setColSolution(colsol); model_.solver()->setRowPrice(duals); } #else OsiTMINLPInterface * tnlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver()); CoinWarmStart * warm = tnlpSolver->solver()->getWarmStart(tnlpSolver->problem()); tnlpSolver->solver()->setWarmStart(warm, tnlpSolver->problem()); delete warm; #endif #if 0 // Sometimes primal dual point is problematic in the context of Cut-and-branch model_.solver()->resolve(); if(!model_.solver()->isProvenOptimal()) model_.solver()->setColSolution(NULL); #endif } #ifdef SIGNAL CoinSighandler_t saveSignal = SIG_DFL; // register signal handler saveSignal = signal (SIGINT,couenne_signal_handler); currentBranchModel = &model_; #endif // to get node parent info in Cbc, pass parameter 3. //model_.branchAndBound(3); remaining_time -= CoinCpuTime(); model_.setDblParam(CbcModel::CbcMaximumSeconds, remaining_time); if(remaining_time > 0.) model_.branchAndBound(); } catch(TNLPSolver::UnsolvedError *E){ s.nonlinearSolver()->model()->finalize_solution (TMINLP::MINLP_ERROR, 0, NULL, DBL_MAX); throw E; } numNodes_ = model_.getNodeCount(); bestObj_ = model_.getObjValue(); bestBound_ = model_.getBestPossibleObjValue(); mipIterationCount_ = model_.getIterationCount(); bool hasFailed = false; if (specOpt==16)//Did we continue branching on a failure { CbcNlpStrategy * nlpStrategy = dynamic_cast<CbcNlpStrategy *>(model_.strategy()); if (nlpStrategy) hasFailed = nlpStrategy->hasFailed(); else throw -1; } else hasFailed = s.nonlinearSolver()->hasContinuedOnAFailure(); // Output summarizing cut generators (taken from CbcSolver.cpp) // ToDo put into proper print level int numberGenerators = model_.numberCutGenerators(); for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++) { CbcCutGenerator * generator = model_.cutGenerator(iGenerator); //CglStored * stored = dynamic_cast<CglStored*>(generator->generator()); if (true&&!(generator->numberCutsInTotal() || generator->numberColumnCuts())) continue; if(modelHandler_->logLevel() >= 1) { *modelHandler_ << generator->cutGeneratorName() << "was tried" << generator->numberTimesEntered() << "times and created" << generator->numberCutsInTotal()+generator->numberColumnCuts() << "cuts of which" << generator->numberCutsActive() << "were active after adding rounds of cuts"; // if (generator->timing()) { // char timebuf[20]; // sprintf(timebuf, "(%.3fs)", generator->timeInCutGenerator()); // *modelHandler_ << timebuf << CoinMessageEol; // } // else { // *modelHandler_ << CoinMessageEol; // } } } TMINLP::SolverReturn status = TMINLP::MINLP_ERROR; if (model_.numberObjects()==0) { if (bestSolution_) delete [] bestSolution_; OsiSolverInterface * solver = (s.nonlinearSolver() == s.continuousSolver())? model_.solver() : s.nonlinearSolver(); bestSolution_ = new double[solver->getNumCols()]; CoinCopyN(solver->getColSolution(), solver->getNumCols(), bestSolution_); bestObj_ = bestBound_ = solver->getObjValue(); } if (bonBabInfoPtr->bestSolution2().size() > 0) { assert((int) bonBabInfoPtr->bestSolution2().size() == s.nonlinearSolver()->getNumCols()); if (bestSolution_) delete [] bestSolution_; bestSolution_ = new double[s.nonlinearSolver()->getNumCols()]; std::copy(bonBabInfoPtr->bestSolution2().begin(), bonBabInfoPtr->bestSolution2().end(), bestSolution_); bestObj_ = (bonBabInfoPtr->bestObj2()); (*s.nonlinearSolver()->messageHandler())<<"\nReal objective function: " <<bestObj_<<CoinMessageEol; } else if (model_.bestSolution()) { if (bestSolution_) delete [] bestSolution_; bestSolution_ = new double[s.nonlinearSolver()->getNumCols()]; CoinCopyN(model_.bestSolution(), s.nonlinearSolver()->getNumCols(), bestSolution_); } if(remaining_time <= 0.){ status = TMINLP::LIMIT_EXCEEDED; if (bestSolution_) { mipStatus_ = Feasible; } else { mipStatus_ = NoSolutionKnown; } } else if (model_.status() == 0) { if(model_.isContinuousUnbounded()){ status = TMINLP::CONTINUOUS_UNBOUNDED; mipStatus_ = UnboundedOrInfeasible; } else if (bestSolution_) { status = TMINLP::SUCCESS; mipStatus_ = FeasibleOptimal; } else { status = TMINLP::INFEASIBLE; mipStatus_ = ProvenInfeasible; } } else if (model_.status() == 1 || model_.status() == 5) { #if (BONMIN_VERSION_MAJOR > 1) || (BONMIN_VERSION_MINOR > 6) status = model_.status() == 1 ? TMINLP::LIMIT_EXCEEDED : TMINLP::USER_INTERRUPT; #else status = TMINLP::LIMIT_EXCEEDED; #endif if (bestSolution_) { mipStatus_ = Feasible; } else { mipStatus_ = NoSolutionKnown; } } else if (model_.status()==2) { status = TMINLP::MINLP_ERROR; } // Which solution should we use? false if RBS's, true if Cbc's bool use_RBS_Cbc = !problem_ || !(problem_ -> getRecordBestSol ()) || !(problem_ -> getRecordBestSol () -> getHasSol()) || (((fabs (bestObj_) < COUENNE_INFINITY / 1e4) && (problem_ -> getRecordBestSol () -> getVal () > bestObj_))); /* if we do not pass the cbc solution and problem_ -> getRecordBestSol () -> getHasSol() is true, then there should be a solution vector in problem_ -> getRecordBestSol () */ assert(use_RBS_Cbc || problem_ -> getRecordBestSol () -> getSol() != NULL); s.nonlinearSolver () -> model () -> finalize_solution (status, s.nonlinearSolver () -> getNumCols (), use_RBS_Cbc ? bestSolution_ : problem_ -> getRecordBestSol () -> getSol (), use_RBS_Cbc ? bestObj_ : problem_ -> getRecordBestSol () -> getVal ()); }
// Generate cuts void CglFakeClique::generateCuts(const OsiSolverInterface& si, OsiCuts & cs, const CglTreeInfo info) { if (fakeSolver_) { assert (si.getNumCols()==fakeSolver_->getNumCols()); fakeSolver_->setColLower(si.getColLower()); const double * solution = si.getColSolution(); fakeSolver_->setColSolution(solution); fakeSolver_->setColUpper(si.getColUpper()); // get and set branch and bound cutoff double cutoff; si.getDblParam(OsiDualObjectiveLimit,cutoff); fakeSolver_->setDblParam(OsiDualObjectiveLimit,COIN_DBL_MAX); #ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast<OsiClpSolverInterface *> (fakeSolver_); if (clpSolver) { // fix up fake solver const ClpSimplex * siSimplex = clpSolver->getModelPtr(); // need to set djs memcpy(siSimplex->primalColumnSolution(), si.getReducedCost(),si.getNumCols()*sizeof(double)); fakeSolver_->setDblParam(OsiDualObjectiveLimit,cutoff); } #endif const CoinPackedMatrix * matrixByRow = si.getMatrixByRow(); const double * elementByRow = matrixByRow->getElements(); const int * column = matrixByRow->getIndices(); const CoinBigIndex * rowStart = matrixByRow->getVectorStarts(); const int * rowLength = matrixByRow->getVectorLengths(); const double * rowUpper = si.getRowUpper(); const double * rowLower = si.getRowLower(); // Scan all rows looking for possibles int numberRows = si.getNumRows(); double tolerance = 1.0e-3; for (int iRow=0;iRow<numberRows;iRow++) { CoinBigIndex start = rowStart[iRow]; CoinBigIndex end = start + rowLength[iRow]; double upRhs = rowUpper[iRow]; double loRhs = rowLower[iRow]; double sum = 0.0; for (CoinBigIndex j=start;j<end;j++) { int iColumn=column[j]; double value = elementByRow[j]; sum += solution[iColumn]*value; } if (sum<loRhs-tolerance||sum>upRhs+tolerance) { // add as cut OsiRowCut rc; rc.setLb(loRhs); rc.setUb(upRhs); rc.setRow(end-start,column+start,elementByRow+start,false); CoinAbsFltEq equal(1.0e-12); cs.insertIfNotDuplicate(rc,equal); } } CglClique::generateCuts(*fakeSolver_,cs,info); if (probing_) { probing_->generateCuts(*fakeSolver_,cs,info); } } else { // just use real solver CglClique::generateCuts(si,cs,info); } }
//------------------------------------------------------------------------------- // Generate three cycle cuts //------------------------------------------------------------------- void CglOddHole::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo info) { // Get basic problem information int nRows=si.getNumRows(); int nCols=si.getNumCols(); const CoinPackedMatrix * rowCopy = si.getMatrixByRow(); // Could do cliques and extra OSL cliques // For moment just easy ones // If no information exists then get a list of suitable rows // If it does then suitable rows are subset of information CglOddHole temp; int * checkRow = new int[nRows]; int i; if (!suitableRows_) { for (i=0;i<nRows;i++) { checkRow[i]=1; } } else { // initialize and extend rows to current size memset(checkRow,0,nRows*sizeof(int)); memcpy(checkRow,suitableRows_,CoinMin(nRows,numberRows_)*sizeof(int)); } temp.createRowList(si,checkRow); // now cut down further by only allowing rows with fractional solution double * solution = new double[nCols]; memcpy(solution,si.getColSolution(),nCols*sizeof(double)); const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const int * rowLength = rowCopy->getVectorLengths(); const double * collower = si.getColLower(); const double * colupper = si.getColUpper(); int * suitable = temp.suitableRows_; // At present I am using new and delete as easier to see arrays in debugger int * fixed = new int[nCols]; // mark fixed columns for (i=0;i<nCols;i++) { if (si.isBinary(i) ) { fixed[i]=0; if (colupper[i]-collower[i]<epsilon_) { solution[i]=0.0; fixed[i]=2; } else if (solution[i]<epsilon_) { solution[i]=0.0; fixed[i]=-1; } else if (solution[i]>onetol_) { solution[i]=1.0; fixed[i]=+1; } } else { //mark as fixed even if not (can not intersect any interesting rows) solution[i]=0.0; fixed[i]=3; } } // first do packed const double * rowlower = si.getRowLower(); const double * rowupper = si.getRowUpper(); for (i=0;i<nRows;i++) { if (suitable[i]) { int k; double sum=0.0; if (rowupper[i]>1.001) suitable[i]=-1; for (k=rowStart[i]; k<rowStart[i]+rowLength[i];k++) { int icol=column[k]; if (!fixed[icol]) sum += solution[icol]; } if (sum<0.9) suitable[i]=-1; //say no good } } #ifdef CGL_DEBUG const OsiRowCutDebugger * debugger = si.getRowCutDebugger(); if (debugger&&!debugger->onOptimalPath(si)) debugger = NULL; #else const OsiRowCutDebugger * debugger = NULL; #endif temp.generateCuts(debugger, *rowCopy,solution, si.getReducedCost(),cs,suitable,fixed,info,true); // now cover //if no >= then skip bool doCover=false; int nsuitable=0; for (i=0;i<nRows;i++) { suitable[i]=abs(suitable[i]); if (suitable[i]) { int k; double sum=0.0; if (rowlower[i]<0.999) sum=2.0; if (rowupper[i]>1.001) doCover=true; for (k=rowStart[i]; k<rowStart[i]+rowLength[i];k++) { int icol=column[k]; if (!fixed[icol]) sum += solution[icol]; if (fixed[icol]==1) sum=2.0; //don't use if any at 1 } if (sum>1.1) { suitable[i]=-1; //say no good } else { nsuitable++; } } } if (doCover&&nsuitable) temp.generateCuts(debugger, *rowCopy,solution,si.getReducedCost(), cs,suitable,fixed,info,false); delete [] checkRow; delete [] solution; delete [] fixed; }
//------------------------------------------------------------- void CglZeroHalf::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo info) { if (mnz_) { int cnum=0,cnzcnt=0; int *cbeg=NULL, *ccnt=NULL,*cind=NULL,*cval=NULL,*crhs=NULL; char *csense=NULL; const double * solution = si.getColSolution(); if ((flags_&1)==0) { // redo bounds const double * columnLower = si.getColLower(); const double * columnUpper = si.getColUpper(); int numberColumns = si.getNumCols(); for (int iColumn=0;iColumn<numberColumns;iColumn++) { if (vlb_[iColumn]!=COIN_INT_MAX) { int ilo,iup; double lo = columnLower[iColumn]; if (lo<-COIN_INT_MAX) lo=-COIN_INT_MAX; ilo= static_cast<int> (ceil(lo)); double up = columnUpper[iColumn]; if (up>COIN_INT_MAX) up=COIN_INT_MAX; iup= static_cast<int> (floor(up)); vlb_[iColumn]=ilo; vub_[iColumn]=iup; } } } if (true) { cutInfo_.sep_012_cut(mr_,mc_,mnz_, mtbeg_,mtcnt_, mtind_, mtval_, vlb_, vub_, mrhs_, msense_, solution, info.inTree ? false : true, &cnum,&cnzcnt, &cbeg,&ccnt,&cind,&cval,&crhs,&csense); } else { int k = 4*mr_+2*mnz_; int * temp = new int[k]; int * mtbeg = temp; int * mtcnt = mtbeg + mr_; int * mtind = mtcnt+mr_; int * mtval = mtind+mnz_; int * mrhs = mtval+mnz_; char * msense = reinterpret_cast<char*> (mrhs+mr_); int i; k=0; int kel=0; for (i=0;i<mr_;i++) { int kel2=kel; int rhs = mrhs_[i]; for (int j=mtbeg_[i];j<mtbeg_[i]+mtcnt_[i];j++) { int iColumn=mtind_[j]; int value=mtval_[j]; if (vlb_[iColumn]<vub_[iColumn]) { mtind[kel]=mtind_[j]; mtval[kel++]=mtval_[j]; } else { rhs -= vlb_[iColumn]*value; } } if (kel>kel2) { mtcnt[k]=kel-kel2; mtbeg[k]=kel2; mrhs[k]=rhs; msense[k++]=msense_[i]; } } if (kel) { cutInfo_.sep_012_cut(k,mc_,kel, mtbeg,mtcnt, mtind, mtval, vlb_, vub_, mrhs, msense, solution, info.inTree ? false : true, &cnum,&cnzcnt, &cbeg,&ccnt,&cind,&cval,&crhs,&csense); } delete [] temp; } if (cnum) { // add cuts double * element = new double[mc_]; for (int i=0;i<cnum;i++) { int n = ccnt[i]; int start = cbeg[i]; for (int j=0;j<n;j++) element[j]=cval[start+j]; OsiRowCut rc; if (csense[i]=='L') { rc.setLb(-COIN_DBL_MAX); rc.setUb(crhs[i]); } else if (csense[i]=='G') { rc.setLb(crhs[i]); rc.setUb(COIN_DBL_MAX); } else { abort(); } rc.setRow(n,cind+start,element,false); if ((flags_&1)!=0) rc.setGloballyValid(); //double violation = rc.violated(solution); //if (violation>1.0e-6) cs.insert(rc); //else //printf("violation of %g\n",violation); } delete [] element; free(cbeg); free(ccnt); free(cind); free(cval); free(crhs); free(csense); } } }
/** Create a set of candidate branching objects. */ int BlisBranchStrategyPseudo::createCandBranchObjects(int numPassesLeft, double ub) { int bStatus = 0; int i, pass, colInd; int preferDir, saveLimit; int numFirsts = 0; int numInfs = 0; int minCount = 0; int numLowerTightens = 0; int numUpperTightens = 0; double lpX, score, infeasibility, downDeg, upDeg, sumDeg = 0.0; bool roundAgain, downKeep, downGood, upKeep, upGood; int *lbInd = NULL; int *ubInd = NULL; double *newLB = NULL; double *newUB = NULL; double *saveUpper = NULL; double *saveLower = NULL; double *saveSolution = NULL; BlisModel *model = dynamic_cast<BlisModel *>(model_); OsiSolverInterface *solver = model->solver(); int numCols = model->getNumCols(); int numObjects = model->numObjects(); int aveIterations = model->getAveIterations(); //std::cout << "aveIterations = " << aveIterations << std::endl; //------------------------------------------------------ // Check if max time is reached or no pass is left. //------------------------------------------------------ double timeLimit = model->AlpsPar()->entry(AlpsParams::timeLimit); AlpsKnowledgeBroker *broker = model->getKnowledgeBroker(); bool maxTimeReached = (broker->timer().getTime() > timeLimit); bool selectNow = false; if (maxTimeReached || !numPassesLeft) { selectNow = true; #ifdef BLIS_DEBUG printf("PSEUDO: CREATE: maxTimeReached %d, numPassesLeft %d\n", maxTimeReached, numPassesLeft); #endif } // Store first time objects. std::vector<BlisObjectInt *> firstObjects; // Store infeasible objects. std::vector<BlisObjectInt *> infObjects; // TODO: check if sorting is expensive. std::multimap<double, BcpsBranchObject*, BlisPseuoGreater> candObjects; double objValue = solver->getObjSense() * solver->getObjValue(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); saveSolution = new double[numCols]; memcpy(saveSolution, solver->getColSolution(), numCols*sizeof(double)); //-------------------------------------------------- // Find the infeasible objects. // NOTE: we might go round this loop twice if we are feed in // a "feasible" solution. //-------------------------------------------------- for (pass = 0; pass < 2; ++pass) { numInfs = 0; BcpsObject * object = NULL; BlisObjectInt * intObject = NULL; infObjects.clear(); firstObjects.clear(); for (i = 0; i < numObjects; ++i) { object = model->objects(i); infeasibility = object->infeasibility(model, preferDir); if (infeasibility) { ++numInfs; intObject = dynamic_cast<BlisObjectInt *>(object); if (intObject) { infObjects.push_back(intObject); if (!selectNow) { minCount = ALPS_MIN(intObject->pseudocost().getDownCount(), intObject->pseudocost().getUpCount()); if (minCount < 1) { firstObjects.push_back(intObject); } } #ifdef BLIS_DEBUG if (intObject->columnIndex() == 40) { std::cout << "x[40] = " << saveSolution[40] << std::endl; } #endif intObject = NULL; } else { // TODO: currently all are integer objects. #ifdef BLIS_DEBU assert(0); #endif } } } if (numInfs) { #if 0 std::cout << "PSEUDO: numInfs = " << numInfs << std::endl; #endif break; } else if (pass == 0) { // The first pass and is IP feasible. #if 1 std::cout << "ERROR: PSEUDO: given a integer feasible sol, no fraction variable" << std::endl; assert(0); #endif roundAgain = false; CoinWarmStartBasis * ws = dynamic_cast<CoinWarmStartBasis*>(solver->getWarmStart()); if (!ws) break; // Force solution values within bounds for (i = 0; i < numCols; ++i) { lpX = saveSolution[i]; if (lpX < lower[i]) { saveSolution[i] = lower[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atLowerBound); } else if (lpX > upper[i]) { saveSolution[i] = upper[i]; roundAgain = true; ws->setStructStatus(i, CoinWarmStartBasis::atUpperBound); } } if (roundAgain) { // Need resolve and do the second round selection. solver->setWarmStart(ws); delete ws; // Resolve. solver->resolve(); if (!solver->isProvenOptimal()) { // Become infeasible, can do nothing. bStatus = -2; goto TERM_CREATE; } else { // Save new lp solution. memcpy(saveSolution, solver->getColSolution(), numCols * sizeof(double)); objValue = solver->getObjSense() * solver->getObjValue(); } } else { delete ws; break; } } } // EOF 2 pass //-------------------------------------------------- // If we have a set of first time object, // branch up and down to initialize pseudo-cost. //-------------------------------------------------- numFirsts = static_cast<int> (firstObjects.size()); //std::cout << "PSEUDO: numFirsts = " << numFirsts << std::endl; if (numFirsts > 0) { //std::cout << "PSEUDO: numFirsts = " << numFirsts << std::endl; //-------------------------------------------------- // Backup solver status and mark hot start. //-------------------------------------------------- saveLower = new double[numCols]; saveUpper = new double[numCols]; memcpy(saveLower, lower, numCols * sizeof(double)); memcpy(saveUpper, upper, numCols * sizeof(double)); CoinWarmStart * ws = solver->getWarmStart(); solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit); aveIterations = ALPS_MIN(50, aveIterations); solver->setIntParam(OsiMaxNumIterationHotStart, aveIterations); solver->markHotStart(); lbInd = new int [numFirsts]; ubInd = new int [numFirsts]; newLB = new double [numFirsts]; newUB = new double [numFirsts]; for (i = 0; i < numFirsts && bStatus != -2; ++i) { colInd = firstObjects[i]->columnIndex(); lpX = saveSolution[colInd]; BlisStrongBranch(model, objValue, colInd, lpX, saveLower, saveUpper, downKeep, downGood, downDeg, upKeep, upGood, upDeg); if(!downKeep && !upKeep) { // Both branch can be fathomed bStatus = -2; } else if (!downKeep) { // Down branch can be fathomed. lbInd[numLowerTightens] = colInd; newLB[numLowerTightens++] = ceil(lpX); } else if (!upKeep) { // Up branch can be fathomed. ubInd[numUpperTightens] = colInd; newUB[numUpperTightens++] = floor(lpX); } } //-------------------------------------------------- // Set new bounds in lp solver for resolving //-------------------------------------------------- if (bStatus != -2) { if (numUpperTightens > 0) { bStatus = -1; for (i = 0; i < numUpperTightens; ++i) { solver->setColUpper(ubInd[i], newUB[i]); } } if (numLowerTightens > 0) { bStatus = -1; for (i = 0; i < numLowerTightens; ++i) { solver->setColLower(lbInd[i], newLB[i]); } } } //-------------------------------------------------- // Unmark hotstart and recover LP solver. //-------------------------------------------------- solver->unmarkHotStart(); solver->setColSolution(saveSolution); solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit); solver->setWarmStart(ws); delete ws; } if (bStatus < 0) { goto TERM_CREATE; } else { // Create a set of candidate branching objects. numBranchObjects_ = numInfs; branchObjects_ = new BcpsBranchObject* [numInfs]; // NOTE: it set model->savedLpSolution. sumDeg = 0.0; for (i = 0; i < numInfs; ++i) { if (infObjects[i]->pseudocost().getUpCost() < infObjects[i]->pseudocost().getDownCost()) { preferDir = 1; } else { preferDir = -1; } branchObjects_[i] = infObjects[i]->createBranchObject(model, preferDir); score = infObjects[i]->pseudocost().getScore(); branchObjects_[i]->setUpScore(score); sumDeg += score; #ifdef BLIS_DEBUG_MORE std::cout << "col[" << infObjects[i]->columnIndex() << "]: score=" << score << ", dir=" << branchObjects_[i]->getDirection() << ", up=" << infObjects[i]->pseudocost().getUpCost() << ", down=" << infObjects[i]->pseudocost().getDownCost() << std::endl; #endif } model->setSolEstimate(objValue + sumDeg); } TERM_CREATE: //------------------------------------------------------ // Cleanup. //------------------------------------------------------ delete [] lbInd; delete [] ubInd; delete [] newLB; delete [] newUB; delete [] saveSolution; delete [] saveLower; delete [] saveUpper; return bStatus; }
/* First tries setting a variable to better value. If feasible then tries setting others. If not feasible then tries swaps Returns 1 if solution, 0 if not */ int CbcHeuristicVND::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; int returnCode = 0; const double * bestSolution = model_->bestSolution(); if (!bestSolution) return 0; // No solution found yet #ifdef HEURISTIC_INFORM printf("Entering heuristic %s - nRuns %d numCould %d when %d\n", heuristicName(),numRuns_,numCouldRun_,when_); #endif if (numberSolutions_ < model_->getSolutionCount()) { // new solution - add info numberSolutions_ = model_->getSolutionCount(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double value = bestSolution[iColumn]; if (value < originalLower) { value = originalLower; } else if (value > originalUpper) { value = originalUpper; } } } int numberNodes = model_->getNodeCount(); if (howOften_ == 100) { if (numberNodes < lastNode_ + 12) return 0; // Do at 50 and 100 if ((numberNodes > 40 && numberNodes <= 50) || (numberNodes > 90 && numberNodes < 100)) numberNodes = howOften_; } if ((numberNodes % howOften_) == 0 && (model_->getCurrentPassNumber() <= 1 || model_->getCurrentPassNumber() == 999999)) { lastNode_ = model_->getNodeCount(); OsiSolverInterface * solver = model_->solver(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); const double * currentSolution = solver->getColSolution(); OsiSolverInterface * newSolver = cloneBut(3); // was model_->continuousSolver()->clone(); //const double * colLower = newSolver->getColLower(); //const double * colUpper = newSolver->getColUpper(); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); // Sort on distance double * distance = new double [numberIntegers]; int * which = new int [numberIntegers]; int i; int nFix = 0; double tolerance = 10.0 * primalTolerance; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double valueInt = bestSolution[iColumn]; if (valueInt < originalLower) { valueInt = originalLower; } else if (valueInt > originalUpper) { valueInt = originalUpper; } baseSolution_[iColumn] = currentSolution[iColumn]; distance[i] = fabs(currentSolution[iColumn] - valueInt); which[i] = i; if (fabs(currentSolution[iColumn] - valueInt) < tolerance) nFix++; } CoinSort_2(distance, distance + numberIntegers, which); nDifferent_ = numberIntegers - nFix; stepSize_ = nDifferent_ / 10; k_ = stepSize_; //nFix = numberIntegers-stepSize_; for (i = 0; i < nFix; i++) { int j = which[i]; int iColumn = integerVariable[j]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double valueInt = bestSolution[iColumn]; if (valueInt < originalLower) { valueInt = originalLower; } else if (valueInt > originalUpper) { valueInt = originalUpper; } double nearest = floor(valueInt + 0.5); newSolver->setColLower(iColumn, nearest); newSolver->setColUpper(iColumn, nearest); } delete [] distance; delete [] which; if (nFix > numberIntegers / 5) { //printf("%d integers have samish value\n",nFix); returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, model_->getCutoff(), "CbcHeuristicVND"); if (returnCode < 0) returnCode = 0; // returned on size else numRuns_++; if ((returnCode&1) != 0) numberSuccesses_++; //printf("return code %d",returnCode); if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; //printf("could add cut with %d elements (if all 0-1)\n",nFix); } else { //printf("\n"); } numberTries_++; if ((numberTries_ % 10) == 0 && numberSuccesses_*3 < numberTries_) howOften_ += static_cast<int> (howOften_ * decayFactor_); } delete newSolver; } return returnCode; }
/** Standard cut generation methods. */ void OaDecompositionBase::generateCuts(const OsiSolverInterface &si, OsiCuts & cs, const CglTreeInfo info) { if (nlp_ == NULL) { throw CoinError("Error in cut generator for outer approximation no NLP ipopt assigned", "generateCuts", "OaDecompositionBase"); } // babInfo is used to communicate with the b-and-b solver (Cbc or Bcp). BabInfo * babInfo = dynamic_cast<BabInfo *> (si.getAuxiliaryInfo()); assert(babInfo); assert(babInfo->babPtr()); numSols_ = babInfo->babPtr()->model().getSolutionCount (); CglTreeInfo info_copy = info; const CbcNode * node = babInfo->babPtr()->model().currentNode(); info_copy.level = (node == NULL) ? 0 : babInfo->babPtr()->model().currentNode()->depth(); if(babInfo->hasSolution()) numSols_ ++; if (babInfo) if (!babInfo->mipFeasible()) return; //Get the continuous solution const double *colsol = si.getColSolution(); vector<double> savedColLower(nlp_->getNumCols()); CoinCopyN(nlp_->getColLower(), nlp_->getNumCols(), savedColLower()); vector<double> savedColUpper(nlp_->getNumCols()); CoinCopyN(nlp_->getColUpper(), nlp_->getNumCols(), savedColUpper()); OsiBranchingInformation brInfo(nlp_, false); brInfo.solution_ = colsol; //Check integer infeasibility bool isInteger = integerFeasible(*nlp_, brInfo, parameters_.cbcIntegerTolerance_, objects_, nObjects_); //Check nodeNumber if it did not change scan savedCuts_ if one is violated force it and exit int nodeNumber = babInfo->babPtr()->model().getNodeCount(); if(nodeNumber == currentNodeNumber_){ #ifdef OA_DEBUG printf("OA decomposition recalled from the same node!\n"); #endif int numCuts = savedCuts_.sizeRowCuts(); for(int i = 0 ; i < numCuts ; i++){ //Check if cuts off solution if(savedCuts_.rowCut(i).violated(colsol) > 0.){ #ifdef OA_DEBUG printf("A violated saved cut has been found\n"); #endif savedCuts_.rowCut(i).setEffectiveness(9.99e99); cs.insert(savedCuts_.rowCut(i)); savedCuts_.eraseRowCut(i); return; i--; numCuts--; } } } else { currentNodeNumber_ = nodeNumber; savedCuts_.dumpCuts(); } if (!isInteger) { if (!doLocalSearch(babInfo))//create sub mip solver. return; } //get the current cutoff double cutoff; si.getDblParam(OsiDualObjectiveLimit, cutoff); // Save solvers state if needed solverManip * lpManip = NULL; if (lp_ != NULL) { assert(lp_ == &si); lpManip = new solverManip(lp_, true, leaveSiUnchanged_, true, true); } else { lpManip = new solverManip(si); } lpManip->setObjects(objects_, nObjects_); double milpBound = performOa(cs, *lpManip, babInfo, cutoff, info_copy); if(babInfo->hasSolution()){ babInfo->babPtr()->model().setSolutionCount (numSols_ - 1); } //Transmit the bound found by the milp { if (milpBound>-1e100) { // Also store into solver if (babInfo) babInfo->setMipBound(milpBound); } } //Clean everything : // Reset the two solvers if (leaveSiUnchanged_) lpManip->restore(); delete lpManip; nlp_->setColLower(savedColLower()); nlp_->setColUpper(savedColUpper()); return; }
//------------------------------------------------------------------- // Generate Stored cuts //------------------------------------------------------------------- void CglStored::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo /*info*/) const { // Get basic problem information const double * solution = si.getColSolution(); int numberRowCuts = cuts_.sizeRowCuts(); for (int i=0;i<numberRowCuts;i++) { const OsiRowCut * rowCutPointer = cuts_.rowCutPtr(i); double violation = rowCutPointer->violated(solution); if (violation>=requiredViolation_) cs.insert(*rowCutPointer); } if (probingInfo_) { int number01 = probingInfo_->numberIntegers(); const cliqueEntry * entry = probingInfo_->fixEntries(); const int * toZero = probingInfo_->toZero(); const int * toOne = probingInfo_->toOne(); const int * integerVariable = probingInfo_->integerVariable(); const double * lower = si.getColLower(); const double * upper = si.getColUpper(); OsiRowCut cut; int column[2]; double element[2]; for (int i=0;i<number01;i++) { int iColumn=integerVariable[i]; if (upper[iColumn]==lower[iColumn]) continue; double value1 = solution[iColumn]; for (int j=toZero[i];j<toOne[i];j++) { int jColumn=sequenceInCliqueEntry(entry[j]); if (jColumn<number01) { jColumn=integerVariable[jColumn]; assert (jColumn>=0); double value2 = solution[jColumn]; if (oneFixesInCliqueEntry(entry[j])) { double violation = 1.0-value1-value2; if (violation>requiredViolation_) { //printf("XXX can do %d + %d >=1\n",iColumn,jColumn); cut.setLb(1.0); cut.setUb(COIN_DBL_MAX); column[0]=iColumn; element[0]=1.0; column[1]=jColumn; element[1]= 1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } else { double violation = value2-value1; if (violation>requiredViolation_) { //printf("XXX can do %d >= %d\n",iColumn,jColumn); cut.setLb(0.0); cut.setUb(COIN_DBL_MAX); column[0]=iColumn; element[0]=1.0; column[1]=jColumn; element[1]= -1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } } else { jColumn -= number01; // not 0-1 double value2 = solution[jColumn]; double lowerValue = lower[jColumn]; double upperValue = upper[jColumn]; if (oneFixesInCliqueEntry(entry[j])) { double violation = upperValue-value1*(upperValue-lowerValue)-value2; if (violation>requiredViolation_) { //printf("XXX can do %g*%d + %d >=%g\n",(upperValue-lowerValue),iColumn,jColumn,upperValue); cut.setLb(upperValue); cut.setUb(COIN_DBL_MAX); column[0]=iColumn; element[0]=upperValue-lowerValue; column[1]=jColumn; element[1]= 1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } else { double violation = value2-value1*(upperValue-lowerValue)-lowerValue; if (violation>requiredViolation_) { //printf("XXX can do %g*%d >= %d -%g\n",(upperValue-lowerValue),iColumn,jColumn,lowerValue); cut.setLb(-lowerValue); cut.setUb(COIN_DBL_MAX); column[0]=iColumn; element[0]=upperValue-lowerValue; column[1]=jColumn; element[1]= -1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } } } for (int j=toOne[i];j<toZero[i+1];j++) { int jColumn=sequenceInCliqueEntry(entry[j]); if (jColumn<number01) { jColumn=integerVariable[jColumn]; assert (jColumn>=0); double value2 = solution[jColumn]; if (oneFixesInCliqueEntry(entry[j])) { double violation = value1-value2; if (violation>requiredViolation_) { //printf("XXX can do %d <= %d\n",iColumn,jColumn); cut.setLb(-COIN_DBL_MAX); cut.setUb(0.0); column[0]=iColumn; element[0]=1.0; column[1]=jColumn; element[1]= -1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } else { double violation = value1+value2-1.0; if (violation>requiredViolation_) { //printf("XXX can do %d + %d <=1\n",iColumn,jColumn); cut.setLb(-COIN_DBL_MAX); cut.setUb(1.0); column[0]=iColumn; element[0]=1.0; column[1]=jColumn; element[1]= 1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } } else { jColumn -= number01; // not 0-1 double value2 = solution[jColumn]; double lowerValue = lower[jColumn]; double upperValue = upper[jColumn]; if (oneFixesInCliqueEntry(entry[j])) { double violation = lowerValue +(upperValue-lowerValue)*value1-value2; if (violation>requiredViolation_) { //printf("XXX can do %g*%d <= %d -%g\n",(upperValue-lowerValue),iColumn,jColumn,lowerValue); cut.setLb(-COIN_DBL_MAX); cut.setUb(-lowerValue); column[0]=iColumn; element[0]=upperValue-lowerValue; column[1]=jColumn; element[1]= -1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } else { double violation = (upperValue-lowerValue)*value1+value2-upperValue; if (violation>requiredViolation_) { //printf("XXX can do %g*%d + %d <=%g\n",(upperValue-lowerValue),iColumn,jColumn,upperValue); cut.setLb(-COIN_DBL_MAX); cut.setUb(upperValue); column[0]=iColumn; element[0]=upperValue-lowerValue; column[1]=jColumn; element[1]= 1.0; cut.setEffectiveness(violation); cut.setRow(2,column,element,false); cs.insert(cut); } } } } } } }
// inner part of dive int CbcHeuristicDive::solution(double & solutionValue, int & numberNodes, int & numberCuts, OsiRowCut ** cuts, CbcSubProblem ** & nodes, double * newSolution) { #ifdef DIVE_DEBUG int nRoundInfeasible = 0; int nRoundFeasible = 0; #endif int reasonToStop = 0; double time1 = CoinCpuTime(); int numberSimplexIterations = 0; int maxSimplexIterations = (model_->getNodeCount()) ? maxSimplexIterations_ : maxSimplexIterationsAtRoot_; // but can't be exactly coin_int_max maxSimplexIterations = CoinMin(maxSimplexIterations,COIN_INT_MAX>>3); OsiSolverInterface * solver = cloneBut(6); // was model_->solver()->clone(); # ifdef COIN_HAS_CLP OsiClpSolverInterface * clpSolver = dynamic_cast<OsiClpSolverInterface *> (solver); if (clpSolver) { ClpSimplex * clpSimplex = clpSolver->getModelPtr(); int oneSolveIts = clpSimplex->maximumIterations(); oneSolveIts = CoinMin(1000+2*(clpSimplex->numberRows()+clpSimplex->numberColumns()),oneSolveIts); clpSimplex->setMaximumIterations(oneSolveIts); if (!nodes) { // say give up easily clpSimplex->setMoreSpecialOptions(clpSimplex->moreSpecialOptions() | 64); } else { // get ray int specialOptions = clpSimplex->specialOptions(); specialOptions &= ~0x3100000; specialOptions |= 32; clpSimplex->setSpecialOptions(specialOptions); clpSolver->setSpecialOptions(clpSolver->specialOptions() | 1048576); if ((model_->moreSpecialOptions()&16777216)!=0) { // cutoff is constraint clpSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX); } } } # endif const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); const double * solution = solver->getColSolution(); const double * objective = solver->getObjCoefficients(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); int numberRows = matrix_.getNumRows(); assert (numberRows <= solver->getNumRows()); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); double direction = solver->getObjSense(); // 1 for min, -1 for max double newSolutionValue = direction * solver->getObjValue(); int returnCode = 0; // Column copy const double * element = matrix_.getElements(); const int * row = matrix_.getIndices(); const CoinBigIndex * columnStart = matrix_.getVectorStarts(); const int * columnLength = matrix_.getVectorLengths(); #ifdef DIVE_FIX_BINARY_VARIABLES // Row copy const double * elementByRow = matrixByRow_.getElements(); const int * column = matrixByRow_.getIndices(); const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts(); const int * rowLength = matrixByRow_.getVectorLengths(); #endif // Get solution array for heuristic solution int numberColumns = solver->getNumCols(); memcpy(newSolution, solution, numberColumns*sizeof(double)); // vectors to store the latest variables fixed at their bounds int* columnFixed = new int [numberIntegers]; double* originalBound = new double [numberIntegers+2*numberColumns]; double * lowerBefore = originalBound+numberIntegers; double * upperBefore = lowerBefore+numberColumns; memcpy(lowerBefore,lower,numberColumns*sizeof(double)); memcpy(upperBefore,upper,numberColumns*sizeof(double)); double * lastDjs=newSolution+numberColumns; bool * fixedAtLowerBound = new bool [numberIntegers]; PseudoReducedCost * candidate = new PseudoReducedCost [numberIntegers]; double * random = new double [numberIntegers]; int maxNumberAtBoundToFix = static_cast<int> (floor(percentageToFix_ * numberIntegers)); assert (!maxNumberAtBoundToFix||!nodes); // count how many fractional variables int numberFractionalVariables = 0; for (int i = 0; i < numberIntegers; i++) { random[i] = randomNumberGenerator_.randomDouble() + 0.3; int iColumn = integerVariable[i]; double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { numberFractionalVariables++; } } const double* reducedCost = NULL; // See if not NLP if (model_->solverCharacteristics()->reducedCostsAccurate()) reducedCost = solver->getReducedCost(); int iteration = 0; while (numberFractionalVariables) { iteration++; // initialize any data initializeData(); // select a fractional variable to bound int bestColumn = -1; int bestRound; // -1 rounds down, +1 rounds up bool canRound = selectVariableToBranch(solver, newSolution, bestColumn, bestRound); // if the solution is not trivially roundable, we don't try to round; // if the solution is trivially roundable, we try to round. However, // if the rounded solution is worse than the current incumbent, // then we don't round and proceed normally. In this case, the // bestColumn will be a trivially roundable variable if (canRound) { // check if by rounding all fractional variables // we get a solution with an objective value // better than the current best integer solution double delta = 0.0; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { assert(downLocks_[i] == 0 || upLocks_[i] == 0); double obj = objective[iColumn]; if (downLocks_[i] == 0 && upLocks_[i] == 0) { if (direction * obj >= 0.0) delta += (floor(value) - value) * obj; else delta += (ceil(value) - value) * obj; } else if (downLocks_[i] == 0) delta += (floor(value) - value) * obj; else delta += (ceil(value) - value) * obj; } } if (direction*(solver->getObjValue() + delta) < solutionValue) { #ifdef DIVE_DEBUG nRoundFeasible++; #endif if (!nodes||bestColumn<0) { // Round all the fractional variables for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { assert(downLocks_[i] == 0 || upLocks_[i] == 0); if (downLocks_[i] == 0 && upLocks_[i] == 0) { if (direction * objective[iColumn] >= 0.0) newSolution[iColumn] = floor(value); else newSolution[iColumn] = ceil(value); } else if (downLocks_[i] == 0) newSolution[iColumn] = floor(value); else newSolution[iColumn] = ceil(value); } } break; } else { // can't round if going to use in branching int i; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[bestColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { if (iColumn==bestColumn) { assert(downLocks_[i] == 0 || upLocks_[i] == 0); double obj = objective[bestColumn]; if (downLocks_[i] == 0 && upLocks_[i] == 0) { if (direction * obj >= 0.0) bestRound=-1; else bestRound=1; } else if (downLocks_[i] == 0) bestRound=-1; else bestRound=1; break; } } } } } #ifdef DIVE_DEBUG else nRoundInfeasible++; #endif } // do reduced cost fixing #ifdef DIVE_DEBUG int numberFixed = reducedCostFix(solver); std::cout << "numberReducedCostFixed = " << numberFixed << std::endl; #else reducedCostFix(solver); #endif int numberAtBoundFixed = 0; #ifdef DIVE_FIX_BINARY_VARIABLES // fix binary variables based on pseudo reduced cost if (binVarIndex_.size()) { int cnt = 0; int n = static_cast<int>(binVarIndex_.size()); for (int j = 0; j < n; j++) { int iColumn1 = binVarIndex_[j]; double value = newSolution[iColumn1]; if (fabs(value) <= integerTolerance && lower[iColumn1] != upper[iColumn1]) { double maxPseudoReducedCost = 0.0; #ifdef DIVE_DEBUG std::cout << "iColumn1 = " << iColumn1 << ", value = " << value << std::endl; #endif int iRow = vbRowIndex_[j]; double chosenValue = 0.0; for (int k = rowStart[iRow]; k < rowStart[iRow] + rowLength[iRow]; k++) { int iColumn2 = column[k]; #ifdef DIVE_DEBUG std::cout << "iColumn2 = " << iColumn2 << std::endl; #endif if (iColumn1 != iColumn2) { double pseudoReducedCost = fabs(reducedCost[iColumn2] * elementByRow[k]); #ifdef DIVE_DEBUG int k2; for (k2 = rowStart[iRow]; k2 < rowStart[iRow] + rowLength[iRow]; k2++) { if (column[k2] == iColumn1) break; } std::cout << "reducedCost[" << iColumn2 << "] = " << reducedCost[iColumn2] << ", elementByRow[" << iColumn2 << "] = " << elementByRow[k] << ", elementByRow[" << iColumn1 << "] = " << elementByRow[k2] << ", pseudoRedCost = " << pseudoReducedCost << std::endl; #endif if (pseudoReducedCost > maxPseudoReducedCost) maxPseudoReducedCost = pseudoReducedCost; } else { // save value chosenValue = fabs(elementByRow[k]); } } assert (chosenValue); maxPseudoReducedCost /= chosenValue; #ifdef DIVE_DEBUG std::cout << ", maxPseudoRedCost = " << maxPseudoReducedCost << std::endl; #endif candidate[cnt].var = iColumn1; candidate[cnt++].pseudoRedCost = maxPseudoReducedCost; } } #ifdef DIVE_DEBUG std::cout << "candidates for rounding = " << cnt << std::endl; #endif std::sort(candidate, candidate + cnt, compareBinaryVars); for (int i = 0; i < cnt; i++) { int iColumn = candidate[i].var; if (numberAtBoundFixed < maxNumberAtBoundToFix) { columnFixed[numberAtBoundFixed] = iColumn; originalBound[numberAtBoundFixed] = upper[iColumn]; fixedAtLowerBound[numberAtBoundFixed] = true; solver->setColUpper(iColumn, lower[iColumn]); numberAtBoundFixed++; if (numberAtBoundFixed == maxNumberAtBoundToFix) break; } } } #endif // fix other integer variables that are at their bounds int cnt = 0; #ifdef GAP double gap = 1.0e30; #endif if (reducedCost && true) { #ifndef JJF_ONE cnt = fixOtherVariables(solver, solution, candidate, random); #else #ifdef GAP double cutoff = model_->getCutoff() ; if (cutoff < 1.0e20 && false) { double direction = solver->getObjSense() ; gap = cutoff - solver->getObjValue() * direction ; gap *= 0.1; // Fix more if plausible double tolerance; solver->getDblParam(OsiDualTolerance, tolerance) ; if (gap <= 0.0) gap = tolerance; gap += 100.0 * tolerance; } int nOverGap = 0; #endif int numberFree = 0; int numberFixed = 0; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (upper[iColumn] > lower[iColumn]) { numberFree++; double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) <= integerTolerance) { candidate[cnt].var = iColumn; candidate[cnt++].pseudoRedCost = fabs(reducedCost[iColumn] * random[i]); #ifdef GAP if (fabs(reducedCost[iColumn]) > gap) nOverGap++; #endif } } else { numberFixed++; } } #ifdef GAP int nLeft = maxNumberAtBoundToFix - numberAtBoundFixed; #ifdef CLP_INVESTIGATE4 printf("cutoff %g obj %g nover %d - %d free, %d fixed\n", cutoff, solver->getObjValue(), nOverGap, numberFree, numberFixed); #endif if (nOverGap > nLeft && true) { nOverGap = CoinMin(nOverGap, nLeft + maxNumberAtBoundToFix / 2); maxNumberAtBoundToFix += nOverGap - nLeft; } #else #ifdef CLP_INVESTIGATE4 printf("cutoff %g obj %g - %d free, %d fixed\n", model_->getCutoff(), solver->getObjValue(), numberFree, numberFixed); #endif #endif #endif } else { for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (upper[iColumn] > lower[iColumn]) { double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) <= integerTolerance) { candidate[cnt].var = iColumn; candidate[cnt++].pseudoRedCost = numberIntegers - i; } } } } std::sort(candidate, candidate + cnt, compareBinaryVars); for (int i = 0; i < cnt; i++) { int iColumn = candidate[i].var; if (upper[iColumn] > lower[iColumn]) { double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) <= integerTolerance && numberAtBoundFixed < maxNumberAtBoundToFix) { // fix the variable at one of its bounds if (fabs(lower[iColumn] - value) <= integerTolerance) { columnFixed[numberAtBoundFixed] = iColumn; originalBound[numberAtBoundFixed] = upper[iColumn]; fixedAtLowerBound[numberAtBoundFixed] = true; solver->setColUpper(iColumn, lower[iColumn]); numberAtBoundFixed++; } else if (fabs(upper[iColumn] - value) <= integerTolerance) { columnFixed[numberAtBoundFixed] = iColumn; originalBound[numberAtBoundFixed] = lower[iColumn]; fixedAtLowerBound[numberAtBoundFixed] = false; solver->setColLower(iColumn, upper[iColumn]); numberAtBoundFixed++; } if (numberAtBoundFixed == maxNumberAtBoundToFix) break; } } } #ifdef DIVE_DEBUG std::cout << "numberAtBoundFixed = " << numberAtBoundFixed << std::endl; #endif double originalBoundBestColumn; double bestColumnValue; int whichWay; if (bestColumn >= 0) { bestColumnValue = newSolution[bestColumn]; if (bestRound < 0) { originalBoundBestColumn = upper[bestColumn]; solver->setColUpper(bestColumn, floor(bestColumnValue)); whichWay=0; } else { originalBoundBestColumn = lower[bestColumn]; solver->setColLower(bestColumn, ceil(bestColumnValue)); whichWay=1; } } else { break; } int originalBestRound = bestRound; int saveModelOptions = model_->specialOptions(); while (1) { model_->setSpecialOptions(saveModelOptions | 2048); solver->resolve(); model_->setSpecialOptions(saveModelOptions); if (!solver->isAbandoned()&&!solver->isIterationLimitReached()) { numberSimplexIterations += solver->getIterationCount(); } else { numberSimplexIterations = maxSimplexIterations + 1; reasonToStop += 100; break; } if (!solver->isProvenOptimal()) { if (nodes) { if (solver->isProvenPrimalInfeasible()) { if (maxSimplexIterationsAtRoot_!=COIN_INT_MAX) { // stop now printf("stopping on first infeasibility\n"); break; } else if (cuts) { // can do conflict cut printf("could do intermediate conflict cut\n"); bool localCut; OsiRowCut * cut = model_->conflictCut(solver,localCut); if (cut) { if (!localCut) { model_->makePartialCut(cut,solver); cuts[numberCuts++]=cut; } else { delete cut; } } } } else { reasonToStop += 10; break; } } if (numberAtBoundFixed > 0) { // Remove the bound fix for variables that were at bounds for (int i = 0; i < numberAtBoundFixed; i++) { int iColFixed = columnFixed[i]; if (fixedAtLowerBound[i]) solver->setColUpper(iColFixed, originalBound[i]); else solver->setColLower(iColFixed, originalBound[i]); } numberAtBoundFixed = 0; } else if (bestRound == originalBestRound) { bestRound *= (-1); whichWay |=2; if (bestRound < 0) { solver->setColLower(bestColumn, originalBoundBestColumn); solver->setColUpper(bestColumn, floor(bestColumnValue)); } else { solver->setColLower(bestColumn, ceil(bestColumnValue)); solver->setColUpper(bestColumn, originalBoundBestColumn); } } else break; } else break; } if (!solver->isProvenOptimal() || direction*solver->getObjValue() >= solutionValue) { reasonToStop += 1; } else if (iteration > maxIterations_) { reasonToStop += 2; } else if (CoinCpuTime() - time1 > maxTime_) { reasonToStop += 3; } else if (numberSimplexIterations > maxSimplexIterations) { reasonToStop += 4; // also switch off #ifdef CLP_INVESTIGATE printf("switching off diving as too many iterations %d, %d allowed\n", numberSimplexIterations, maxSimplexIterations); #endif when_ = 0; } else if (solver->getIterationCount() > 1000 && iteration > 3 && !nodes) { reasonToStop += 5; // also switch off #ifdef CLP_INVESTIGATE printf("switching off diving one iteration took %d iterations (total %d)\n", solver->getIterationCount(), numberSimplexIterations); #endif when_ = 0; } memcpy(newSolution, solution, numberColumns*sizeof(double)); numberFractionalVariables = 0; double sumFractionalVariables=0.0; for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; double away = fabs(floor(value + 0.5) - value); if (away > integerTolerance) { numberFractionalVariables++; sumFractionalVariables += away; } } if (nodes) { // save information //branchValues[numberNodes]=bestColumnValue; //statuses[numberNodes]=whichWay+(bestColumn<<2); //bases[numberNodes]=solver->getWarmStart(); ClpSimplex * simplex = clpSolver->getModelPtr(); CbcSubProblem * sub = new CbcSubProblem(clpSolver,lowerBefore,upperBefore, simplex->statusArray(),numberNodes); nodes[numberNodes]=sub; // other stuff sub->branchValue_=bestColumnValue; sub->problemStatus_=whichWay; sub->branchVariable_=bestColumn; sub->objectiveValue_ = simplex->objectiveValue(); sub->sumInfeasibilities_ = sumFractionalVariables; sub->numberInfeasibilities_ = numberFractionalVariables; printf("DiveNode %d column %d way %d bvalue %g obj %g\n", numberNodes,sub->branchVariable_,sub->problemStatus_, sub->branchValue_,sub->objectiveValue_); numberNodes++; if (solver->isProvenOptimal()) { memcpy(lastDjs,solver->getReducedCost(),numberColumns*sizeof(double)); memcpy(lowerBefore,lower,numberColumns*sizeof(double)); memcpy(upperBefore,upper,numberColumns*sizeof(double)); } } if (!numberFractionalVariables||reasonToStop) break; } if (nodes) { printf("Exiting dive for reason %d\n",reasonToStop); if (reasonToStop>1) { printf("problems in diving\n"); int whichWay=nodes[numberNodes-1]->problemStatus_; CbcSubProblem * sub; if ((whichWay&2)==0) { // leave both ways sub = new CbcSubProblem(*nodes[numberNodes-1]); nodes[numberNodes++]=sub; } else { sub = nodes[numberNodes-1]; } if ((whichWay&1)==0) sub->problemStatus_=whichWay|1; else sub->problemStatus_=whichWay&~1; } if (!numberNodes) { // was good at start! - create fake clpSolver->resolve(); ClpSimplex * simplex = clpSolver->getModelPtr(); CbcSubProblem * sub = new CbcSubProblem(clpSolver,lowerBefore,upperBefore, simplex->statusArray(),numberNodes); nodes[numberNodes]=sub; // other stuff sub->branchValue_=0.0; sub->problemStatus_=0; sub->branchVariable_=-1; sub->objectiveValue_ = simplex->objectiveValue(); sub->sumInfeasibilities_ = 0.0; sub->numberInfeasibilities_ = 0; printf("DiveNode %d column %d way %d bvalue %g obj %g\n", numberNodes,sub->branchVariable_,sub->problemStatus_, sub->branchValue_,sub->objectiveValue_); numberNodes++; assert (solver->isProvenOptimal()); } nodes[numberNodes-1]->problemStatus_ |= 256*reasonToStop; // use djs as well if (solver->isProvenPrimalInfeasible()&&cuts) { // can do conflict cut and re-order printf("could do final conflict cut\n"); bool localCut; OsiRowCut * cut = model_->conflictCut(solver,localCut); if (cut) { printf("cut - need to use conflict and previous djs\n"); if (!localCut) { model_->makePartialCut(cut,solver); cuts[numberCuts++]=cut; } else { delete cut; } } else { printf("bad conflict - just use previous djs\n"); } } } // re-compute new solution value double objOffset = 0.0; solver->getDblParam(OsiObjOffset, objOffset); newSolutionValue = -objOffset; for (int i = 0 ; i < numberColumns ; i++ ) newSolutionValue += objective[i] * newSolution[i]; newSolutionValue *= direction; //printf("new solution value %g %g\n",newSolutionValue,solutionValue); if (newSolutionValue < solutionValue && !reasonToStop) { double * rowActivity = new double[numberRows]; memset(rowActivity, 0, numberRows*sizeof(double)); // paranoid check memset(rowActivity, 0, numberRows*sizeof(double)); for (int i = 0; i < numberColumns; i++) { int j; double value = newSolution[i]; if (value) { for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; rowActivity[iRow] += value * element[j]; } } } // check was approximately feasible bool feasible = true; for (int i = 0; i < numberRows; i++) { if (rowActivity[i] < rowLower[i]) { if (rowActivity[i] < rowLower[i] - 1000.0*primalTolerance) feasible = false; } else if (rowActivity[i] > rowUpper[i]) { if (rowActivity[i] > rowUpper[i] + 1000.0*primalTolerance) feasible = false; } } for (int i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double value = newSolution[iColumn]; if (fabs(floor(value + 0.5) - value) > integerTolerance) { feasible = false; break; } } if (feasible) { // new solution solutionValue = newSolutionValue; //printf("** Solution of %g found by CbcHeuristicDive\n",newSolutionValue); //if (cuts) //clpSolver->getModelPtr()->writeMps("good8.mps", 2); returnCode = 1; } else { // Can easily happen //printf("Debug CbcHeuristicDive giving bad solution\n"); } delete [] rowActivity; } #ifdef DIVE_DEBUG std::cout << "nRoundInfeasible = " << nRoundInfeasible << ", nRoundFeasible = " << nRoundFeasible << ", returnCode = " << returnCode << ", reasonToStop = " << reasonToStop << ", simplexIts = " << numberSimplexIterations << ", iterations = " << iteration << std::endl; #endif delete [] columnFixed; delete [] originalBound; delete [] fixedAtLowerBound; delete [] candidate; delete [] random; delete [] downArray_; downArray_ = NULL; delete [] upArray_; upArray_ = NULL; delete solver; return returnCode; }
int main (int argc, const char *argv[]) { OsiClpSolverInterface solver1; //#define USE_OSI_NAMES #ifdef USE_OSI_NAMES // Say we are keeping names (a bit slower this way) solver1.setIntParam(OsiNameDiscipline,1); #endif // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } // Tell solver to return fast if presolve or initial solve infeasible solver1.getModelPtr()->setMoreSpecialOptions(3); // Pass to Cbc initialize defaults CbcModel modelA(solver1); CbcModel * model = &modelA; CbcMain0(modelA); // Event handler MyEventHandler3 eventHandler; model->passInEventHandler(&eventHandler); /* Now go into code for standalone solver Could copy arguments and add -quit at end to be safe but this will do */ if (argc>2) { CbcMain1(argc-1,argv+1,modelA,callBack); } else { const char * argv2[]={"driver6","-solve","-quit"}; CbcMain1(3,argv2,modelA,callBack); } // Solver was cloned so get current copy OsiSolverInterface * solver = model->solver(); // Print solution if finished (could get from model->bestSolution() as well if (model->bestSolution()) { const double * solution = solver->getColSolution(); int iColumn; int numberColumns = solver->getNumCols(); std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14); std::cout<<"--------------------------------------"<<std::endl; #ifdef USE_OSI_NAMES for (iColumn=0;iColumn<numberColumns;iColumn++) { double value=solution[iColumn]; if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) std::cout<<std::setw(6)<<iColumn<<" "<<std::setw(8)<<setiosflags(std::ios::left)<<solver->getColName(iColumn) <<resetiosflags(std::ios::adjustfield)<<std::setw(14)<<" "<<value<<std::endl; } #else // names may not be in current solver - use original for (iColumn=0;iColumn<numberColumns;iColumn++) { double value=solution[iColumn]; if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) std::cout<<std::setw(6)<<iColumn<<" "<<std::setw(8)<<setiosflags(std::ios::left)<<solver1.getModelPtr()->columnName(iColumn) <<resetiosflags(std::ios::adjustfield)<<std::setw(14)<<" "<<value<<std::endl; } #endif std::cout<<"--------------------------------------"<<std::endl; std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific); } else { std::cout<<" No solution!"<<std::endl; } return 0; }