// Creates a branching object CbcBranchingObject * CbcLink::createBranch(int way) { int j; const double * solution = model_->testSolution(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); OsiSolverInterface * solver = model_->solver(); const double * upper = solver->getColUpper(); int firstNonFixed=-1; int lastNonFixed=-1; int firstNonZero=-1; int lastNonZero = -1; double weight = 0.0; double sum =0.0; int base=0; for (j=0;j<numberMembers_;j++) { for (int k=0;k<numberLinks_;k++) { int iColumn = which_[base+k]; if (upper[iColumn]) { double value = CoinMax(0.0,solution[iColumn]); sum += value; if (firstNonFixed<0) firstNonFixed=j; lastNonFixed=j; if (value>integerTolerance) { weight += weights_[j]*value; if (firstNonZero<0) firstNonZero=j; lastNonZero=j; } } } base += numberLinks_; } assert (lastNonZero-firstNonZero>=sosType_) ; // find where to branch assert (sum>0.0); weight /= sum; int iWhere; double separator=0.0; for (iWhere=firstNonZero;iWhere<lastNonZero;iWhere++) if (weight<weights_[iWhere+1]) break; if (sosType_==1) { // SOS 1 separator = 0.5 *(weights_[iWhere]+weights_[iWhere+1]); } else { // SOS 2 if (iWhere==firstNonFixed) iWhere++;; if (iWhere==lastNonFixed-1) iWhere = lastNonFixed-2; separator = weights_[iWhere+1]; } // create object CbcBranchingObject * branch; branch = new CbcLinkBranchingObject(model_,this,way,separator); return branch; }
double CbcNWay::infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { int numberUnsatis = 0; int j; OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double largestValue = 0.0; double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); double distance = CoinMin(value - lower[iColumn], upper[iColumn] - value); if (distance > integerTolerance) { numberUnsatis++; largestValue = CoinMax(distance, largestValue); } } preferredWay = 1; if (numberUnsatis) { return largestValue; } else { return 0.0; // satisfied } }
bool OsiColCut::infeasible(const OsiSolverInterface &im) const { const double * oldColLb = im.getColLower(); const double * oldColUb = im.getColUpper(); const CoinPackedVector & cutLbs = lbs(); const CoinPackedVector & cutUbs = ubs(); int i; for ( i=0; i<cutLbs.getNumElements(); i++ ) { int colIndx = cutLbs.getIndices()[i]; double newLb= cutLbs.getElements()[i] > oldColLb[colIndx] ? cutLbs.getElements()[i] : oldColLb[colIndx]; double newUb = oldColUb[colIndx]; if ( cutUbs.isExistingIndex(colIndx) ) if ( cutUbs[colIndx] < newUb ) newUb = cutUbs[colIndx]; if ( newLb > newUb ) return true; } for ( i=0; i<cutUbs.getNumElements(); i++ ) { int colIndx = cutUbs.getIndices()[i]; double newUb = cutUbs.getElements()[i] < oldColUb[colIndx] ? cutUbs.getElements()[i] : oldColUb[colIndx]; double newLb = oldColLb[colIndx]; if ( cutLbs.isExistingIndex(colIndx) ) if ( cutLbs[colIndx] > newLb ) newLb = cutLbs[colIndx]; if ( newUb < newLb ) return true; } return false; }
// Return "down" estimate double CbcSimpleIntegerPseudoCost::downEstimate() const { OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); if (upper[columnNumber_] == lower[columnNumber_]) { // fixed return 0.0; } double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double below = floor(value + integerTolerance); double above = below + 1.0; if (above > upper[columnNumber_]) { above = below; below = above - 1; } double downCost = CoinMax((value - below) * downPseudoCost_, 0.0); return downCost; }
//------------------------------------------------------------------- // 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); } }
// Apply bounds void OsiSolverBranch::applyBounds(OsiSolverInterface &solver, int way) const { int base = way + 1; assert(way == -1 || way == 1); int numberColumns = solver.getNumCols(); const double *columnLower = solver.getColLower(); 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]); solver.setColLower(iColumn, value); } else { int iRow = iColumn - numberColumns; const double *rowLower = solver.getRowLower(); double value = CoinMax(bound_[i], rowLower[iRow]); solver.setRowLower(iRow, value); } } const double *columnUpper = solver.getColUpper(); for (i = start_[base + 1]; i < start_[base + 2]; i++) { int iColumn = indices_[i]; if (iColumn < numberColumns) { double value = CoinMin(bound_[i], columnUpper[iColumn]); solver.setColUpper(iColumn, value); } else { int iRow = iColumn - numberColumns; const double *rowUpper = solver.getRowUpper(); double value = CoinMin(bound_[i], rowUpper[iRow]); solver.setRowUpper(iRow, value); } } }
// 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; }
double CbcSimpleIntegerPseudoCost::infeasibility(const OsiBranchingInformation * /*info*/, int &preferredWay) const { OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); if (upper[columnNumber_] == lower[columnNumber_]) { // fixed preferredWay = 1; return 0.0; } double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); /*printf("%d %g %g %g %g\n",columnNumber_,value,lower[columnNumber_], solution[columnNumber_],upper[columnNumber_]);*/ double nearest = floor(value + 0.5); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); double below = floor(value + integerTolerance); double above = below + 1.0; if (above > upper[columnNumber_]) { above = below; below = above - 1; } double downCost = CoinMax((value - below) * downPseudoCost_, 0.0); double upCost = CoinMax((above - value) * upPseudoCost_, 0.0); if (downCost >= upCost) preferredWay = 1; else preferredWay = -1; // See if up down choice set if (upDownSeparator_ > 0.0) { preferredWay = (value - below >= upDownSeparator_) ? 1 : -1; } if (preferredWay_) preferredWay = preferredWay_; if (fabs(value - nearest) <= integerTolerance) { return 0.0; } else { // can't get at model so 1,2 don't make sense assert(method_ < 1 || method_ > 2); if (!method_) return CoinMin(downCost, upCost); else return CoinMax(downCost, upCost); } }
/// check if (column!) cuts compatible with solver interface int CouenneDisjCuts::checkDisjSide (OsiSolverInterface &si, OsiCuts *cuts) const { int retval = COUENNE_FEASIBLE; const double *lower = si.getColLower (), *upper = si.getColUpper (); // check each colcut in cuts (there should be just one) for (int i = cuts -> sizeColCuts (); i--;) { // lower bounds const CoinPackedVector &lbs = cuts -> colCutPtr (i) -> lbs (); const int *lindices = lbs.getIndices (); const double *lvalues = lbs.getElements (); for (int j = lbs.getNumElements (); j--;) { register double lb = *lvalues++; register int ind = *lindices++; if (lb > upper [ind] + COUENNE_EPS) // fathom node return COUENNE_INFEASIBLE; if (lb > lower [ind] + COUENNE_EPS) retval = COUENNE_TIGHTENED; } // upper bounds const CoinPackedVector &ubs = cuts -> colCutPtr (i) -> ubs (); const int *uindices = ubs.getIndices (); const double *uvalues = ubs.getElements (); for (int j = ubs.getNumElements (); j--;) { register double ub = *uvalues++; register int ind = *uindices++; if (ub < lower [ind] - COUENNE_EPS) // fathom node return COUENNE_INFEASIBLE; if (ub < upper [ind] - COUENNE_EPS) retval = COUENNE_TIGHTENED; } } return retval; }
// 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); }
// 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; }
// 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); } }
// This looks at solution and sets bounds to contain solution void CbcNWay::feasibleRegion() { int j; OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); if (value >= upper[iColumn] - integerTolerance) { solver->setColLower(iColumn, upper[iColumn]); } else { assert (value <= lower[iColumn] + integerTolerance); solver->setColUpper(iColumn, lower[iColumn]); } } }
// Infeasibility - large is 0.5 double CbcSimpleIntegerFixed::infeasibility(int & preferredWay) const { OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnNumber_]; value = CoinMax(value, lower[columnNumber_]); value = CoinMin(value, upper[columnNumber_]); /*printf("%d %g %g %g %g\n",columnNumber_,value,lower[columnNumber_], solution[columnNumber_],upper[columnNumber_]);*/ double nearest = floor(value+(1.0-breakEven_)); assert (breakEven_>0.0&&breakEven_<1.0); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); if (nearest>value) preferredWay=1; else preferredWay=-1; if (preferredWay_) preferredWay=preferredWay_; 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) { if (upper[columnNumber_]==lower[columnNumber_]) return 0.0; else return 1.0e-5; } else { return weight; } }
// 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); }
//############################################################################# 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::greedyHeuristic() { MibSModel * model = MibSModel_; //OsiSolverInterface * oSolver = model->getSolver(); OsiSolverInterface * oSolver = model->solver(); double uObjSense(oSolver->getObjSense()); double lObjSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * uColIndices = model->getUpperColInd(); int * lColIndices = model->getLowerColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); double * intCost = model->getInterdictCost(); double intBudget = model->getInterdictBudget(); int tCols(uCols + lCols); assert(tCols == oSolver->getNumCols()); int i(0), ind_min_wt(0); double usedBudget(0.0); double * fixedVars = new double[lCols]; double * testsol = new double[tCols]; CoinZeroN(fixedVars, lCols); CoinZeroN(testsol, tCols); std::multimap<double, int> lObjCoeffsOrd; for(i = 0; i < lCols; i++) lObjCoeffsOrd.insert(std::pair<double, int>(lObjCoeffs[i] * lObjSense, i)); if(!bestSol_) bestSol_ = new double[tCols]; //initialize the best solution information //bestObjVal_ = model->getSolver()->getInfinity() * uObjSense; //CoinZeroN(bestSol_, tCols); std::multimap<double, int>::iterator iter; //std::multimap<double, int>::iterator first; //std::multimap<double, int>::iterator last; //int dist = std::distance(first, last); srandom((unsigned) time(NULL)); int randchoice(0); if(0) std::cout << "randchoice " << randchoice << std::endl; double cost(0.0); //starting from the largest, fix corr upper-level variables //then, with these fixed, solve the lower-level problem //this yields a feasible solution iter = lObjCoeffsOrd.begin(); while((usedBudget < intBudget) && (iter != lObjCoeffsOrd.end())){ ind_min_wt = iter->second; cost = intCost[ind_min_wt]; testsol[uColIndices[ind_min_wt]] = 1.0; double min_wt = iter->first; if(0){ std::cout << "upper: " << ind_min_wt << " " << uColIndices[ind_min_wt] << " " << oSolver->getColUpper()[uColIndices[ind_min_wt]] << " " << oSolver->getColLower()[uColIndices[ind_min_wt]] << std::endl; std::cout << "lower: " << ind_min_wt << " " << lColIndices[ind_min_wt] << " " << oSolver->getColUpper()[lColIndices[ind_min_wt]] << std::endl; } //if((oSolver->getColUpper()[uColIndices[ind_min_wt]] == 1.0) //&& (oSolver->getColUpper()[lColIndices[ind_min_wt]] > 0)){ if(oSolver->getColUpper()[uColIndices[ind_min_wt]] > etol_){ //if(((usedBudget + cost) <= intBudget) // && checkLowerFeasibility(oSolver, testsol)){ if((usedBudget + cost) <= intBudget){ //FIXME: SHOULD BE CHECKING FOR CURRENT BOUNDS HERE //fix the corresponding upper-level variable to 1 randchoice = random() % 2; if(0) std::cout << "randchoice " << random << std::endl; if(randchoice){ fixedVars[ind_min_wt] = 1.0; usedBudget += intCost[ind_min_wt]; } } } else{ testsol[uColIndices[ind_min_wt]] = 0; //break; } iter++; } /* now we find a feasible solution by fixing upper-level vars and solving the lower-level problem */ double * incumbentSol = new double[tCols]; double * colsol = new double[tCols]; CoinZeroN(colsol, tCols); for(i = 0; i < uCols; i++){ colsol[uColIndices[i]] = fixedVars[i]; if(fixedVars[i] == 1.0) if(0) std::cout << "fixed " << i << std::endl; } bfSol * sol = getBilevelSolution(colsol, lObjSense * oSolver->getInfinity()); if(sol){ double incumbentObjVal = sol->getObjVal(); CoinCopyN(sol->getColumnSol(), tCols, incumbentSol); MibSSolution * mibSol = new MibSSolution(tCols, incumbentSol, incumbentObjVal, model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); } //bestObjVal_ = incumbentObjVal; //CoinCopyN(incumbentSol, tCols, bestSol_); delete [] incumbentSol; delete [] testsol; //delete [] colsol; //delete [] fixedVars; //delete sol; }
//############################################################################# 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(); } }
//------------------------------------------------------------------- // 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); } } } } } } }
/** Clean an OsiCut \return 1 if min violation is too small \return 2 if small coefficient can not be removed \return 3 if dynamic is too big \return 4 if too many non zero element*/ int Validator::cleanCut(OsiRowCut & aCut, const double * solCut, const OsiSolverInterface &si, const CglParam& par, const double * origColLower, const double * origColUpper) const { /** Compute fill-in in si */ int numcols = si.getNumCols(); const double * colLower = (origColLower) ? origColLower : si.getColLower(); const double * colUpper = (origColUpper) ? origColUpper : si.getColUpper(); int maxNnz = static_cast<int> (maxFillIn_ * static_cast<double> (numcols)); double rhs = aCut.lb(); assert (aCut.ub()> 1e50); CoinPackedVector *vec = const_cast<CoinPackedVector *>(&aCut.row()); int * indices = vec->getIndices(); double * elems = vec->getElements(); int n = vec->getNumElements(); /** First compute violation if it is too small exit */ double violation = aCut.violated(solCut); if (violation < minViolation_) return 1; /** Now relax get dynamic and remove tiny elements */ int offset = 0; rhs -= 1e-8; double smallest = 1e100; double biggest = 0; for (int i = 0 ; i < n ; i++) { double val = fabs(elems[i]); if (val <= par.getEPS()) //try to remove coef { if (val>0 && val<1e-20) { offset++; continue; throw; } if (val==0) { offset++; continue; } int & iCol = indices[i]; if (elems[i]>0. && colUpper[iCol] < 10000.) { offset++; rhs -= elems[i] * colUpper[iCol]; elems[i]=0; } else if (elems[i]<0. && colLower[iCol] > -10000.) { offset++; rhs -= elems[i] * colLower[iCol]; elems[i]=0.; } else { #ifdef DEBUG std::cout<<"Small coefficient : "<<elems[i]<<" bounds : ["<<colLower[iCol]<<", "<<colUpper[iCol]<<std::endl; #endif numRejected_[SmallCoefficient]++; return SmallCoefficient; } } else //Not a small coefficient keep it { smallest = std::min(val,smallest); biggest = std::max (val,biggest); if (biggest > maxRatio_ * smallest) { #ifdef DEBUG std::cout<<"Whaooo "<<biggest/smallest<<std::endl; #endif numRejected_[BigDynamic]++; return BigDynamic; } if (offset) //if offset is zero current values are ok otherwise translate { int i2 = i - offset; indices[i2] = indices[i]; elems[i2] = elems[i]; } } } if ((n - offset) > maxNnz) { numRejected_[DenseCut] ++; return DenseCut; } if (offset == n) { numRejected_[EmptyCut]++; return EmptyCut; } if (offset) vec->truncate(n - offset); indices = vec->getIndices(); elems = vec->getElements(); n = vec->getNumElements(); aCut.setLb(rhs); violation = aCut.violated(solCut); if (violation < minViolation_) { numRejected_[SmallViolation]++; return SmallViolation; } return NoneAccepted; }
/**Clean cut 2, different algorithm. First check the dynamic of the cut if < maxRatio scale to a biggest coef of 1 otherwise scale it so that biggest coeff is 1 and try removing tinys ( < 1/maxRatio) either succeed or fail */ int Validator::cleanCut2(OsiRowCut & aCut, const double * solCut, const OsiSolverInterface &si, const CglParam &/* par */, const double * origColLower, const double * origColUpper) const { /** Compute fill-in in si */ int numcols = si.getNumCols(); // int numrows = si.getNumRows(); const double * colLower = (origColLower) ? origColLower : si.getColLower(); const double * colUpper = (origColUpper) ? origColUpper : si.getColUpper(); int maxNnz = static_cast<int> ( maxFillIn_ * static_cast<double> (numcols)); double rhs = aCut.lb(); assert (aCut.ub()> 1e50); CoinPackedVector *vec = const_cast<CoinPackedVector *>(&aCut.row()); // vec->sortIncrIndex(); int * indices = vec->getIndices(); double * elems = vec->getElements(); int n = vec->getNumElements(); if (n==0) { numRejected_[EmptyCut]++; return EmptyCut; } /** First compute violation if it is too small exit */ double violation = aCut.violated(solCut); if (violation < minViolation_) return 1; /** Now relax get dynamic and remove tiny elements */ int offset = 0; rhs -= 1e-10; double smallest = fabs(rhs); double biggest = smallest; double veryTiny = 1e-20; for (int i = 0 ; i < n ; i++) { double val = fabs(elems[i]); if (val > veryTiny) //tiny should be very very small { smallest = std::min(val,smallest); biggest = std::max (val,biggest); } } if (biggest > 1e9) { #ifdef DEBUG std::cout<<"Whaooo "<<biggest/smallest<<std::endl; #endif numRejected_[BigDynamic]++; return BigDynamic; } //rescale the cut so that biggest is 1e1. double toBeBiggest = rhsScale_; rhs *= (toBeBiggest / biggest); toBeBiggest /= biggest; for (int i = 0 ; i < n ; i++) { elems[i] *= toBeBiggest; } if (biggest > maxRatio_ * smallest) //we have to remove some small coefficients { double myTiny = biggest * toBeBiggest / maxRatio_; veryTiny *= toBeBiggest ; for (int i = 0 ; i < n ; i++) { double val = fabs(elems[i]); if (val < myTiny) { if (val< veryTiny) { offset++; continue; } int & iCol = indices[i]; if (elems[i]>0. && colUpper[iCol] < 1000.) { offset++; rhs -= elems[i] * colUpper[iCol]; elems[i]=0; } else if (elems[i]<0. && colLower[iCol] > -1000.) { offset++; rhs -= elems[i] * colLower[iCol]; elems[i]=0.; } else { numRejected_[SmallCoefficient]++; return SmallCoefficient; } } else //Not a small coefficient keep it { if (offset) //if offset is zero current values are ok { int i2 = i - offset; indices[i2] = indices[i]; elems[i2] = elems[i]; } } } } if ((n - offset) > maxNnz) { numRejected_[DenseCut] ++; return DenseCut; } if (offset) vec->truncate(n - offset); if (vec->getNumElements() == 0 ) { numRejected_[EmptyCut]++; return EmptyCut; } /** recheck violation */ aCut.setLb(rhs); violation = aCut.violated(solCut); if (violation < minViolation_) { numRejected_[SmallViolation]++; return SmallViolation; } assert(fabs(rhs)<1e09); return NoneAccepted; }
// 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); } }
// Create a list of rows which might yield cuts // The possible parameter is a list to cut down search void CglOddHole::createRowList( const OsiSolverInterface & si, const int * possible) { // Get basic problem information int nRows=si.getNumRows(); const CoinPackedMatrix * rowCopy = si.getMatrixByRow(); const int * column = rowCopy->getIndices(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const int * rowLength = rowCopy->getVectorLengths(); int rowIndex; delete [] suitableRows_; numberRows_=nRows; const double * rowElements = rowCopy->getElements(); const double * rowupper = si.getRowUpper(); const double * rowlower = si.getRowLower(); const double * collower = si.getColLower(); const double * colupper = si.getColUpper(); suitableRows_=new int[nRows]; if (possible) { memcpy(suitableRows_,possible,nRows*sizeof(int)); } else { int i; for (i=0;i<nRows;i++) { suitableRows_[i]=1; } } for (rowIndex=0; rowIndex<nRows; rowIndex++){ double rhs1=rowupper[rowIndex]; double rhs2=rowlower[rowIndex]; if (suitableRows_[rowIndex]) { int i; bool goodRow=true; for (i=rowStart[rowIndex]; i<rowStart[rowIndex]+rowLength[rowIndex];i++) { int thisCol=column[i]; if (colupper[thisCol]-collower[thisCol]>epsilon_) { // could allow general integer variables but unlikely if (!si.isBinary(thisCol) ) { goodRow=false; break; } if (fabs(rowElements[i]-1.0)>epsilon_) { goodRow=false; break; } } else { rhs1 -= collower[thisCol]*rowElements[i]; rhs2 -= collower[thisCol]*rowElements[i]; } } if (fabs(rhs1-1.0)>epsilon_&&fabs(rhs2-1.0)>epsilon_) { goodRow=false; } if (goodRow) { suitableRows_[rowIndex]=1; } else { suitableRows_[rowIndex]=0; } } } }
CbcLotsize::printLotsize(double value, bool condition, int type) const #else CbcLotsize::printLotsize(double , bool , int ) const #endif { #if CBC_PRINT if (columnNumber_ >= firstPrint && columnNumber_ <= lastPrint) { int printIt = CBC_PRINT - 1; // Get details OsiSolverInterface * solver = saveModel->solver(); double currentLower = solver->getColLower()[columnNumber_]; double currentUpper = solver->getColUpper()[columnNumber_]; int i; // See if in a valid range (with two tolerances) bool inRange = false; bool inRange2 = false; double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); // increase if type 2 if (type == 2) { integerTolerance *= 100.0; type = 0; printIt = 2; // always print } // bounds should match some bound int rangeL = -1; int rangeU = -1; if (rangeType_ == 1) { for (i = 0; i < numberRanges_; i++) { if (fabs(currentLower - bound_[i]) < 1.0e-12) rangeL = i; if (fabs(currentUpper - bound_[i]) < 1.0e-12) rangeU = i; if (fabs(value - bound_[i]) < integerTolerance) inRange = true; if (fabs(value - bound_[i]) < 1.0e8) inRange2 = true; } } else { for (i = 0; i < numberRanges_; i++) { if (fabs(currentLower - bound_[2*i]) < 1.0e-12) rangeL = i; if (fabs(currentUpper - bound_[2*i+1]) < 1.0e-12) rangeU = i; if (value > bound_[2*i] - integerTolerance && value < bound_[2*i+1] + integerTolerance) inRange = true; if (value > bound_[2*i] - integerTolerance && value < bound_[2*i+1] + integerTolerance) inRange = true; } } assert (rangeL >= 0 && rangeU >= 0); bool abortIt = false; switch (type) { // returning from findRange (fall through to just check) case 0: if (printIt) { printf("findRange returns %s for column %d and value %g", condition ? "true" : "false", columnNumber_, value); if (printIt > 1) printf(" LP bounds %g, %g", currentLower, currentUpper); printf("\n"); } // Should match case 1: if (inRange != condition) { printIt = 2; abortIt = true; } break; // case 2: break; // case 3: break; // case 4: break; } } #endif }
//------------------------------------------------------------- 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); } } }
// 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; }
//------------------------------------------------------------------------------- // 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; }