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; }
// 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; } }
//############################################################################# bool MibSHeuristic::checkLowerFeasibility(OsiSolverInterface * si, double * solution) { MibSModel * model = MibSModel_; OsiSolverInterface * lSolver = model->bS_->setUpModel(si, true, solution); 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()) return true; else return false; }
// Override OsiSolver::solve() because Soplex doesn't have branch & bound int OsiSpxSolver::solve() { OsiSolverInterface* si = OsiSolver::getSolver(); if(!OsiSolver::prepareSolve()) { return UNSAT; } timer.reset(); try { si->initialSolve(); } catch (CoinError err) { err.print(true); return UNSAT; } time = timer.timeElapsed(); if (si->isProvenOptimal()) return SAT; else if (si->isProvenPrimalInfeasible()) return UNSAT; else return UNKNOWN; }
//############################################################################# 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 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; }
BlisReturnStatus BlisStrongBranch(BlisModel *model, double objValue, int colInd, double x, const double *saveLower, const double *saveUpper, bool &downKeep, bool &downFinished, double &downDeg, bool &upKeep, bool &upFinished, double &upDeg) { BlisReturnStatus status = BlisReturnStatusOk; int lpStatus = 0; int j, numIntInfDown, numObjInfDown; double newObjValue; OsiSolverInterface * solver = model->solver(); int numCols = solver->getNumCols(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); // Restore bounds int numDiff = 0; BlisSolution* ksol = NULL; int ind = model->getIntObjIndices()[colInd]; BlisObjectInt *intObj = dynamic_cast<BlisObjectInt *>(model->objects(ind)); #ifdef BLIS_DEBUG_MORE for (j = 0; j < numCols; ++j) { if (saveLower[j] != lower[j]) { //solver->setColLower(j, saveLower[j]); ++numDiff; } if (saveUpper[j] != upper[j]) { //solver->setColUpper(j, saveUpper[j]); ++numDiff; } } std::cout << "BEFORE: numDiff = " << numDiff << std::endl; #endif //------------------------------------------------------ // Branching down. //------------------------------------------------------ solver->setColUpper(colInd, floor(x)); solver->solveFromHotStart(); newObjValue = solver->getObjSense() * solver->getObjValue(); downDeg = newObjValue - objValue; if (solver->isProvenOptimal()) { lpStatus = 0; // optimal #ifdef BLIS_DEBUG_MORE printf("STRONG: COL[%d]: downDeg=%g, x=%g\n", colInd, downDeg, x); #endif // Update pseudocost intObj->pseudocost().update(-1, downDeg, x); model->setSharedObjectMark(ind); // Check if ip feasible ksol = model->feasibleSolution(numIntInfDown, numObjInfDown); if (ksol) { #ifdef BLIS_DEBUG_MORE printf("STRONG:Down:found a feasible solution\n"); #endif model->storeSolution(BlisSolutionTypeStrong, ksol); downKeep = false; } else { downKeep = true; } downFinished = true; } else if (solver->isIterationLimitReached() && !solver->isDualObjectiveLimitReached()) { lpStatus = 2; // unknown downKeep = true; downFinished = false; } else { downDeg = 1.0e20; lpStatus = 1; // infeasible downKeep = false; downFinished = false; } #ifdef BLIS_DEBUG_MORE std::cout << "Down: lpStatus = " << lpStatus << std::endl; #endif // restore bounds numDiff = 0; for (j = 0; j < numCols; ++j) { if (saveLower[j] != lower[j]) { solver->setColLower(j, saveLower[j]); ++numDiff; } if (saveUpper[j] != upper[j]) { solver->setColUpper(j, saveUpper[j]); ++numDiff; } } #ifdef BLIS_DEBUG assert(numDiff > 0); //std::cout << "numDiff = " << numDiff << std::endl; #endif //---------------------------------------------- // Branching up. //---------------------------------------------- solver->setColLower(colInd, ceil(x)); solver->solveFromHotStart(); newObjValue = solver->getObjSense() * solver->getObjValue(); upDeg = newObjValue - objValue; if (solver->isProvenOptimal()) { lpStatus = 0; // optimal #ifdef BLIS_DEBUG_MORE printf("STRONG: COL[%d]: upDeg=%g, x=%g\n", colInd, upDeg, x); #endif // Update pseudocost intObj->pseudocost().update(1, upDeg, x); model->setSharedObjectMark(ind); // Check if IP feasible ksol = model->feasibleSolution(numIntInfDown, numObjInfDown); if (ksol) { #ifdef BLIS_DEBUG_MORE printf("STRONG:Up:found a feasible solution\n"); #endif model->storeSolution(BlisSolutionTypeStrong, ksol); upKeep = false; } else { upKeep = true; } upFinished = true; } else if (solver->isIterationLimitReached() &&!solver->isDualObjectiveLimitReached()) { lpStatus = 2; // unknown upKeep = true; upFinished = false; } else { lpStatus = 1; // infeasible upKeep = false; upFinished = false; upDeg = 1.0e20; } #ifdef BLIS_DEBUG_MORE std::cout << "STRONG: Up: lpStatus = " << lpStatus << std::endl; #endif // restore bounds for (j = 0; j < numCols; ++j) { if (saveLower[j] != lower[j]) { solver->setColLower(j,saveLower[j]); } if (saveUpper[j] != upper[j]) { solver->setColUpper(j,saveUpper[j]); } } return status; }
int main( int argc, char **argv ) { if ( argc < 2 ) { printf("Invalid number of parameters!\n"); exit( EXIT_FAILURE ); } char problemName[ 256 ]; getFileName( problemName, argv[1] ); clock_t start = clock(); OsiClpSolverInterface *realSolver = new OsiClpSolverInterface(); realSolver->getModelPtr()->setPerturbation(50); /* makes CLP faster for hard instances */ OsiSolverInterface *solver = (OsiSolverInterface*) realSolver; parseParameters( argc, argv ); readLP( solver, argv[1] ); FILE *log = NULL; if(!output.empty()) { log = fopen(output.c_str(), "a"); if(!log) { printf("Could not open the file!\n"); exit(EXIT_FAILURE); } } const int numCols = solver->getNumCols(), numRows = solver->getNumRows(); int pass = 0, newCuts = 0, totalCuts = 0; double pTime, opt, cgTime; CGraph *cgraph = NULL; if(sepMethod == Npsep) cgraph = build_cgraph_osi( solver ); if(!optFile.empty()) { getOptimals(); if(optimals.find(problemName) == optimals.end()) { fprintf(stderr, "ERROR: optimal value not found!\n"); exit(EXIT_FAILURE); } opt = optimals[problemName]; } solver->initialSolve(); if (!solver->isProvenOptimal()) { if (solver->isAbandoned()) { fprintf( stderr, "LP solver abandoned due to numerical dificulties.\n" ); exit( EXIT_FAILURE ); } if (solver->isProvenPrimalInfeasible()) { fprintf( stderr, "LP solver says PRIMAL INFEASIBLE.\n" ); exit( EXIT_FAILURE ); } if (solver->isProvenDualInfeasible()) { fprintf( stderr, "LP solver says DUAL INFEASIBLE.\n" ); exit( EXIT_FAILURE ); } if (solver->isPrimalObjectiveLimitReached()) { fprintf( stderr, "LP solver says isPrimalObjectiveLimitReached.\n" ); exit( EXIT_FAILURE ); } if (solver->isDualObjectiveLimitReached()) { fprintf( stderr, "LP solver says isDualObjectiveLimitReached.\n" ); exit( EXIT_FAILURE ); } if (solver->isIterationLimitReached()) { fprintf( stderr, "LP solver says isIterationLimitReached.\n" ); exit( EXIT_FAILURE ); } fprintf( stderr, "ERROR: Could not solve LP relaxation to optimality. Checking status...\n" ); exit( EXIT_FAILURE ); } double initialBound = solver->getObjValue(); printf("%.2lf %d %d %.7lf", ((double)(clock()-start)) / ((double)CLOCKS_PER_SEC), pass, 0, solver->getObjValue()); if(!optFile.empty()) { printf(" %.7lf %.7lf", opt, abs_mip_gap(solver->getObjValue(), opt)); } printf("\n"); do { clock_t startSep = clock(); newCuts = 0; switch (sepMethod) { case Npsep: { CglEClique cliqueGen; OsiCuts cuts; CglTreeInfo info; info.level = 0; info.pass = 1; vector<string> varNames = getVarNames(solver->getColNames(), numCols); cliqueGen.parseParameters( argc, (const char**)argv ); cliqueGen.setCGraph( cgraph ); cliqueGen.setGenOddHoles( true ); //allow (or not) inserting odd hole cuts cliqueGen.colNames = &varNames; cliqueGen.generateCuts( *solver, cuts, info ); newCuts = cuts.sizeCuts(); solver->applyCuts( cuts ); } break; case CglSepM: { CglClique cliqueGen; OsiCuts cuts; CglTreeInfo info; info.level = 0; info.pass = 1; cliqueGen.setMinViolation( MIN_VIOLATION ); cliqueGen.setStarCliqueReport(false); cliqueGen.setRowCliqueReport(false); cliqueGen.generateCuts( *solver, cuts, info ); newCuts = cuts.sizeCuts(); solver->applyCuts( cuts ); } break; Default: { fprintf( stderr, "Separation Method does not recognized!\n" ); exit( EXIT_FAILURE ); } } pTime = ((double)(clock()-start)) / ((double)CLOCKS_PER_SEC); if(pTime > MAX_TIME) break; totalCuts += newCuts; ++pass; if (newCuts) { solver->resolve(); if (!solver->isProvenOptimal()) { if (solver->isAbandoned()) { fprintf( stderr, "LP solver abandoned due to numerical dificulties.\n" ); exit( EXIT_FAILURE ); } if (solver->isProvenPrimalInfeasible()) { fprintf( stderr, "LP solver says PRIMAL INFEASIBLE.\n" ); exit( EXIT_FAILURE ); } if (solver->isProvenDualInfeasible()) { fprintf( stderr, "LP solver says DUAL INFEASIBLE.\n" ); exit( EXIT_FAILURE ); } if (solver->isPrimalObjectiveLimitReached()) { fprintf( stderr, "LP solver says isPrimalObjectiveLimitReached.\n" ); exit( EXIT_FAILURE ); } if (solver->isDualObjectiveLimitReached()) { fprintf( stderr, "LP solver says isDualObjectiveLimitReached.\n" ); exit( EXIT_FAILURE ); } if (solver->isIterationLimitReached()) { fprintf( stderr, "LP solver says isIterationLimitReached.\n" ); exit( EXIT_FAILURE ); } fprintf( stderr, "ERROR: Could not solve LP relaxation. Exiting.\n" ); exit( EXIT_FAILURE ); } pTime = ((double)(clock()-start)) / ((double)CLOCKS_PER_SEC); if(pTime > MAX_TIME) break; double sepTime = ((double)(clock()-startSep)) / ((double)CLOCKS_PER_SEC); printf("%.2lf %d %d %.7lf", sepTime, pass, newCuts, solver->getObjValue()); if(!optFile.empty()) printf(" %.7lf %.7lf", opt, abs_mip_gap(solver->getObjValue(), opt)); printf("\n"); } } while ( (newCuts>0) && (pass<MAX_PASSES) ) ; if(log) { double totalTime = ((double)(clock()-start)) / ((double)CLOCKS_PER_SEC); fprintf(log, "%s %.2lf %d %d %.7lf", problemName, totalTime, pass - 1, totalCuts, solver->getObjValue()); if(!optFile.empty()) fprintf(log, " %.7lf", abs_mip_gap(solver->getObjValue(), opt)); fprintf(log, "\n"); } if(cgraph) cgraph_free( &cgraph ); delete realSolver; return EXIT_SUCCESS; }
// mex function usage: // [x,y,status] = mexosi(n_vars,n_cons,A,x_lb,x_ub,c,Ax_lb,Ax_ub,isMIP,isQP,vartype,Q,options) // 0 1 2 3 4 5 6 7 8 9 10 11 12 void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[]) { // Enable printing in MATLAB int loglevel = 0; DerivedHandler *mexprinter = new DerivedHandler(); // assumed open mexprinter->setLogLevel(loglevel); // check that we have the right number of inputs if(nrhs < 10) mexErrMsgTxt("At least 10 inputs required in call to mexosi. Bug in osi.m?..."); // check that we have the right number of outputs if(nlhs < 3) mexErrMsgTxt("At least 3 ouptuts required in call to mexosi. Bug in osi.m?..."); // Get pointers to input values const int n_vars = (int)*mxGetPr(prhs[0]); const int n_cons = (int)*mxGetPr(prhs[1]); const mxArray *A = prhs[2]; const double *x_lb = mxGetPr(prhs[3]); const double *x_ub = mxGetPr(prhs[4]); const double *c = mxGetPr(prhs[5]); const double *Ax_lb = mxGetPr(prhs[6]); const double *Ax_ub = mxGetPr(prhs[7]); const bool isMIP = (bool)*(mxLogical*)mxGetData(prhs[8]); const bool isQP = (bool)*(mxLogical*)mxGetData(prhs[9]); mxLogical *isinteger = (mxLogical*)mxGetData(prhs[10]); const mxArray* Q = prhs[11]; // process the options int returnStatus = 0; // extract row/col/value data from A const mwIndex * A_col_starts = mxGetJc(A); const mwIndex * A_row_index = mxGetIr(A); const double * A_data = mxGetPr(A); // figure out the number of non-zeros in A int nnz = (int)(A_col_starts[n_vars] - A_col_starts[0]); // number of non-zeros //mexPrintf("nnz = %d, n_vars = %d, n_cons = %d\n",nnz,n_vars,n_cons); // we need to convert these into other types of indices for Coin to use them std::vector<CoinBigIndex> A_col_starts_coin(A_col_starts,A_col_starts+n_vars+1); std::vector<int> A_row_index_coin(A_row_index,A_row_index+nnz); // declare the solver OsiSolverInterface* pSolver; // initialize the solver if ( isMIP ) { pSolver = new OsiCbcSolverInterface; } else { pSolver = new OsiClpSolverInterface; } // OsiCbcSolverInterface is deprecated and CbcModel should be used instead but don't // know how to get that working with loadProblem. // OsiCbcSolverInterface solver1; // CbcModel model(solver1); // CbcMain0(model); // OsiSolverInterface * pSolver = model.solver(); if (nrhs>12) { // get stuff out of the options structure if provided // Finish me } // mexPrintf("Setting Log Level to 0.\n"); // load the problem mexPrintf("Loading the problem.\n"); pSolver->loadProblem( n_vars, n_cons, // problem size &A_col_starts_coin[0], &A_row_index_coin[0], A_data, // the A matrix x_lb, x_ub, c, // the objective and bounds Ax_lb, Ax_ub ); // the constraint bounds // pSolver->messageHandler()->setLogLevel(0); // This doesn't seem to work pSolver->setHintParam(OsiDoReducePrint,true,OsiHintTry); // deal with integer inputs if ( isMIP ) { for(int i=0;i<n_vars;i++) { if (isinteger[i]) pSolver->setInteger(i); } } if (isQP) { error("QP is not working yet"); // need to call loadQuadraticObjective here ??? } // CbcModel model(pSolver); // model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // solve the problem //mexPrintf("Trying to solve the problem.\n"); if (isMIP) { pSolver->branchAndBound(); // model.branchAndBound(); } else { // model.initialSolve(); pSolver->initialSolve(); } // Allocate memory for return data plhs[0] = mxCreateDoubleMatrix(n_vars,1, mxREAL); // for the solution plhs[1] = mxCreateDoubleMatrix(n_cons,1, mxREAL); // for the constraint prices plhs[2] = mxCreateDoubleMatrix(1,1, mxREAL); // for the return status double *x = mxGetPr(plhs[0]); double *y = mxGetPr(plhs[1]); double *returncode = mxGetPr(plhs[2]); // Copy solutions if available if ( pSolver->isProvenOptimal() ) { // if ( model.isProvenOptimal() ) { // if ( model.solver()->isProvenOptimal() ) { //mexPrintf("Solution found.\n"); // extract the solutions const double * solution = pSolver->getColSolution(); const double * dualvars = pSolver->getRowPrice(); // copy the solution to the outpus memcpy(x,solution,n_vars*sizeof(double)); memcpy(y,dualvars,n_cons*sizeof(double)); *returncode = 1; } else { if ( pSolver->isProvenPrimalInfeasible() ) { mexPrintf("Primal problem is proven infeasible.\n"); *returncode = 0; } else if ( pSolver->isProvenDualInfeasible() ) { mexPrintf("Dual problem is proven infeasible.\n"); *returncode = -1; } else if ( pSolver->isPrimalObjectiveLimitReached() ) { mexPrintf("The primal objective limit was reached.\n"); *returncode = -2; } else if ( pSolver->isDualObjectiveLimitReached() ) { mexPrintf("The dual objective limit was reached.\n"); *returncode = -3; } else if ( pSolver->isIterationLimitReached() ) { mexPrintf("The iteration limit was reached\n"); *returncode = -4; } } // clean up memory if ( mexprinter!= NULL) delete mexprinter; delete pSolver; }
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 OSIXXX; // Build our own instance from scratch /* * This section adapted from Matt Galati's example * on the COIN-OR Tutorial website. * * Problem from Bertsimas, Tsitsiklis page 21 * * optimal solution: x* = (1,1) * * minimize -1 x0 - 1 x1 * s.t 1 x0 + 2 x1 <= 3 * 2 x0 + 1 x1 <= 3 * x0 >= 0 * x1 >= 0 */ int n_cols = 2; double *objective = new double[n_cols];//the objective coefficients double *col_lb = new double[n_cols];//the column lower bounds double *col_ub = new double[n_cols];//the column upper bounds //Define the objective coefficients. //minimize -1 x0 - 1 x1 objective[0] = -1.0; objective[1] = -1.0; //Define the variable lower/upper bounds. // x0 >= 0 => 0 <= x0 <= infinity // x1 >= 0 => 0 <= x1 <= infinity col_lb[0] = 0.0; col_lb[1] = 0.0; col_ub[0] = si->getInfinity(); col_ub[1] = si->getInfinity(); int n_rows = 2; double *row_lb = new double[n_rows]; //the row lower bounds double *row_ub = new double[n_rows]; //the row upper bounds //Define the constraint matrix. CoinPackedMatrix *matrix = new CoinPackedMatrix(false,0,0); matrix->setDimensions(0, n_cols); //1 x0 + 2 x1 <= 3 => -infinity <= 1 x0 + 2 x2 <= 3 CoinPackedVector row1; row1.insert(0, 1.0); row1.insert(1, 2.0); row_lb[0] = -1.0 * si->getInfinity(); row_ub[0] = 3.0; matrix->appendRow(row1); //2 x0 + 1 x1 <= 3 => -infinity <= 2 x0 + 1 x1 <= 3 CoinPackedVector row2; row2.insert(0, 2.0); row2.insert(1, 1.0); row_lb[1] = -1.0 * si->getInfinity(); row_ub[1] = 3.0; matrix->appendRow(row2); //load the problem to OSI si->loadProblem(*matrix, col_lb, col_ub, objective, row_lb, row_ub); //write the MPS file to a file called example.mps si->writeMps("example"); // 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; }
//############################################################################# void MibSBilevel::checkBilevelFeasiblity(bool isRoot) { int cutStrategy = model_->MibSPar_->entry(MibSParams::cutStrategy); bool warmStartLL = model_->MibSPar_->entry(MibSParams::warmStartLL); int maxThreadsLL = model_->MibSPar_->entry(MibSParams::maxThreadsLL); int whichCutsLL = model_->MibSPar_->entry(MibSParams::whichCutsLL); int probType = model_->MibSPar_->entry(MibSParams::bilevelProblemType); std::string feasCheckSolver = model_->MibSPar_->entry(MibSParams::feasCheckSolver); if (warmStartLL && (feasCheckSolver == "SYMPHONY") && solver_){ solver_ = setUpModel(model_->getSolver(), false); }else{ if (solver_){ delete solver_; } solver_ = setUpModel(model_->getSolver(), true); } OsiSolverInterface *lSolver = solver_; //CoinWarmStart * ws = getWarmStart(); //if (ws != NULL){ // lSolver->setWarmStart(ws); //} //delete ws; if(1) lSolver->writeLp("lowerlevel"); if (feasCheckSolver == "Cbc"){ dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); }else if (feasCheckSolver == "SYMPHONY"){ //dynamic_cast<OsiSymSolverInterface *> // (lSolver)->setSymParam("prep_level", -1); sym_environment *env = dynamic_cast<OsiSymSolverInterface *> (lSolver)->getSymphonyEnvironment(); if (warmStartLL){ sym_set_int_param(env, "keep_warm_start", TRUE); if (probType == 1){ //Interdiction sym_set_int_param(env, "should_use_rel_br", FALSE); sym_set_int_param(env, "use_hot_starts", FALSE); sym_set_int_param(env, "should_warmstart_node", TRUE); sym_set_int_param(env, "sensitivity_analysis", TRUE); sym_set_int_param(env, "sensitivity_bounds", TRUE); sym_set_int_param(env, "set_obj_upper_lim", FALSE); } } //Always uncomment for debugging!! sym_set_int_param(env, "do_primal_heuristic", FALSE); sym_set_int_param(env, "verbosity", -2); sym_set_int_param(env, "prep_level", -1); sym_set_int_param(env, "max_active_nodes", maxThreadsLL); sym_set_int_param(env, "tighten_root_bounds", FALSE); sym_set_int_param(env, "max_sp_size", 100); sym_set_int_param(env, "do_reduced_cost_fixing", FALSE); if (whichCutsLL == 0){ sym_set_int_param(env, "generate_cgl_cuts", FALSE); }else{ sym_set_int_param(env, "generate_cgl_gomory_cuts", GENERATE_DEFAULT); } if (whichCutsLL == 1){ sym_set_int_param(env, "generate_cgl_knapsack_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_probing_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_clique_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_twomir_cuts", DO_NOT_GENERATE); sym_set_int_param(env, "generate_cgl_flowcover_cuts", DO_NOT_GENERATE); } }else if (feasCheckSolver == "CPLEX"){ #ifdef USE_CPLEX lSolver->setHintParam(OsiDoReducePrint); lSolver->messageHandler()->setLogLevel(0); CPXENVptr cpxEnv = dynamic_cast<OsiCpxSolverInterface*>(lSolver)->getEnvironmentPtr(); assert(cpxEnv); CPXsetintparam(cpxEnv, CPX_PARAM_SCRIND, CPX_OFF); CPXsetintparam(cpxEnv, CPX_PARAM_THREADS, maxThreadsLL); #endif } if (warmStartLL && feasCheckSolver == "SYMPHONY"){ lSolver->resolve(); setWarmStart(lSolver->getWarmStart()); }else{ lSolver->branchAndBound(); } const double * sol = model_->solver()->getColSolution(); double objVal(lSolver->getObjValue() * model_->getLowerObjSense()); MibSTreeNode * node = static_cast<MibSTreeNode *>(model_->activeNode_); MibSTreeNode * parent = static_cast<MibSTreeNode *>(model_->activeNode_->getParent()); if((!node->isBoundSet()) && (node->getIndex() != 0)){ double parentBound = parent->getLowerUB(); node->setLowerUB(parentBound); node->setIsBoundSet(true); } if(objVal > node->getLowerUB()){ node->setLowerUB(objVal); node->setIsBoundSet(true); } double etol(model_->etol_); double lowerObj = getLowerObj(sol, model_->getLowerObjSense()); int lN(model_->lowerDim_); // lower-level dimension int uN(model_->upperDim_); // lower-level dimension if(!optLowerSolution_) optLowerSolution_ = new double[lN]; if(!optLowerSolutionOrd_) optLowerSolutionOrd_ = new double[lN]; CoinZeroN(optLowerSolution_, lN); CoinZeroN(optLowerSolutionOrd_, lN); int * lowerColInd = model_->getLowerColInd(); int * upperColInd = model_->getUpperColInd(); int index(0); if(0){ std::cout << "objVal: " << objVal << std::endl; std::cout << "lowerObj: " << lowerObj << std::endl; } if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ const double * values = lSolver->getColSolution(); int lN(model_->getLowerDim()); int i(0); // May want to take out this update and keep current - both optimal // changed this 7/1 to allow for continuous vars /* for(i = 0; i < lN; i++){ lowerSolution_[i] = (double) floor(values[i] + 0.5); } */ for(i = 0; i < lN; i++){ if(lSolver->isInteger(i)) lowerSolution_[i] = (double) floor(values[i] + 0.5); else lowerSolution_[i] = (double) values[i]; } isBilevelFeasible_ = true; useBilevelBranching_ = false; }else if (lSolver->isProvenOptimal()){ /** Current solution is not bilevel feasible, but we may still have a solution **/ //std::cout << "Solution is not bilevel feasible." << std::endl; const double * values = lSolver->getColSolution(); int lN(model_->getLowerDim()); int i(0); //added this 7/1 to store y* for val func cut for(i = 0; i < lN; i++){ if(lSolver->isInteger(i)) optLowerSolution_[i] = (double) floor(values[i] + 0.5); else optLowerSolution_[i] = (double) values[i]; } int numCols = model_->solver()->getNumCols(); int pos(0); #if 1 for(i = 0; i < numCols; i++){ if ((pos = model_->bS_->binarySearch(0, lN - 1, i, lowerColInd)) >= 0){ optLowerSolutionOrd_[pos] = optLowerSolution_[pos]; } } #else double upperObj(0); double * newSolution = new double[numCols]; const double * upperObjCoeffs = model_->solver()->getObjCoefficients(); for(i = 0; i < numCols; i++){ pos = model_->bS_->binarySearch(0, lN - 1, i, lowerColInd); if(pos < 0){ pos = model_->bS_->binarySearch(0, uN - 1, i, upperColInd); newSolution[i] = sol[i]; } else{ newSolution[i] = optLowerSolution_[pos]; optLowerSolutionOrd_[pos] = optLowerSolution_[pos]; } upperObj += newSolution[i] * upperObjCoeffs[i]; } if(model_->checkUpperFeasibility(newSolution)){ MibSSolution *mibsSol = new MibSSolution(numCols, newSolution, upperObj, model_); model_->storeSolution(BlisSolutionTypeHeuristic, mibsSol); } delete [] newSolution; #endif /* run a heuristic to find a better feasible solution */ heuristic_->findHeuristicSolutions(); isBilevelFeasible_ = false; if(cutStrategy != 1) useBilevelBranching_ = true; } //delete lSolver; }
//Solver function int sci_rmps(char *fname) { //creating a problem pointer using base class of OsiSolverInterface and //instantiate the object using derived class of ClpSolverInterface OsiSolverInterface* si = new OsiClpSolverInterface(); // Error management variable SciErr sciErr; //data declarations int *piAddressVarOne = NULL; //pointer used to access argument of the function char* ptr; //pointer to point to address of file name double* options_; //options to set maximum iterations CheckInputArgument(pvApiCtx, 2,2 ); //Check we have exactly two arguments as input or not CheckOutputArgument(pvApiCtx, 6, 6); //Check we have exactly six arguments on output side or not //Getting the input arguments from Scilab //Getting the MPS file path //Reading mps file getStringFromScilab(1,&ptr); std::cout<<ptr; //get options from Scilab if(getFixedSizeDoubleMatrixInList(2 , 2 , 1 , 1 , &options_)) { return 1; } //Read the MPS file si->readMps(ptr); //setting options for maximum iterations si->setIntParam(OsiMaxNumIteration,options_[0]); //Solve the problem si->initialSolve(); //Quering about the problem //get number of variables double numVars_; numVars_ = si->getNumCols(); //get number of constraint equations double numCons_; numCons_ = si->getNumRows(); //Output the solution to Scilab //get solution for x const double* xValue = si->getColSolution(); //get objective value double objValue = si->getObjValue(); //get Status value double status; if(si->isProvenOptimal()) status=0; else if(si->isProvenPrimalInfeasible()) status=1; else if(si->isProvenDualInfeasible()) status=2; else if(si->isIterationLimitReached()) status=3; else if(si->isAbandoned()) status=4; else if(si->isPrimalObjectiveLimitReached()) status=5; else if(si->isDualObjectiveLimitReached()) status=6; //get number of iterations double iterations = si->getIterationCount(); //get reduced cost const double* reducedCost = si->getReducedCost(); //get dual vector const double* dual = si->getRowPrice(); returnDoubleMatrixToScilab(1 , 1 , numVars_ , xValue); returnDoubleMatrixToScilab(2 , 1 , 1 , &objValue); returnDoubleMatrixToScilab(3 , 1 , 1 , &status); returnDoubleMatrixToScilab(4 , 1 , 1 , &iterations); returnDoubleMatrixToScilab(5 , 1 , numVars_ , reducedCost); returnDoubleMatrixToScilab(6 , 1 , numCons_ , dual); free(xValue); free(dual); free(reducedCost); }
//############################################################################# 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; }
/// OaDecomposition method double OaFeasibilityChecker::performOa(OsiCuts & cs, solverManip &lpManip, BabInfo * babInfo, double &cutoff,const CglTreeInfo & info) const { bool isInteger = true; bool feasible = 1; OsiSolverInterface * lp = lpManip.si(); OsiBranchingInformation branch_info(lp,false); //int numcols = lp->getNumCols(); double milpBound = -COIN_DBL_MAX; int numberPasses = 0; double * nlpSol = NULL; int numberCutsBefore = cs.sizeRowCuts(); while (isInteger && feasible ) { numberPasses++; //setup the nlp //Fix the variable which have to be fixed, after having saved the bounds double * colsol = const_cast<double *>(lp->getColSolution()); branch_info.solution_ = colsol; fixIntegers(*nlp_,branch_info, parameters_.cbcIntegerTolerance_,objects_, nObjects_); //Now solve the NLP get the cuts, and intall them in the local LP nlp_->resolve(txt_id); if (post_nlp_solve(babInfo, cutoff)) { //nlp solved and feasible // Update the cutoff double ub = nlp_->getObjValue(); cutoff = ub > 0 ? ub *(1 - parameters_.cbcCutoffIncrement_) : ub*(1 + parameters_.cbcCutoffIncrement_); // Update the lp solver cutoff lp->setDblParam(OsiDualObjectiveLimit, cutoff); } // Get the cuts outer approximation at the current point nlpSol = const_cast<double *>(nlp_->getColSolution()); const double * toCut = (parameter().addOnlyViolated_)? colsol:NULL; if(cut_count_ <= maximum_oa_cuts_ && type_ == OA) nlp_->getOuterApproximation(cs, nlpSol, 1, toCut, true); else {//if (type_ == Benders) nlp_->getBendersCut(cs, parameter().global_); } if(pol_ == DetectCycles) nlp_->getBendersCut(savedCuts_, parameter().global_); int numberCuts = cs.sizeRowCuts() - numberCutsBefore; cut_count_ += numberCuts; if (numberCuts > 0) installCuts(*lp, cs, numberCuts); lp->resolve(); double objvalue = lp->getObjValue(); //milpBound = max(milpBound, lp->getObjValue()); feasible = (lp->isProvenOptimal() && !lp->isDualObjectiveLimitReached() && (objvalue<cutoff)) ; //if value of integers are unchanged then we have to get out bool changed = true;//if lp is infeasible we don't have to check anything isInteger = 0; // if(!fixed)//fathom on bounds // milpBound = 1e200; if (feasible) { changed = isDifferentOnIntegers(*nlp_, objects_, nObjects_, 0.1, nlp_->getColSolution(), lp->getColSolution()); } if (changed) { branch_info.solution_ = lp->getColSolution(); isInteger = integerFeasible(*lp,branch_info, parameters_.cbcIntegerTolerance_, objects_, nObjects_); } else { isInteger = 0; // if(!fixed)//fathom on bounds milpBound = 1e200; } #ifdef OA_DEBUG printf("Obj value after cuts %g, %d rows\n",lp->getObjValue(), numberCuts) ; #endif } int num_cuts_now = cs.sizeRowCuts(); if(pol_ == KeepAll){ for(int i = numberCutsBefore ; i < num_cuts_now ; i++){ cs.rowCut(i).setEffectiveness(99.9e99); } } #ifdef OA_DEBUG debug_.printEndOfProcedureDebugMessage(cs, true, cutoff, milpBound, isInteger, feasible, std::cout); std::cout<<"milpBound found: "<<milpBound<<std::endl; #endif return milpBound; }
//############################################################################# 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; }
//----------------------------------------------------------------------------- // Generate Lift-and-Project cuts //------------------------------------------------------------------- void CglLiftAndProject::generateCuts(const OsiSolverInterface& si, OsiCuts& cs, const CglTreeInfo /*info*/) { // Assumes the mixed 0-1 problem // // min {cx: <Atilde,x> >= btilde} // // is in canonical form with all bounds, // including x_t>=0, -x_t>=-1 for x_t binary, // explicitly stated in the constraint matrix. // See ~/COIN/Examples/Cgl2/cgl2.cpp // for a general purpose "convert" function. // Reference [BCC]: Balas, Ceria, and Corneujols, // "A lift-and-project cutting plane algorithm // for mixed 0-1 program", Math Prog 58, (1993) // 295-324. // This implementation uses Normalization 1. // Given canonical problem and // the lp-relaxation solution, x, // the LAP cut generator attempts to construct // a cut for every x_j such that 0<x_j<1 // [BCC:307] // x_j is the strictly fractional binary variable // the cut is generated from int j = 0; // Get basic problem information // let Atilde be an m by n matrix const int m = si.getNumRows(); const int n = si.getNumCols(); const double * x = si.getColSolution(); // Remember - Atildes may have gaps.. const CoinPackedMatrix * Atilde = si.getMatrixByRow(); const double * AtildeElements = Atilde->getElements(); const int * AtildeIndices = Atilde->getIndices(); const CoinBigIndex * AtildeStarts = Atilde->getVectorStarts(); const int * AtildeLengths = Atilde->getVectorLengths(); const int AtildeFullSize = AtildeStarts[m]; const double * btilde = si.getRowLower(); // Set up memory for system (10) [BCC:307] // (the problem over the norm intersected // with the polar cone) // // min <<x^T,Atilde^T>,u> + x_ju_0 // s.t. // <B,w> = (0,...,0,beta_,beta)^T // w is nonneg for all but the // last two entries, which are free. // where // w = (u,v,v_0,u_0)in BCC notation // u and v are m-vectors; u,v >=0 // v_0 and u_0 are free-scalars, and // // B = Atilde^T -Atilde^T -e_j e_j // btilde^T e_0^T 0 0 // e_0^T btilde^T 1 0 // ^T indicates Transpose // e_0 is a (AtildeNCols x 1) vector of all zeros // e_j is e_0 with a 1 in the jth position // Storing B in column order. B is a (n+2 x 2m+2) matrix // But need to allow for possible gaps in Atilde. // At each iteration, only need to change 2 cols and objfunc // Sane design of OsiSolverInterface does not permit mucking // with matrix. // Because we must delete and add cols to alter matrix, // and we can only add columns on the end of the matrix // put the v_0 and u_0 columns on the end. // rather than as described in [BCC] // Initially allocating B with space for v_0 and u_O cols // but not populating, for efficiency. // B without u_0 and v_0 is a (n+2 x 2m) size matrix. int twoM = 2*m; int BNumRows = n+2; int BNumCols = twoM+2; int BFullSize = 2*AtildeFullSize+twoM+3; double * BElements = new double[BFullSize]; int * BIndices = new int[BFullSize]; CoinBigIndex * BStarts = new CoinBigIndex [BNumCols+1]; int * BLengths = new int[BNumCols]; int i, ij, k=0; int nPlus1=n+1; int offset = AtildeStarts[m]+m; for (i=0; i<m; i++){ for (ij=AtildeStarts[i];ij<AtildeStarts[i]+AtildeLengths[i];ij++){ BElements[k]=AtildeElements[ij]; BElements[k+offset]=-AtildeElements[ij]; BIndices[k]= AtildeIndices[ij]; BIndices[k+offset]= AtildeIndices[ij]; k++; } BElements[k]=btilde[i]; BElements[k+offset]=btilde[i]; BIndices[k]=n; BIndices[k+offset]=nPlus1; BStarts[i]= AtildeStarts[i]+i; BStarts[i+m]=offset+BStarts[i];// = AtildeStarts[m]+m+AtildeStarts[i]+i BLengths[i]= AtildeLengths[i]+1; BLengths[i+m]= AtildeLengths[i]+1; k++; } BStarts[twoM]=BStarts[twoM-1]+BLengths[twoM-1]; // Cols that will be deleted each iteration int BNumColsLessOne=BNumCols-1; int BNumColsLessTwo=BNumCols-2; const int delCols[2] = {BNumColsLessOne, BNumColsLessTwo}; // Set lower bound on u and v // u_0, v_0 will be reset as free const double solverINFINITY = si.getInfinity(); double * BColLowers = new double[BNumCols]; double * BColUppers = new double[BNumCols]; CoinFillN(BColLowers,BNumCols,0.0); CoinFillN(BColUppers,BNumCols,solverINFINITY); // Set row lowers and uppers. // The rhs is zero, for but the last two rows. // For these the rhs is beta_ double * BRowLowers = new double[BNumRows]; double * BRowUppers = new double[BNumRows]; CoinFillN(BRowLowers,BNumRows,0.0); CoinFillN(BRowUppers,BNumRows,0.0); BRowLowers[BNumRows-2]=beta_; BRowUppers[BNumRows-2]=beta_; BRowLowers[BNumRows-1]=beta_; BRowUppers[BNumRows-1]=beta_; // Calculate base objective <<x^T,Atilde^T>,u> // Note: at each iteration coefficient u_0 // changes to <x^T,e_j> // w=(u,v,beta,v_0,u_0) size 2m+3 // So, BOjective[2m+2]=x[j] double * BObjective= new double[BNumCols]; double * Atildex = new double[m]; CoinFillN(BObjective,BNumCols,0.0); Atilde->times(x,Atildex); // Atildex is size m, x is size n CoinDisjointCopyN(Atildex,m,BObjective); // Number of cols and size of Elements vector // in B without the v_0 and u_0 cols int BFullSizeLessThree = BFullSize-3; // Load B matrix into a column orders CoinPackedMatrix CoinPackedMatrix * BMatrix = new CoinPackedMatrix(true, BNumRows, BNumColsLessTwo, BFullSizeLessThree, BElements,BIndices, BStarts,BLengths); // Assign problem into a solver interface // Note: coneSi will cleanup the memory itself OsiSolverInterface * coneSi = si.clone(false); coneSi->assignProblem (BMatrix, BColLowers, BColUppers, BObjective, BRowLowers, BRowUppers); // Problem sense should default to "min" by default, // but just to be virtuous... coneSi->setObjSense(1.0); // The plot outline from here on down: // coneSi has been assigned B without the u_0 and v_0 columns // Calculate base objective <<x^T,Atilde^T>,u> // bool haveWarmStart = false; // For (j=0; j<n, j++) // if (!isBinary(x_j) || x_j<=0 || x_j>=1) continue; // // IMPROVEME: if(haveWarmStart) check if j attractive // add {-e_j,0,-1} matrix column for v_0 // add {e_j,0,0} matrix column for u_0 // objective coefficient for u_0 is x_j // if (haveWarmStart) // set warmstart info // solve min{objw:Bw=0; w>=0,except v_0, u_0 free} // if (bounded) // get warmstart info // haveWarmStart=true; // ustar = optimal u solution // ustar_0 = optimal u_0 solution // alpha^T= <ustar^T,Atilde> -ustar_0e_j^T // (double check <alpha^T,x> >= beta_ should be violated) // add <alpha^T,x> >= beta_ to cutset // endif // delete column for u_0 // this deletes all column info. // delete column for v_0 // endFor // clean up memory // return 0; int * nVectorIndices = new int[n]; CoinIotaN(nVectorIndices, n, 0); bool haveWarmStart = false; bool equalObj1, equalObj2; CoinRelFltEq eq; double v_0Elements[2] = {-1,1}; double u_0Elements[1] = {1}; CoinWarmStart * warmStart = 0; double * ustar = new double[m]; CoinFillN(ustar, m, 0.0); double* alpha = new double[n]; CoinFillN(alpha, n, 0.0); for (j=0;j<n;j++){ if (!si.isBinary(j)) continue; // Better to ask coneSi? No! // coneSi has no binInfo. equalObj1=eq(x[j],0); equalObj2=eq(x[j],1); if (equalObj1 || equalObj2) continue; // IMPROVEME: if (haveWarmStart) check if j attractive; // AskLL:wanted to declare u_0 and v_0 packedVec outside loop // and setIndices, but didn't see a method to do that(?) // (Could "insert". Seems inefficient) int v_0Indices[2]={j,nPlus1}; int u_0Indices[1]={j}; // CoinPackedVector v_0(2,v_0Indices,v_0Elements,false); CoinPackedVector u_0(1,u_0Indices,u_0Elements,false); #if CGL_DEBUG const CoinPackedMatrix *see1 = coneSi->getMatrixByRow(); #endif coneSi->addCol(v_0,-solverINFINITY,solverINFINITY,0); coneSi->addCol(u_0,-solverINFINITY,solverINFINITY,x[j]); if(haveWarmStart) { coneSi->setWarmStart(warmStart); coneSi->resolve(); } else { #if CGL_DEBUG const CoinPackedMatrix *see2 = coneSi->getMatrixByRow(); #endif coneSi->initialSolve(); } if(coneSi->isProvenOptimal()){ warmStart = coneSi->getWarmStart(); haveWarmStart=true; const double * wstar = coneSi->getColSolution(); CoinDisjointCopyN(wstar, m, ustar); Atilde->transposeTimes(ustar,alpha); alpha[j]+=wstar[BNumCols-1]; #if debug int p; double sum; for(p=0;p<n;p++)sum+=alpha[p]*x[p]; if (sum<=beta_){ throw CoinError("Cut not violated", "cutGeneration", "CglLiftAndProject"); } #endif // add <alpha^T,x> >= beta_ to cutset OsiRowCut rc; rc.setRow(n,nVectorIndices,alpha); rc.setLb(beta_); rc.setUb(solverINFINITY); cs.insert(rc); } // delete col for u_o and v_0 coneSi->deleteCols(2,delCols); // clean up memory } // clean up delete [] alpha; delete [] ustar; delete [] nVectorIndices; // BMatrix, BColLowers,BColUppers, BObjective, BRowLowers, BRowUppers // are all freed by OsiSolverInterface destructor (?) delete [] BLengths; delete [] BStarts; delete [] BIndices; delete [] BElements; }
//############################################################################# 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; } }
/** 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; }
// 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 CbcHeuristicNaive::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; // See if to do bool atRoot = model_->getNodeCount() == 0; int passNumber = model_->getCurrentPassNumber(); if (!when() || (when() == 1 && model_->phase() != 1) || !atRoot || passNumber != 1) return 0; // switched off // Don't do if it was this heuristic which found solution! if (this == model_->lastHeuristic()) return 0; numRuns_++; double cutoff; model_->solver()->getDblParam(OsiDualObjectiveLimit, cutoff); double direction = model_->solver()->getObjSense(); cutoff *= direction; cutoff = CoinMin(cutoff, solutionValue); OsiSolverInterface * solver = model_->continuousSolver(); if (!solver) solver = model_->solver(); const double * colLower = solver->getColLower(); const double * colUpper = solver->getColUpper(); const double * objective = solver->getObjCoefficients(); int numberColumns = model_->getNumCols(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; bool solutionFound = false; CoinWarmStartBasis saveBasis; CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *>(solver->getWarmStart()) ; if (basis) { saveBasis = * basis; delete basis; } // First just fix all integers as close to zero as possible OsiSolverInterface * newSolver = cloneBut(7); // wassolver->clone(); for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double lower = colLower[iColumn]; double upper = colUpper[iColumn]; double value; if (lower > 0.0) value = lower; else if (upper < 0.0) value = upper; else value = 0.0; newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); } newSolver->initialSolve(); if (newSolver->isProvenOptimal()) { double solValue = newSolver->getObjValue() * direction ; if (solValue < cutoff) { // we have a solution solutionFound = true; solutionValue = solValue; memcpy(betterSolution, newSolver->getColSolution(), numberColumns*sizeof(double)); COIN_DETAIL_PRINT(printf("Naive fixing close to zero gave solution of %g\n", solutionValue)); cutoff = solValue - model_->getCutoffIncrement(); } } // Now fix all integers as close to zero if zero or large cost int nFix = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; double lower = colLower[iColumn]; double upper = colUpper[iColumn]; double value; if (fabs(objective[i]) > 0.0 && fabs(objective[i]) < large_) { nFix++; if (lower > 0.0) value = lower; else if (upper < 0.0) value = upper; else value = 0.0; newSolver->setColLower(iColumn, value); newSolver->setColUpper(iColumn, value); } else { // set back to original newSolver->setColLower(iColumn, lower); newSolver->setColUpper(iColumn, upper); } } const double * solution = solver->getColSolution(); if (nFix) { newSolver->setWarmStart(&saveBasis); newSolver->setColSolution(solution); newSolver->initialSolve(); if (newSolver->isProvenOptimal()) { double solValue = newSolver->getObjValue() * direction ; if (solValue < cutoff) { // try branch and bound double * newSolution = new double [numberColumns]; COIN_DETAIL_PRINT(printf("%d fixed after fixing costs\n", nFix)); int returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, solutionValue, solutionValue, "CbcHeuristicNaive1"); if (returnCode < 0) returnCode = 0; // returned on size if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } if (returnCode == 1) { // solution solutionFound = true; memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); COIN_DETAIL_PRINT(printf("Naive fixing zeros gave solution of %g\n", solutionValue)); cutoff = solutionValue - model_->getCutoffIncrement(); } delete [] newSolution; } } } #if 1 newSolver->setObjSense(-direction); // maximize newSolver->setWarmStart(&saveBasis); newSolver->setColSolution(solution); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double value = solution[iColumn]; double lower = colLower[iColumn]; double upper = colUpper[iColumn]; double newLower; double newUpper; if (newSolver->isInteger(iColumn)) { newLower = CoinMax(lower, floor(value) - 2.0); newUpper = CoinMin(upper, ceil(value) + 2.0); } else { newLower = CoinMax(lower, value - 1.0e5); newUpper = CoinMin(upper, value + 1.0e-5); } newSolver->setColLower(iColumn, newLower); newSolver->setColUpper(iColumn, newUpper); } newSolver->initialSolve(); if (newSolver->isProvenOptimal()) { double solValue = newSolver->getObjValue() * direction ; if (solValue < cutoff) { nFix = 0; newSolver->setObjSense(direction); // correct direction //const double * thisSolution = newSolver->getColSolution(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { double value = solution[iColumn]; double lower = colLower[iColumn]; double upper = colUpper[iColumn]; double newLower = lower; double newUpper = upper; if (newSolver->isInteger(iColumn)) { if (value < lower + 1.0e-6) { nFix++; newUpper = lower; } else if (value > upper - 1.0e-6) { nFix++; newLower = upper; } else { newLower = CoinMax(lower, floor(value) - 2.0); newUpper = CoinMin(upper, ceil(value) + 2.0); } } newSolver->setColLower(iColumn, newLower); newSolver->setColUpper(iColumn, newUpper); } // try branch and bound double * newSolution = new double [numberColumns]; COIN_DETAIL_PRINT(printf("%d fixed after maximizing\n", nFix)); int returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, solutionValue, solutionValue, "CbcHeuristicNaive1"); if (returnCode < 0) returnCode = 0; // returned on size if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } if (returnCode == 1) { // solution solutionFound = true; memcpy(betterSolution, newSolution, numberColumns*sizeof(double)); COIN_DETAIL_PRINT(printf("Naive maximizing gave solution of %g\n", solutionValue)); cutoff = solutionValue - model_->getCutoffIncrement(); } delete [] newSolution; } } #endif delete newSolver; return solutionFound ? 1 : 0; }