// Apply bounds void OsiSolverBranch::applyBounds(OsiSolverInterface &solver, int way) const { int base = way + 1; assert(way == -1 || way == 1); int numberColumns = solver.getNumCols(); const double *columnLower = solver.getColLower(); int i; for (i = start_[base]; i < start_[base + 1]; i++) { int iColumn = indices_[i]; if (iColumn < numberColumns) { double value = CoinMax(bound_[i], columnLower[iColumn]); solver.setColLower(iColumn, value); } else { int iRow = iColumn - numberColumns; const double *rowLower = solver.getRowLower(); double value = CoinMax(bound_[i], rowLower[iRow]); solver.setRowLower(iRow, value); } } const double *columnUpper = solver.getColUpper(); for (i = start_[base + 1]; i < start_[base + 2]; i++) { int iColumn = indices_[i]; if (iColumn < numberColumns) { double value = CoinMin(bound_[i], columnUpper[iColumn]); solver.setColUpper(iColumn, value); } else { int iRow = iColumn - numberColumns; const double *rowUpper = solver.getRowUpper(); double value = CoinMin(bound_[i], rowUpper[iRow]); solver.setRowUpper(iRow, value); } } }
/* Generate cuts for the model data contained in si. The generated cuts are inserted into and returned in the collection of cuts cs. */ bool AbcCutGenerator::generateCuts( OsiCuts & cs , bool fullScan) { int howOften = whenCutGenerator_; if (howOften == -100) return false; if (howOften > 0) howOften = howOften % 1000000; else howOften = 1; if (!howOften) howOften = 1; bool returnCode = false; OsiSolverInterface * solver = model_->solver(); #if defined(ABC_DEBUG_MORE) std::cout << "model_->getNodeCount() = " << model_->getNodeCount() << std::endl; #endif if (fullScan || (model_->getNodeCount() % howOften) == 0 ) { CglProbing* generator = dynamic_cast<CglProbing*>(generator_); if (!generator) { generator_->generateCuts(*solver,cs); } else { // Probing - return tight column bounds CglTreeInfo info; generator->generateCutsAndModify(*solver,cs,&info); const double * tightLower = generator->tightLower(); const double * lower = solver->getColLower(); const double * tightUpper = generator->tightUpper(); const double * upper = solver->getColUpper(); const double * solution = solver->getColSolution(); int j; int numberColumns = solver->getNumCols(); double primalTolerance = 1.0e-8; for (j=0; j<numberColumns; j++) { if (tightUpper[j] == tightLower[j] && upper[j] > lower[j]) { // fix solver->setColLower(j, tightLower[j]); solver->setColUpper(j, tightUpper[j]); if (tightLower[j] > solution[j] + primalTolerance || tightUpper[j] < solution[j] - primalTolerance) returnCode = true; } } } } return returnCode; }
// This looks at solution and sets bounds to contain solution void CbcNWay::feasibleRegion() { int j; OsiSolverInterface * solver = model_->solver(); const double * solution = model_->testSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance); for (j = 0; j < numberMembers_; j++) { int iColumn = members_[j]; double value = solution[iColumn]; value = CoinMax(value, lower[iColumn]); value = CoinMin(value, upper[iColumn]); if (value >= upper[iColumn] - integerTolerance) { solver->setColLower(iColumn, upper[iColumn]); } else { assert (value <= lower[iColumn] + integerTolerance); solver->setColUpper(iColumn, lower[iColumn]); } } }
// Force this object within exiting bounds, then fix the bounds at the // the nearest integer value. Assume solution value is within tolerance of // the nearest integer. void BlisObjectInt::feasibleRegion(BcpsModel *m) { BlisModel *model = dynamic_cast<BlisModel* >(m); OsiSolverInterface * solver = model->solver(); const double * solution = solver->getColSolution(); const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); double value = solution[columnIndex_]; // 1) Force value to be in bounds. value = CoinMax(value, lower[columnIndex_]); value = CoinMin(value, upper[columnIndex_]); double nearest = floor(value + 0.5); // 2) Fix variable at the nearest integer assert (fabs(value - nearest) <= 0.01); solver->setColLower(columnIndex_, nearest); solver->setColUpper(columnIndex_, nearest); }
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; }
//############################################################################# 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; } }
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; }
/* Comments needed Returns 1 if solution, 0 if not */ int CbcHeuristicPivotAndFix::solution(double & /*solutionValue*/, double * /*betterSolution*/) { numCouldRun_++; // Todo: Ask JJHF what this for. std::cout << "Entering Pivot-and-Fix Heuristic" << std::endl; #ifdef HEURISTIC_INFORM printf("Entering heuristic %s - nRuns %d numCould %d when %d\n", heuristicName(),numRuns_,numCouldRun_,when_); #endif #ifdef FORNOW std::cout << "Lucky you! You're in the Pivot-and-Fix Heuristic" << std::endl; // The struct should be moved to member data typedef struct { int numberSolutions; int maximumSolutions; int numberColumns; double ** solution; int * numberUnsatisfied; } clpSolution; double start = CoinCpuTime(); OsiClpSolverInterface * clpSolverOriginal = dynamic_cast<OsiClpSolverInterface *> (model_->solver()); assert (clpSolverOriginal); OsiClpSolverInterface *clpSolver(clpSolverOriginal); ClpSimplex * simplex = clpSolver->getModelPtr(); // Initialize the structure holding the solutions clpSolution solutions; // Set typeStruct field of ClpTrustedData struct to one. // This tells Clp it's "Mahdi!" ClpTrustedData trustedSolutions; trustedSolutions.typeStruct = 1; trustedSolutions.data = &solutions; solutions.numberSolutions = 0; solutions.maximumSolutions = 0; solutions.numberColumns = simplex->numberColumns(); solutions.solution = NULL; solutions.numberUnsatisfied = NULL; simplex->setTrustedUserPointer(&trustedSolutions); // Solve from all slack to get some points simplex->allSlackBasis(); simplex->primal(); // ------------------------------------------------- // Get the problem information // - get the number of cols and rows int numCols = clpSolver->getNumCols(); int numRows = clpSolver->getNumRows(); // - get the right hand side of the rows const double * rhs = clpSolver->getRightHandSide(); // - find the integer variables bool * varClassInt = new bool[numCols]; int numInt = 0; for (int i = 0; i < numCols; i++) { if (clpSolver->isContinuous(i)) varClassInt[i] = 0; else { varClassInt[i] = 1; numInt++; } } // -Get the rows sense const char * rowSense; rowSense = clpSolver->getRowSense(); // -Get the objective coefficients const double *objCoefficients = clpSolver->getObjCoefficients(); double *originalObjCoeff = new double [numCols]; for (int i = 0; i < numCols; i++) originalObjCoeff[i] = objCoefficients[i]; // -Get the matrix of the problem double ** matrix = new double * [numRows]; for (int i = 0; i < numRows; i++) { matrix[i] = new double[numCols]; for (int j = 0; j < numCols; j++) matrix[i][j] = 0; } const CoinPackedMatrix* matrixByRow = clpSolver->getMatrixByRow(); const double * matrixElements = matrixByRow->getElements(); const int * matrixIndices = matrixByRow->getIndices(); const int * matrixStarts = matrixByRow->getVectorStarts(); for (int j = 0; j < numRows; j++) { for (int i = matrixStarts[j]; i < matrixStarts[j+1]; i++) { matrix[j][matrixIndices[i]] = matrixElements[i]; } } // The newObj is the randomly perturbed constraint used to find new // corner points double * newObj = new double [numCols]; // Set the random seed srand ( time(NULL) + 1); int randNum; // We're going to add a new row to the LP formulation // after finding each new solution. // Adding a new row requires the new elements and the new indices. // The elements are original objective function coefficients. // The indicies are the (dense) columns indices stored in addRowIndex. // The rhs is the value of the new solution stored in solutionValue. int * addRowIndex = new int[numCols]; for (int i = 0; i < numCols; i++) addRowIndex[i] = i; // The number of feasible solutions found by the PF heuristic. // This controls the return code of the solution() method. int numFeasibles = 0; // Shuffle the rows int * index = new int [numRows]; for (int i = 0; i < numRows; i++) index[i] = i; for (int i = 0; i < numRows; i++) { int temp = index[i]; int randNumTemp = i + (rand() % (numRows - i)); index[i] = index[randNumTemp]; index[randNumTemp] = temp; } // In the clpSolution struct, we store a lot of column solutions. // For each perturb objective, we store the solution from each // iteration of the LP solve. // For each perturb objective, we look at the collection of // solutions to do something extremly intelligent :-) // We could (and should..and will :-) wipe out the block of // solutions when we're done with them. But for now, we just move on // and store the next block of solutions for the next (perturbed) // objective. // The variable startIndex tells us where the new block begins. int startIndex = 0; // At most "fixThreshold" number of integer variables can be unsatisfied // for calling smallBranchAndBound(). // The PF Heuristic only fixes fixThreshold number of variables to // their integer values. Not more. Not less. The reason is to give // the smallBB some opportunity to find better solutions. If we fix // everything it might be too many (leading the heuristic to come up // with infeasibility rather than a useful result). // (This is an important paramater. And it is dynamically set.) double fixThreshold; /* if(numInt > 400) fixThreshold = 17*sqrt(numInt); if(numInt<=400 && numInt>100) fixThreshold = 5*sqrt(numInt); if(numInt<=100) fixThreshold = 4*sqrt(numInt); */ // Initialize fixThreshold based on the number of integer // variables if (numInt <= 100) fixThreshold = .35 * numInt; if (numInt > 100 && numInt < 1000) fixThreshold = .85 * numInt; if (numInt >= 1000) fixThreshold = .1 * numInt; // Whenever the dynamic system for changing fixThreshold // kicks in, it changes the parameter by the // fixThresholdChange amount. // (The 25% should be member data and tuned. Another paper!) double fixThresholdChange = 0.25 * fixThreshold; // maxNode is the maximum number of nodes we allow smallBB to // search. It's initialized to 400 and changed dynamically. // The 400 should be member data, if we become virtuous. int maxNode = 400; // We control the decision to change maxNode through the boolean // variable changeMaxNode. The boolean variable is initialized to // true and gets set to false under a condition (and is never true // again.) // It's flipped off and stays off (in the current incarnation of PF) bool changeMaxNode = 1; // The sumReturnCode is used for the dynamic system that sets // fixThreshold and changeMaxNode. // // We track what's happening in sumReturnCode. There are 8 switches. // The first 5 switches corresponds to a return code for smallBB. // // We want to know how many times we consecutively get the same // return code. // // If "good" return codes are happening often enough, we're happy. // // If a "bad" returncodes happen consecutively, we want to // change something. // // The switch 5 is the number of times PF didn't call smallBB // becuase the number of integer variables that took integer values // was less than fixThreshold. // // The swicth 6 was added for a brilliant idea...to be announced // later (another paper!) // // The switch 7 is the one that changes the max node. Read the // code. (Todo: Verbalize the brilliant idea for the masses.) // int sumReturnCode[8]; /* sumReturnCode[0] ~ -1 --> problem too big for smallBB sumReturnCode[1] ~ 0 --> smallBB not finshed and no soln sumReturnCode[2] ~ 1 --> smallBB not finshed and there is a soln sumReturnCode[3] ~ 2 --> smallBB finished and no soln sumReturnCode[4] ~ 3 --> smallBB finished and there is a soln sumReturnCode[5] ~ didn't call smallBranchAndBound too few to fix sumReturnCode[6] ~ didn't call smallBranchAndBound too many unsatisfied sumReturnCode[7] ~ the same as sumReturnCode[1] but becomes zero just if the returnCode is not 0 */ for (int i = 0; i < 8; i++) sumReturnCode[i] = 0; int * colIndex = new int[numCols]; for (int i = 0; i < numCols; i++) colIndex[i] = i; double cutoff = COIN_DBL_MAX; bool didMiniBB; // Main loop for (int i = 0; i < numRows; i++) { // track the number of mini-bb for the dynamic threshold setting didMiniBB = 0; for (int k = startIndex; k < solutions.numberSolutions; k++) //if the point has 0 unsatisfied variables; make sure it is //feasible. Check integer feasiblity and constraints. if (solutions.numberUnsatisfied[k] == 0) { double feasibility = 1; //check integer feasibility for (int icol = 0; icol < numCols; icol++) { double closest = floor(solutions.solution[k][icol] + 0.5); if (varClassInt[icol] && (fabs(solutions.solution[k][icol] - closest) > 1e-6)) { feasibility = 0; break; } } //check if the solution satisfies the constraints for (int irow = 0; irow < numRows; irow++) { double lhs = 0; for (int j = 0; j < numCols; j++) lhs += matrix[irow][j] * solutions.solution[k][j]; if (rowSense[irow] == 'L' && lhs > rhs[irow] + 1e-6) { feasibility = 0; break; } if (rowSense[irow] == 'G' && lhs < rhs[irow] - 1e-6) { feasibility = 0; break; } if (rowSense[irow] == 'E' && (lhs - rhs[irow] > 1e-6 || lhs - rhs[irow] < -1e-6)) { feasibility = 0; break; } } //if feasible, find the objective value and set the cutoff // for the smallBB and add a new constraint to the LP // (and update the best solution found so far for the // return arguments) if (feasibility) { double objectiveValue = 0; for (int j = 0; j < numCols; j++) objectiveValue += solutions.solution[k][j] * originalObjCoeff[j]; cutoff = objectiveValue; clpSolver->addRow(numCols, addRowIndex, originalObjCoeff, -COIN_DBL_MAX, cutoff); // Todo: pick up the best solution in the block (not // the last). solutionValue = objectiveValue; for (int m = 0; m < numCols; m++) betterSolution[m] = solutions.solution[k][m]; numFeasibles++; } } // Go through the block of solution and decide if to call smallBB for (int k = startIndex; k < solutions.numberSolutions; k++) { if (solutions.numberUnsatisfied[k] <= fixThreshold) { // get new copy OsiSolverInterface * newSolver; newSolver = new OsiClpSolverInterface(*clpSolver); newSolver->setObjSense(1); newSolver->setObjective(originalObjCoeff); int numberColumns = newSolver->getNumCols(); int numFixed = 0; // Fix the first fixThreshold number of integer vars // that are satisfied for (int iColumn = 0 ; iColumn < numberColumns ; iColumn++) { if (newSolver->isInteger(iColumn)) { double value = solutions.solution[k][iColumn]; double intValue = floor(value + 0.5); if (fabs(value - intValue) < 1.0e-5) { newSolver->setColLower(iColumn, intValue); newSolver->setColUpper(iColumn, intValue); numFixed++; if (numFixed > numInt - fixThreshold) break; } } } COIN_DETAIL_PRINT(printf("numFixed: %d\n", numFixed)); COIN_DETAIL_PRINT(printf("fixThreshold: %f\n", fixThreshold)); COIN_DETAIL_PRINT(printf("numInt: %d\n", numInt)); double *newSolution = new double[numCols]; double newSolutionValue; // Call smallBB on the modified problem int returnCode = smallBranchAndBound(newSolver, maxNode, newSolution, newSolutionValue, cutoff, "mini"); // If smallBB found a solution, update the better // solution and solutionValue (we gave smallBB our // cutoff, so it only finds improving solutions) if (returnCode == 1 || returnCode == 3) { numFeasibles ++; solutionValue = newSolutionValue; for (int m = 0; m < numCols; m++) betterSolution[m] = newSolution[m]; COIN_DETAIL_PRINT(printf("cutoff: %f\n", newSolutionValue)); COIN_DETAIL_PRINT(printf("time: %.2lf\n", CoinCpuTime() - start)); } didMiniBB = 1; COIN_DETAIL_PRINT(printf("returnCode: %d\n", returnCode)); //Update sumReturnCode array for (int iRC = 0; iRC < 6; iRC++) { if (iRC == returnCode + 1) sumReturnCode[iRC]++; else sumReturnCode[iRC] = 0; } if (returnCode != 0) sumReturnCode[7] = 0; else sumReturnCode[7]++; if (returnCode == 1 || returnCode == 3) { cutoff = newSolutionValue; clpSolver->addRow(numCols, addRowIndex, originalObjCoeff, -COIN_DBL_MAX, cutoff); COIN_DETAIL_PRINT(printf("******************\n\n*****************\n")); } break; } } if (!didMiniBB && solutions.numberSolutions - startIndex > 0) { sumReturnCode[5]++; for (int iRC = 0; iRC < 5; iRC++) sumReturnCode[iRC] = 0; } //Change "fixThreshold" if needed // using the data we've recorded in sumReturnCode if (sumReturnCode[1] >= 3) fixThreshold -= fixThresholdChange; if (sumReturnCode[7] >= 3 && changeMaxNode) { maxNode *= 5; changeMaxNode = 0; } if (sumReturnCode[3] >= 3 && fixThreshold < 0.95 * numInt) fixThreshold += fixThresholdChange; if (sumReturnCode[5] >= 4) fixThreshold += fixThresholdChange; if (sumReturnCode[0] > 3) fixThreshold -= fixThresholdChange; startIndex = solutions.numberSolutions; //Check if the maximum iterations limit is reached // rlh: Ask John how this is working with the change to trustedUserPtr. if (solutions.numberSolutions > 20000) break; // The first time in this loop PF solves orig LP. //Generate the random objective function randNum = rand() % 10 + 1; randNum = fmod(randNum, 2); for (int j = 0; j < numCols; j++) { if (randNum == 1) if (fabs(matrix[index[i]][j]) < 1e-6) newObj[j] = 0.1; else newObj[j] = matrix[index[i]][j] * 1.1; else if (fabs(matrix[index[i]][j]) < 1e-6) newObj[j] = -0.1; else newObj[j] = matrix[index[i]][j] * 0.9; } clpSolver->setObjective(newObj); if (rowSense[i] == 'L') clpSolver->setObjSense(-1); else // Todo #1: We don't need to solve the LPs to optimality. // We just need corner points. // There's a problem in stopping Clp that needs to be looked // into. So for now, we solve optimality. clpSolver->setObjSense(1); // simplex->setMaximumIterations(100); clpSolver->getModelPtr()->primal(1); // simplex->setMaximumIterations(100000); #ifdef COIN_DETAIL printf("cutoff: %f\n", cutoff); printf("time: %.2f\n", CoinCpuTime() - start); for (int iRC = 0; iRC < 8; iRC++) printf("%d ", sumReturnCode[iRC]); printf("\nfixThreshold: %f\n", fixThreshold); printf("numInt: %d\n", numInt); printf("\n---------------------------------------------------------------- %d\n", i); #endif //temp: if (i > 3) break; } COIN_DETAIL_PRINT(printf("Best Feasible Found: %f\n", cutoff)); COIN_DETAIL_PRINT(printf("Total time: %.2f\n", CoinCpuTime() - start)); if (numFeasibles == 0) { return 0; } // We found something better std::cout << "See you soon! You're leaving the Pivot-and-Fix Heuristic" << std::endl; std::cout << std::endl; return 1; #endif return 0; }
/** 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; }
TNLPSolver::ReturnStatus LpBranchingSolver:: solveFromHotStart(OsiTMINLPInterface* tminlp_interface) { TNLPSolver::ReturnStatus retstatus = TNLPSolver::solvedOptimal; // updated the bounds of the linear solver std::vector<int> diff_low_bnd_index; std::vector<double> diff_low_bnd_value; std::vector<int> diff_up_bnd_index; std::vector<double> diff_up_bnd_value; // Get the bounds. We assume that the bounds in the linear solver // are always the original ones const int numCols = tminlp_interface->getNumCols(); const double* colLow_orig = lin_->getColLower(); const double* colUp_orig = lin_->getColUpper(); const double* colLow = tminlp_interface->getColLower(); const double* colUp = tminlp_interface->getColUpper(); OsiSolverInterface * lin = lin_; // eventualy clone lin_ if(warm_start_mode_ == Clone){ lin = lin_->clone(); // std::cout<<"Cloning it"<<std::endl; } // Set the bounds on the LP solver according to the changes in // tminlp_interface for (int i=0; i<numCols; i++) { const double& lo = colLow[i]; if (colLow_orig[i] < lo) { if(warm_start_mode_ == Basis){ diff_low_bnd_value.push_back(colLow_orig[i]); diff_low_bnd_index.push_back(i); } lin->setColLower(i,lo); } const double& up = colUp[i]; if (colUp_orig[i] > up) { if(warm_start_mode_ == Basis){ diff_up_bnd_index.push_back(i); diff_up_bnd_value.push_back(colUp_orig[i]); } lin->setColUpper(i,lo); } } if(warm_start_mode_ == Basis){ lin->setWarmStart(warm_); } lin->resolve(); double obj = lin->getObjValue(); bool go_on = true; if (lin->isProvenPrimalInfeasible() || lin->isDualObjectiveLimitReached()) { retstatus = TNLPSolver::provenInfeasible; go_on = false; } else if (lin->isIterationLimitReached()) { retstatus = TNLPSolver::iterationLimit; go_on = false; } else { if (maxCuttingPlaneIterations_ > 0 && go_on) { double violation; obj = ecp_->doEcpRounds(*lin, true, &violation); if (obj == COIN_DBL_MAX) { retstatus = TNLPSolver::provenInfeasible; } else if (violation <= 1e-8) { retstatus = TNLPSolver::solvedOptimal; } } } tminlp_interface->problem()->set_obj_value(obj); tminlp_interface->problem()->Set_x_sol(numCols, lin_->getColSolution()); //restore the original bounds if(warm_start_mode_ == Basis){ for (unsigned int i = 0; i < diff_low_bnd_index.size(); i++) { lin_->setColLower(diff_low_bnd_index[i],diff_low_bnd_value[i]); } for (unsigned int i = 0; i < diff_up_bnd_index.size(); i++) { lin_->setColUpper(diff_up_bnd_index[i],diff_up_bnd_value[i]); } } else { delete lin; } return retstatus; }
// This version fixes stuff and does IP int CbcHeuristicLocal::solutionFix(double & objectiveValue, double * newSolution, const int * /*keep*/) { /* If when is set to off (0), or set to root (1) and we're not at the root, return. If this heuristic discovered the current solution, don't continue. */ numCouldRun_++; // See if to do if (!when() || (when() == 1 && model_->phase() != 1)) return 0; // switched off // Don't do if it was this heuristic which found solution! if (this == model_->lastHeuristic()) return 0; /* Load up a new solver with the solution. Why continuousSolver(), as opposed to solver()? */ OsiSolverInterface * newSolver = model_->continuousSolver()->clone(); const double * colLower = newSolver->getColLower(); //const double * colUpper = newSolver->getColUpper(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); /* The net effect here is that anything that hasn't moved from its lower bound will be fixed at lower bound. See comments in solution() w.r.t. asymmetric treatment of upper and lower bounds. */ int i; int nFix = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); newSolver->setColLower(iColumn, CoinMax(colLower[iColumn], originalLower)); if (!used_[iColumn]) { newSolver->setColUpper(iColumn, colLower[iColumn]); nFix++; } } /* Try a `small' branch-and-bound search. The notion here is that we've fixed a lot of variables and reduced the amount of `free' problem to a point where a small BaB search will suffice to fully explore the remaining problem. This routine will execute integer presolve, then call branchAndBound to do the actual search. */ int returnCode = 0; #ifdef CLP_INVESTIGATE2 printf("Fixing %d out of %d (%d continuous)\n", nFix, numberIntegers, newSolver->getNumCols() - numberIntegers); #endif if (nFix*10 <= numberIntegers) { // see if we can fix more int * which = new int [2*(numberIntegers-nFix)]; int * sort = which + (numberIntegers - nFix); int n = 0; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; if (used_[iColumn]) { which[n] = iColumn; sort[n++] = used_[iColumn]; } } CoinSort_2(sort, sort + n, which); // only half fixed in total n = CoinMin(n, numberIntegers / 2 - nFix); int allow = CoinMax(numberSolutions_ - 2, sort[0]); int nFix2 = 0; for (i = 0; i < n; i++) { int iColumn = integerVariable[i]; if (used_[iColumn] <= allow) { newSolver->setColUpper(iColumn, colLower[iColumn]); nFix2++; } else { break; } } delete [] which; nFix += nFix2; #ifdef CLP_INVESTIGATE2 printf("Number fixed increased from %d to %d\n", nFix - nFix2, nFix); #endif } if (nFix*10 > numberIntegers) { returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, objectiveValue, objectiveValue, "CbcHeuristicLocal"); /* -2 is return due to user event, and -1 is overloaded with what look to be two contradictory meanings. */ if (returnCode < 0) { returnCode = 0; // returned on size int numberColumns = newSolver->getNumCols(); int numberContinuous = numberColumns - numberIntegers; if (numberContinuous > 2*numberIntegers && nFix*10 < numberColumns) { #define LOCAL_FIX_CONTINUOUS #ifdef LOCAL_FIX_CONTINUOUS //const double * colUpper = newSolver->getColUpper(); const double * colLower = newSolver->getColLower(); int nAtLb = 0; //double sumDj=0.0; const double * dj = newSolver->getReducedCost(); double direction = newSolver->getObjSense(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn)) { if (!used_[iColumn]) { //double djValue = dj[iColumn]*direction; nAtLb++; //sumDj += djValue; } } } if (nAtLb) { // fix some continuous double * sort = new double[nAtLb]; int * which = new int [nAtLb]; //double threshold = CoinMax((0.01*sumDj)/static_cast<double>(nAtLb),1.0e-6); int nFix2 = 0; for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (!newSolver->isInteger(iColumn)) { if (!used_[iColumn]) { double djValue = dj[iColumn] * direction; if (djValue > 1.0e-6) { sort[nFix2] = -djValue; which[nFix2++] = iColumn; } } } } CoinSort_2(sort, sort + nFix2, which); int divisor = 2; nFix2 = CoinMin(nFix2, (numberColumns - nFix) / divisor); for (int i = 0; i < nFix2; i++) { int iColumn = which[i]; newSolver->setColUpper(iColumn, colLower[iColumn]); } delete [] sort; delete [] which; #ifdef CLP_INVESTIGATE2 printf("%d integers have zero value, and %d continuous fixed at lb\n", nFix, nFix2); #endif returnCode = smallBranchAndBound(newSolver, numberNodes_, newSolution, objectiveValue, objectiveValue, "CbcHeuristicLocal"); if (returnCode < 0) returnCode = 0; // returned on size } #endif } } } /* If the result is complete exploration with a solution (3) or proven infeasibility (2), we could generate a cut (the AI folks would call it a nogood) to prevent us from going down this route in the future. */ if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } delete newSolver; return returnCode; }
/** 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; }
/* First tries setting a variable to better value. If feasible then tries setting others. If not feasible then tries swaps Returns 1 if solution, 0 if not */ int CbcHeuristicVND::solution(double & solutionValue, double * betterSolution) { numCouldRun_++; int returnCode = 0; const double * bestSolution = model_->bestSolution(); if (!bestSolution) return 0; // No solution found yet #ifdef HEURISTIC_INFORM printf("Entering heuristic %s - nRuns %d numCould %d when %d\n", heuristicName(),numRuns_,numCouldRun_,when_); #endif if (numberSolutions_ < model_->getSolutionCount()) { // new solution - add info numberSolutions_ = model_->getSolutionCount(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int i; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double value = bestSolution[iColumn]; if (value < originalLower) { value = originalLower; } else if (value > originalUpper) { value = originalUpper; } } } int numberNodes = model_->getNodeCount(); if (howOften_ == 100) { if (numberNodes < lastNode_ + 12) return 0; // Do at 50 and 100 if ((numberNodes > 40 && numberNodes <= 50) || (numberNodes > 90 && numberNodes < 100)) numberNodes = howOften_; } if ((numberNodes % howOften_) == 0 && (model_->getCurrentPassNumber() <= 1 || model_->getCurrentPassNumber() == 999999)) { lastNode_ = model_->getNodeCount(); OsiSolverInterface * solver = model_->solver(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); const double * currentSolution = solver->getColSolution(); OsiSolverInterface * newSolver = cloneBut(3); // was model_->continuousSolver()->clone(); //const double * colLower = newSolver->getColLower(); //const double * colUpper = newSolver->getColUpper(); double primalTolerance; solver->getDblParam(OsiPrimalTolerance, primalTolerance); // Sort on distance double * distance = new double [numberIntegers]; int * which = new int [numberIntegers]; int i; int nFix = 0; double tolerance = 10.0 * primalTolerance; for (i = 0; i < numberIntegers; i++) { int iColumn = integerVariable[i]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double valueInt = bestSolution[iColumn]; if (valueInt < originalLower) { valueInt = originalLower; } else if (valueInt > originalUpper) { valueInt = originalUpper; } baseSolution_[iColumn] = currentSolution[iColumn]; distance[i] = fabs(currentSolution[iColumn] - valueInt); which[i] = i; if (fabs(currentSolution[iColumn] - valueInt) < tolerance) nFix++; } CoinSort_2(distance, distance + numberIntegers, which); nDifferent_ = numberIntegers - nFix; stepSize_ = nDifferent_ / 10; k_ = stepSize_; //nFix = numberIntegers-stepSize_; for (i = 0; i < nFix; i++) { int j = which[i]; int iColumn = integerVariable[j]; const OsiObject * object = model_->object(i); // get original bounds double originalLower; double originalUpper; getIntegerInformation( object, originalLower, originalUpper); double valueInt = bestSolution[iColumn]; if (valueInt < originalLower) { valueInt = originalLower; } else if (valueInt > originalUpper) { valueInt = originalUpper; } double nearest = floor(valueInt + 0.5); newSolver->setColLower(iColumn, nearest); newSolver->setColUpper(iColumn, nearest); } delete [] distance; delete [] which; if (nFix > numberIntegers / 5) { //printf("%d integers have samish value\n",nFix); returnCode = smallBranchAndBound(newSolver, numberNodes_, betterSolution, solutionValue, model_->getCutoff(), "CbcHeuristicVND"); if (returnCode < 0) returnCode = 0; // returned on size else numRuns_++; if ((returnCode&1) != 0) numberSuccesses_++; //printf("return code %d",returnCode); if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; //printf("could add cut with %d elements (if all 0-1)\n",nFix); } else { //printf("\n"); } numberTries_++; if ((numberTries_ % 10) == 0 && numberSuccesses_*3 < numberTries_) howOften_ += static_cast<int> (howOften_ * decayFactor_); } delete newSolver; } return returnCode; }
bool BlisConGenerator::generateCons(OsiCuts & coinCuts , bool fullScan) { bool status = false; if (strategy_ == -2) { // This con generator has been disabled. return false; } OsiSolverInterface * solver = model_->solver(); #if defined(BLIS_DEBUG_MORE) std::cout << "model_->getNodeCount() = " << model_->getNodeCount() << std::endl; #endif if ( fullScan || ((strategy_ > 0) && (model_->getNumNodes() % strategy_) == 0) ) { //-------------------------------------------------- // Start to generate cons ... //-------------------------------------------------- int j; double start = CoinCpuTime(); int numConsBefore = coinCuts.sizeCuts(); int numRowsBefore = coinCuts.sizeRowCuts(); assert(generator_ != NULL); CglProbing* generator = dynamic_cast<CglProbing *>(generator_); if (!generator) { generator_->generateCuts(*solver, coinCuts); } else { // It is probing - return tight column bound CglTreeInfo info; generator->generateCutsAndModify(*solver, coinCuts, &info); const double * tightLower = generator->tightLower(); const double * lower = solver->getColLower(); const double * tightUpper = generator->tightUpper(); const double * upper = solver->getColUpper(); const double * solution = solver->getColSolution(); int numberColumns = solver->getNumCols(); double primalTolerance = 1.0e-8; for (j = 0; j < numberColumns; ++j) { if ( (tightUpper[j] == tightLower[j]) && (upper[j] > lower[j]) ) { // fix column j solver->setColLower(j, tightLower[j]); solver->setColUpper(j, tightUpper[j]); if ( (tightLower[j] > solution[j] + primalTolerance) || (tightUpper[j] < solution[j] - primalTolerance) ) { status = true; } } } } // EOF probing. //-------------------------------------------------- // Remove zero length row cuts. //-------------------------------------------------- int numRowCons = coinCuts.sizeRowCuts(); for (j = numRowsBefore; j < numRowCons; ++j) { OsiRowCut & rCut = coinCuts.rowCut(j); int len = rCut.row().getNumElements(); #ifdef BLIS_DEBUG_MORE std::cout << "Cut " << j<<": length = " << len << std::endl; #endif if (len == 0) { // Empty cuts coinCuts.eraseRowCut(j); --j; --numRowCons; #ifdef BLIS_DEBUG std::cout << "WARNING: Empty cut from " << name_ << std::endl; #endif } else if (len < 0) { #ifdef BLIS_DEBUG std::cout << "ERROR: Cut length = " << len << std::endl; #endif // Error assert(0); } } //-------------------------------------------------- // Update statistics. //-------------------------------------------------- ++calls_; numConsGenerated_ += (coinCuts.sizeCuts() - numConsBefore); time_ += (CoinCpuTime() - start); if (numConsGenerated_ == 0) { ++noConsCalls_; } } return status; }
int * analyze(OsiClpSolverInterface * solverMod, int & numberChanged, double & increment, bool changeInt, CoinMessageHandler * generalMessageHandler, bool noPrinting) { bool noPrinting_ = noPrinting; OsiSolverInterface * solver = solverMod->clone(); char generalPrint[200]; if (0) { // just get increment CbcModel model(*solver); model.analyzeObjective(); double increment2 = model.getCutoffIncrement(); printf("initial cutoff increment %g\n", increment2); } const double *objective = solver->getObjCoefficients() ; const double *lower = solver->getColLower() ; const double *upper = solver->getColUpper() ; int numberColumns = solver->getNumCols() ; int numberRows = solver->getNumRows(); double direction = solver->getObjSense(); int iRow, iColumn; // Row copy CoinPackedMatrix matrixByRow(*solver->getMatrixByRow()); const double * elementByRow = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); // Column copy CoinPackedMatrix matrixByCol(*solver->getMatrixByCol()); const double * element = matrixByCol.getElements(); const int * row = matrixByCol.getIndices(); const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); const int * columnLength = matrixByCol.getVectorLengths(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); char * ignore = new char [numberRows]; int * changed = new int[numberColumns]; int * which = new int[numberRows]; double * changeRhs = new double[numberRows]; memset(changeRhs, 0, numberRows*sizeof(double)); memset(ignore, 0, numberRows); numberChanged = 0; int numberInteger = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8 && solver->isInteger(iColumn)) numberInteger++; } bool finished = false; while (!finished) { int saveNumberChanged = numberChanged; for (iRow = 0; iRow < numberRows; iRow++) { int numberContinuous = 0; double value1 = 0.0, value2 = 0.0; bool allIntegerCoeff = true; double sumFixed = 0.0; int jColumn1 = -1, jColumn2 = -1; for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int jColumn = column[j]; double value = elementByRow[j]; if (upper[jColumn] > lower[jColumn] + 1.0e-8) { if (!solver->isInteger(jColumn)) { if (numberContinuous == 0) { jColumn1 = jColumn; value1 = value; } else { jColumn2 = jColumn; value2 = value; } numberContinuous++; } else { if (fabs(value - floor(value + 0.5)) > 1.0e-12) allIntegerCoeff = false; } } else { sumFixed += lower[jColumn] * value; } } double low = rowLower[iRow]; if (low > -1.0e20) { low -= sumFixed; if (fabs(low - floor(low + 0.5)) > 1.0e-12) allIntegerCoeff = false; } double up = rowUpper[iRow]; if (up < 1.0e20) { up -= sumFixed; if (fabs(up - floor(up + 0.5)) > 1.0e-12) allIntegerCoeff = false; } if (!allIntegerCoeff) continue; // can't do if (numberContinuous == 1) { // see if really integer // This does not allow for complicated cases if (low == up) { if (fabs(value1) > 1.0e-3) { value1 = 1.0 / value1; if (fabs(value1 - floor(value1 + 0.5)) < 1.0e-12) { // integer changed[numberChanged++] = jColumn1; solver->setInteger(jColumn1); if (upper[jColumn1] > 1.0e20) solver->setColUpper(jColumn1, 1.0e20); if (lower[jColumn1] < -1.0e20) solver->setColLower(jColumn1, -1.0e20); } } } else { if (fabs(value1) > 1.0e-3) { value1 = 1.0 / value1; if (fabs(value1 - floor(value1 + 0.5)) < 1.0e-12) { // This constraint will not stop it being integer ignore[iRow] = 1; } } } } else if (numberContinuous == 2) { if (low == up) { /* need general theory - for now just look at 2 cases - 1 - +- 1 one in column and just costs i.e. matching objective 2 - +- 1 two in column but feeds into G/L row which will try and minimize */ if (fabs(value1) == 1.0 && value1*value2 == -1.0 && !lower[jColumn1] && !lower[jColumn2]) { int n = 0; int i; double objChange = direction * (objective[jColumn1] + objective[jColumn2]); double bound = CoinMin(upper[jColumn1], upper[jColumn2]); bound = CoinMin(bound, 1.0e20); for ( i = columnStart[jColumn1]; i < columnStart[jColumn1] + columnLength[jColumn1]; i++) { int jRow = row[i]; double value = element[i]; if (jRow != iRow) { which[n++] = jRow; changeRhs[jRow] = value; } } for ( i = columnStart[jColumn1]; i < columnStart[jColumn1] + columnLength[jColumn1]; i++) { int jRow = row[i]; double value = element[i]; if (jRow != iRow) { if (!changeRhs[jRow]) { which[n++] = jRow; changeRhs[jRow] = value; } else { changeRhs[jRow] += value; } } } if (objChange >= 0.0) { // see if all rows OK bool good = true; for (i = 0; i < n; i++) { int jRow = which[i]; double value = changeRhs[jRow]; if (value) { value *= bound; if (rowLength[jRow] == 1) { if (value > 0.0) { double rhs = rowLower[jRow]; if (rhs > 0.0) { double ratio = rhs / value; if (fabs(ratio - floor(ratio + 0.5)) > 1.0e-12) good = false; } } else { double rhs = rowUpper[jRow]; if (rhs < 0.0) { double ratio = rhs / value; if (fabs(ratio - floor(ratio + 0.5)) > 1.0e-12) good = false; } } } else if (rowLength[jRow] == 2) { if (value > 0.0) { if (rowLower[jRow] > -1.0e20) good = false; } else { if (rowUpper[jRow] < 1.0e20) good = false; } } else { good = false; } } } if (good) { // both can be integer changed[numberChanged++] = jColumn1; solver->setInteger(jColumn1); if (upper[jColumn1] > 1.0e20) solver->setColUpper(jColumn1, 1.0e20); if (lower[jColumn1] < -1.0e20) solver->setColLower(jColumn1, -1.0e20); changed[numberChanged++] = jColumn2; solver->setInteger(jColumn2); if (upper[jColumn2] > 1.0e20) solver->setColUpper(jColumn2, 1.0e20); if (lower[jColumn2] < -1.0e20) solver->setColLower(jColumn2, -1.0e20); } } // clear for (i = 0; i < n; i++) { changeRhs[which[i]] = 0.0; } } } } } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8 && !solver->isInteger(iColumn)) { double value; value = upper[iColumn]; if (value < 1.0e20 && fabs(value - floor(value + 0.5)) > 1.0e-12) continue; value = lower[iColumn]; if (value > -1.0e20 && fabs(value - floor(value + 0.5)) > 1.0e-12) continue; bool integer = true; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (!ignore[iRow]) { integer = false; break; } } if (integer) { // integer changed[numberChanged++] = iColumn; solver->setInteger(iColumn); if (upper[iColumn] > 1.0e20) solver->setColUpper(iColumn, 1.0e20); if (lower[iColumn] < -1.0e20) solver->setColLower(iColumn, -1.0e20); } } } finished = numberChanged == saveNumberChanged; } delete [] which; delete [] changeRhs; delete [] ignore; //if (numberInteger&&!noPrinting_) //printf("%d integer variables",numberInteger); if (changeInt) { //if (!noPrinting_) { //if (numberChanged) // printf(" and %d variables made integer\n",numberChanged); //else // printf("\n"); //} //increment=0.0; if (!numberChanged) { delete [] changed; delete solver; return NULL; } else { for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (solver->isInteger(iColumn)) solverMod->setInteger(iColumn); } delete solver; return changed; } } else { //if (!noPrinting_) { //if (numberChanged) // printf(" and %d variables could be made integer\n",numberChanged); //else // printf("\n"); //} // just get increment int logLevel = generalMessageHandler->logLevel(); CbcModel model(*solver); if (!model.defaultHandler()) model.passInMessageHandler(generalMessageHandler); if (noPrinting_) model.setLogLevel(0); model.analyzeObjective(); generalMessageHandler->setLogLevel(logLevel); double increment2 = model.getCutoffIncrement(); if (increment2 > increment && increment2 > 0.0) { if (!noPrinting_) { sprintf(generalPrint, "Cutoff increment increased from %g to %g", increment, increment2); CoinMessages generalMessages = solverMod->getModelPtr()->messages(); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } increment = increment2; } delete solver; numberChanged = 0; delete [] changed; return NULL; } }
//############################################################################# OsiSolverInterface * MibSBilevel::setUpModel(OsiSolverInterface * oSolver, bool newOsi, const double *lpSol) { /** Create lower-level model with fixed upper-level vars **/ int probType = model_->MibSPar_->entry(MibSParams::bilevelProblemType); bool warmStartLL = model_->MibSPar_->entry(MibSParams::warmStartLL); bool doDualFixing = model_->MibSPar_->entry(MibSParams::doDualFixing); std::string feasCheckSolver = model_->MibSPar_->entry(MibSParams::feasCheckSolver); OsiSolverInterface * nSolver; double etol(model_->etol_); int i(0), j(0), index1(0), index2(0); int uCols(model_->getUpperDim()); int lRows(model_->getLowerRowNum()); int lCols(model_->getLowerDim()); int * uColIndices = model_->getUpperColInd(); int * lColIndices = model_->getLowerColInd(); int * lRowIndices = model_->getLowerRowInd(); double objSense(model_->getLowerObjSense()); double * lObjCoeffs = model_->getLowerObjCoeffs(); const CoinPackedMatrix * matrix = oSolver->getMatrixByRow(); double coeff(0.0); if (!lpSol){ lpSol = oSolver->getColSolution(); } const double * origRowLb = model_->getOrigRowLb(); const double * origRowUb = model_->getOrigRowUb(); const double * origColLb = model_->getOrigColLb(); const double * origColUb = model_->getOrigColUb(); double * rowUb = new double[lRows]; double * rowLb = new double[lRows]; double * colUb = new double[lCols]; double * colLb = new double[lCols]; //CoinZeroN(rowUb, lRows); //CoinZeroN(rowLb, lRows); //CoinZeroN(colUb, lCols); //CoinZeroN(colLb, lCols); /** Set the row bounds **/ for(i = 0; i < lRows; i++){ rowLb[i] = origRowLb[lRowIndices[i]]; rowUb[i] = origRowUb[lRowIndices[i]]; } for(i = 0; i < lCols; i++){ colLb[i] = origColLb[lColIndices[i]]; colUb[i] = origColUb[lColIndices[i]]; } if (newOsi){ if (feasCheckSolver == "Cbc"){ nSolver = new OsiCbcSolverInterface(); }else if (feasCheckSolver == "SYMPHONY"){ nSolver = new OsiSymSolverInterface(); }else if (feasCheckSolver == "CPLEX"){ #ifdef USE_CPLEX nSolver = new OsiCpxSolverInterface(); #else throw CoinError("CPLEX chosen as solver, but it has not been enabled", "setUpModel", "MibsBilevel"); #endif }else{ throw CoinError("Unknown solver chosen", "setUpModel", "MibsBilevel"); } int * integerVars = new int[lCols]; double * objCoeffs = new double[lCols]; CoinFillN(integerVars, lCols, 0); //CoinZeroN(objCoeffs, lCols); int intCnt(0); /** Fill in array of lower-level integer variables **/ for(i = 0; i < lCols; i++){ index1 = lColIndices[i]; if(oSolver->isInteger(index1)){ integerVars[intCnt] = i; intCnt++; } } CoinDisjointCopyN(lObjCoeffs, lCols, objCoeffs); CoinPackedMatrix * newMat = new CoinPackedMatrix(false, 0, 0); newMat->setDimensions(0, lCols); double tmp(0.0); /* for(i = 0; i < lRows; i++){ CoinPackedVector row; index1 = lRowIndices[i]; start = matStarts[index1]; end = start + matrix->getVectorSize(index1); for(j = start; j < end; j++){ index2 = matIndices[j]; //tmp = findIndex(index, lCols, lColIndices); tmp = binarySearch(0, lCols - 1, index2, lColIndices); if(tmp > -1) row.insert(tmp, matElements[j]); } newMat->appendRow(row); } */ for(i = 0; i < lRows; i++){ CoinPackedVector row; index1 = lRowIndices[i]; for(j = 0; j < lCols; j++){ index2 = lColIndices[j]; tmp = matrix->getCoefficient(index1, index2); row.insert(j, tmp); } newMat->appendRow(row); } /* nSolver->assignProblem(newMat, colLb, colUb, objCoeffs, rowLb, rowUb); */ nSolver->loadProblem(*newMat, colLb, colUb, objCoeffs, rowLb, rowUb); for(i = 0; i < intCnt; i++){ nSolver->setInteger(integerVars[i]); } //nSolver->setInteger(integerVars, intCnt); nSolver->setObjSense(objSense); //1 min; -1 max nSolver->setHintParam(OsiDoReducePrint, true, OsiHintDo); #if 0 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); } #endif delete [] integerVars; }else{ nSolver = solver_; } #define SYM_VERSION_IS_WS strcmp(SYMPHONY_VERSION, "WS") #if SYMPHONY_VERSION_IS_WS if (feasCheckSolver == "SYMPHONY" && probType == 1 && warmStartLL && !newOsi && doDualFixing){ //Interdiction /** Get upper bound from best known (feasible) lower level solution and try to fix additional variables by sensitivity analysis **/ std::vector<std::pair<AlpsKnowledge*, double> > solutionPool; model_->getKnowledgeBroker()-> getAllKnowledges(AlpsKnowledgeTypeSolution, solutionPool); const double * sol; double objval, Ub(objSense*nSolver->getInfinity()); BlisSolution* blisSol; std::vector<std::pair<AlpsKnowledge*, double> >::const_iterator si; for (si = solutionPool.begin(); si != solutionPool.end(); ++si){ blisSol = dynamic_cast<BlisSolution*>(si->first); sol = blisSol->getValues(); for (i = 0; i < uCols; i++){ if (lpSol[uColIndices[i]] > 1 - etol && sol[lColIndices[i]] > 1-etol){ break; } } if (i == uCols && -objSense*blisSol->getQuality() < Ub){ Ub = -objSense*blisSol->getQuality(); } } /** Figure out which variables get fixed by the upper level solution **/ int *newUbInd = new int[uCols]; int *newLbInd = new int[uCols]; double *newUbVal = new double[uCols]; double *newLbVal = new double[uCols]; double newLb; for (i = 0; i < uCols; i++){ newUbInd[i] = uColIndices[i]; newLbInd[i] = uColIndices[i]; newLbVal[i] = 0; if (lpSol[uColIndices[i]] > 1 - etol){ newUbVal[i] = 0; }else{ newUbVal[i] = 1; } } /** If we found an upper bound, then do the dual fixing **/ if (Ub < objSense*nSolver->getInfinity()){ sym_environment *env = dynamic_cast<OsiSymSolverInterface *>(nSolver)->getSymphonyEnvironment(); for (i = 0; i < uCols; i++){ if (newUbVal[i] == 1){ // Try fixing it to zero newUbVal[i] = 0; sym_get_lb_for_new_rhs(env, 0, NULL, NULL, uCols, newLbInd, newLbVal, uCols, newUbInd, newUbVal, &newLb); if (objSense*newLb > Ub + etol){ //Victory! This variable can be fixed to 1 permanently newLbVal[i] = 1; } //Set upper bound back to 1 newUbVal[i] = 1; if (newLbVal[i] == 0){ // Try fixing it to one newLbVal[i] = 1; sym_get_lb_for_new_rhs(env, 0, NULL, NULL, uCols, newLbInd, newLbVal, uCols, newUbInd, newUbVal, &newLb); if (objSense*newLb > Ub + etol){ //Victory! This variable can be fixed to 0 permanently newUbVal[i] = 0; } newLbVal[i] = 0; } } } } /** Now set the row bounds to account for fixings **/ /** This is probably very frgaile. Assuming interdiction rows come last. It would be better to set variable bounds directly, but this doesn't seem to work right now. **/ int iRowStart = lRows-uCols; #if 1 for(i = iRowStart; i < lRows; i++){ nSolver->setRowLower(i, newLbVal[i-iRowStart]); nSolver->setRowUpper(i, newUbVal[i-iRowStart]); } #else for(i = 0; i < uCols; i++){ nSolver->setColLower(i, newLbVal[i]); nSolver->setColUpper(i, newUbVal[i]); } #endif delete[] newUbInd; delete[] newLbInd; delete[] newUbVal; delete[] newLbVal; }else{ #endif //FIXME: NEED TO GET ROW SENSE HERE /** Get contribution of upper-level columns **/ double * upComp = new double[lRows]; CoinFillN(upComp, lRows, 0.0); for(i = 0; i < lRows; i++){ index1 = lRowIndices[i]; for(j = 0; j < uCols; j++){ index2 = uColIndices[j]; coeff = matrix->getCoefficient(index1, index2); if (coeff != 0){ upComp[i] += coeff * lpSol[index2]; } } } /** Correct the row bounds to account for fixed upper-level vars **/ for(i = 0; i < lRows; i++){ nSolver->setRowLower(i, rowLb[i] - upComp[i]); nSolver->setRowUpper(i, rowUb[i] - upComp[i]); } delete [] upComp; #if SYMPHONY_VERSION_IS_WS } #endif //I don't think this is needed //if(!getWarmStart()) // setWarmStart(nSolver->getWarmStart()); return nSolver; }
// Generate constraints for the model data contained in si. // The generated constraints are inserted into and returned in the // constraint pool. // Default implementation use Cgl cut generators. bool BlisConGenerator::generateConstraints(BcpsConstraintPool &conPool) { bool status = false; OsiSolverInterface * solver = model_->solver(); #if defined(BLIS_DEBUG_MORE) std::cout << "model_->getNodeCount() = " << model_->getNodeCount() << std::endl; #endif //-------------------------------------------------- // Start to generate constraints... //-------------------------------------------------- assert(generator_ != NULL); int j; OsiCuts newOsiCuts; CglProbing* generator = dynamic_cast<CglProbing *>(generator_); if (generator) { // It is CglProbing - return tight column bounds CglTreeInfo info; generator->generateCutsAndModify(*solver, newOsiCuts, &info); const double * tightLower = generator->tightLower(); const double * lower = solver->getColLower(); const double * tightUpper = generator->tightUpper(); const double * upper = solver->getColUpper(); const double * solution = solver->getColSolution(); int numberColumns = solver->getNumCols(); double primalTolerance = 1.0e-8; for (j = 0; j < numberColumns; ++j) { if ( (tightUpper[j] == tightLower[j]) && (upper[j] > lower[j]) ) { // Fix column j solver->setColLower(j, tightLower[j]); solver->setColUpper(j, tightUpper[j]); if ( (tightLower[j] > solution[j] + primalTolerance) || (tightUpper[j] < solution[j] - primalTolerance) ) { status = true; } } } } else { // Other Cgl cut generators generator_->generateCuts(*solver, newOsiCuts); } //-------------------------------------------------- // Create blis constraints and remove zero length row cuts. //-------------------------------------------------- int numNewConstraints = newOsiCuts.sizeRowCuts(); for (j = 0; j < numNewConstraints; ++j) { OsiRowCut & rCut = newOsiCuts.rowCut(j); int len = rCut.row().getNumElements(); #ifdef BLIS_DEBUG_MORE std::cout << "Cut " << j<<": length = " << len << std::endl; #endif if (len > 0) { // Create BlisConstraints from OsiCuts. BlisConstraint *blisCon = BlisOsiCutToConstraint(&rCut); conPool.addConstraint(blisCon); } else if (len == 0) { // Empty cuts #ifdef BLIS_DEBUG std::cout << "WARNING: Empty cut from " << name_ << std::endl; #endif } else { #ifdef BLIS_DEBUG std::cout << "ERROR: Cut length = " << len << std::endl; #endif // Error assert(0); } } // Adjust cut strategy. if ( (strategy_ == BlisCutStrategyAuto) && (noConsCalls_ > BLIS_CUT_DISABLE) ) { strategy_ = BlisCutStrategyNone; } return status; }
// 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 CbcHeuristicCrossover::solution(double & solutionValue, double * betterSolution) { if (when_ == 0) return 0; numCouldRun_++; bool useBest = (numberSolutions_ != model_->getSolutionCount()); if (!useBest && (when_ % 10) == 1) return 0; numberSolutions_ = model_->getSolutionCount(); OsiSolverInterface * continuousSolver = model_->continuousSolver(); int useNumber = CoinMin(model_->numberSavedSolutions(), useNumber_); if (useNumber < 2 || !continuousSolver) return 0; // Fix later if (!useBest) abort(); numRuns_++; double cutoff; model_->solver()->getDblParam(OsiDualObjectiveLimit, cutoff); double direction = model_->solver()->getObjSense(); cutoff *= direction; cutoff = CoinMin(cutoff, solutionValue); OsiSolverInterface * solver = cloneBut(2); // But reset bounds solver->setColLower(continuousSolver->getColLower()); solver->setColUpper(continuousSolver->getColUpper()); int numberColumns = solver->getNumCols(); // Fixed double * fixed = new double [numberColumns]; for (int i = 0; i < numberColumns; i++) fixed[i] = -COIN_DBL_MAX; int whichSolution[10]; for (int i = 0; i < useNumber; i++) whichSolution[i] = i; for (int i = 0; i < useNumber; i++) { int k = whichSolution[i]; const double * solution = model_->savedSolution(k); for (int j = 0; j < numberColumns; j++) { if (solver->isInteger(j)) { if (fixed[j] == -COIN_DBL_MAX) fixed[j] = floor(solution[j] + 0.5); else if (fabs(fixed[j] - solution[j]) > 1.0e-7) fixed[j] = COIN_DBL_MAX; } } } const double * colLower = solver->getColLower(); for (int i = 0; i < numberColumns; i++) { if (solver->isInteger(i)) { double value = fixed[i]; if (value != COIN_DBL_MAX) { if (when_ < 10) { solver->setColLower(i, value); solver->setColUpper(i, value); } else if (value == colLower[i]) { solver->setColUpper(i, value); } } } } int returnCode = smallBranchAndBound(solver, numberNodes_, betterSolution, solutionValue, solutionValue, "CbcHeuristicCrossover"); if (returnCode < 0) returnCode = 0; // returned on size if ((returnCode&2) != 0) { // could add cut returnCode &= ~2; } delete solver; return returnCode; }