//----------------------------------------------------------------------------- void CbcSolverLongThin::resolve() { int * whichRow = NULL; int * whichColumn = NULL; // problem may be small enough to do nested search const double * colLower = modelPtr_->columnLower(); const double * colUpper = modelPtr_->columnUpper(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int numberRows=modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); int i; int nFix=0; int nNewRow=0; int nNewCol=0; int sizeDynamic = COIN_INT_MAX; int smallOriginalNumberRows=0; if (algorithm_==0) { for (i=0;i<numberIntegers;i++) { int iColumn=integerVariable[i]; if (colLower[iColumn]==colUpper[iColumn]) nFix++; } } else { whichRow = new int[numberRows]; whichColumn = new int [numberColumns]; // more sophisticated OsiCuts cs; tryCut->generateCuts(*this,cs); int numberCuts = cs.sizeColCuts(); if (numberCuts) { for ( i = 0 ; i < numberCuts ; i++) { const OsiColCut *thisCut = cs.colCutPtr(i) ; const CoinPackedVector & ubs = thisCut->ubs() ; int n = ubs.getNumElements() ; const int * which = ubs.getIndices() ; const double * values = ubs.getElements() ; for (int j = 0;j<n;j++) { int iColumn = which[j] ; this->setColUpper(iColumn,values[j]) ; } } } #if 1 const int * duplicate = tryCut->duplicate(); sizeDynamic = tryCut->sizeDynamic(); int nOrig = tryCut->numberOriginalRows(); for (i=0;i<nOrig;i++) { if (duplicate[i]==-1) whichRow[nNewRow++]=i; else modelPtr_->setRowStatus(i,ClpSimplex::basic); } smallOriginalNumberRows=nNewRow; for (;i<numberRows;i++) { whichRow[nNewRow++]=i; } #else for (i=0;i<numberRows;i++) whichRow[i]=i; nNewRow=numberRows; #endif for (i=0;i<numberIntegers;i++) { int iColumn=integerVariable[i]; if (colLower[iColumn]==colUpper[iColumn]) nFix++; bool choose; if (algorithm_==1) choose = true; else choose = (node_[i]>count_-memory_&&node_[i]>0); if ((choose&&colUpper[i]) ||(modelPtr_->getStatus(i)!=ClpSimplex::atLowerBound&& modelPtr_->getStatus(i)!=ClpSimplex::isFixed) ||colLower[i]>0.0) whichColumn[nNewCol++]=i; } } if (nestedSearch_<1.0&&model_&&model_->phase()==2) { if (((double) sizeDynamic)*((double) nNewCol)<1000000000&&sizeDynamic<10000000) { // could do Dynamic Programming // back to original number of rows nNewRow = smallOriginalNumberRows; // and get rid of any basics int nNewCol=0; for (i=0;i<numberColumns;i++) { if (colUpper[i]||colLower[i]>0.0) whichColumn[nNewCol++]=i; } ClpSimplex temp(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); int returnCode; double * rowLower2 = temp.rowLower(); double * rowUpper2 = temp.rowUpper(); int numberColumns2 = temp.numberColumns(); double * colLower2 = temp.columnLower(); double * colUpper2 = temp.columnUpper(); const CoinPackedMatrix * matrix = temp.matrix(); const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); double offset=0.0; const double * objective = temp.objective(); bool feasible=true; for (i=0;i<numberColumns2;i++) { double value = colLower2[i]; if (value) { offset += value*objective[i]; colLower2[i]=0.0; colUpper2[i] -= value; for (int j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; rowLower2[iRow] -= value*element[j]; rowUpper2[iRow] -= value*element[j]; if (rowUpper2[iRow]<-1.0e-8) { feasible=false; printf("odd - problem is infeasible\n"); } } } } temp.setObjectiveOffset(-offset); OsiClpSolverInterface temp2(&temp); double * solutionDP = NULL; if (feasible) { for (i=0;i<numberColumns2;i++) temp2.setInteger(i); CbcModel modelSmall(temp2); modelSmall.messageHandler()->setLogLevel(0); CbcFathomDynamicProgramming fathom1(modelSmall); // Set maximum space allowed fathom1.setMaximumSize(100000000); temp2.writeMps("small"); returnCode=fathom1.fathom(solutionDP); if (returnCode!=1) { printf("probably not enough memory\n"); abort(); } } if (solutionDP) { double objValue = 0.0; double * solution = modelPtr_->primalColumnSolution(); const double * objective = modelPtr_->objective(); for (i=0;i<numberColumns;i++) solution[i]=colLower[i]; for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]+=solutionDP[i]; } for (i=0;i<numberColumns;i++) objValue += solution[i]*objective[i]; if (objValue<model_->getCutoff()) { printf("good solution %g by dynamic programming\n",objValue); returnCode = 0; // paranoid check double * rowLower = modelPtr_->rowLower(); double * rowUpper = modelPtr_->rowUpper(); // Column copy const CoinPackedMatrix * matrix2 = modelPtr_->matrix(); element = matrix2->getElements(); row = matrix2->getIndices(); columnStart = matrix2->getVectorStarts(); columnLength = matrix2->getVectorLengths(); double * rowActivity = new double [numberRows]; memset(rowActivity,0,numberRows*sizeof(double)); for (i=0;i<numberColumns;i++) { int j; double value = solution[i]; assert (value>=colLower[i]&&value<=colUpper[i]); if (value) { printf("%d has value %g\n",i,value); for (j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; rowActivity[iRow] += value*element[j]; } } } // check was feasible bool feasible=true; for (i=0;i<numberRows;i++) { if(rowActivity[i]<rowLower[i]) { if (rowActivity[i]<rowLower[i]-1.0e-8) feasible = false; } else if(rowActivity[i]>rowUpper[i]) { if (rowActivity[i]>rowUpper[i]+1.0e-8) feasible = false; } } if (!feasible) { printf("** Bad solution by dynamic programming\n"); abort(); } delete [] rowActivity; model_->setBestSolution(CBC_TREE_SOL,objValue,solution); } else { returnCode=2; } } else { returnCode=2; } temp2.releaseClp(); modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; return; } if (nFix>nestedSearch_*numberIntegers) { // Do nested search // back to original number of rows nNewRow = smallOriginalNumberRows; // and get rid of any basics int nNewCol=0; for (i=0;i<numberColumns;i++) { if (colUpper[i]||colLower[i]>0.0) whichColumn[nNewCol++]=i; } #if 0 // We clone from continuous solver so set some stuff OsiSolverInterface * solver = model_->continuousSolver(); CbcSolverLongThin * osiclp = dynamic_cast< CbcSolverLongThin*> (solver); assert (osiclp); // up special options if (osiclp->specialOptions()==3) osiclp->setSpecialOptions(7); double saveNested = osiclp->getNested(); int saveAlgorithm = osiclp->getAlgorithm(); osiclp->setNested(1.0); osiclp->setAlgorithm(0); int numberObjects = model_->numberObjects(); if (numberObjects>model_->numberIntegers()) { // for now only integers //assert (numberObjects == model_->numberIntegers()+1); model_->setNumberObjects(model_->numberIntegers()); // try follow on //model_->setNumberObjects(model_->numberIntegers()+1); } double saveMaxTime = model_->getDblParam(CbcModel::CbcMaximumSeconds); model_->setDblParam(CbcModel::CbcMaximumSeconds,1.0e5); // up special options #if 1 int returnCode= model_->subBranchAndBound(colLower,colUpper,2000); #else CbcModel * model3 = model_->cleanModel(colLower,colUpper); // integer presolve int returnCode=0; CbcModel * model2 = model3->integerPresolve(false); if (!model2||!model2->getNumRows()) { delete model2; delete model3; returnCode= 2; } else { if (handler_->logLevel()>1) printf("Reduced model has %d rows and %d columns\n", model2->getNumRows(),model2->getNumCols()); if (true) { OsiSolverInterface * solver = model2->solver(); OsiSolverInterface * osiclp = dynamic_cast< OsiSolverInterface*> (solver); assert (osiclp); int * priority = new int [numberColumns+1]; int n=0; int iColumn; for ( iColumn=0;iColumn<numberColumns;iColumn++) { if (solver->isInteger(iColumn)) { priority[n++]=10000; } } priority[n]=1; CbcObject * newObject =new CbcFollowOn2(model2); model2->addObjects(1,&newObject); delete newObject; model2->passInPriorities(priority,false); delete [] priority; } returnCode= model_->subBranchAndBound(model3,model2,4000); } #endif model_->setDblParam(CbcModel::CbcMaximumSeconds,saveMaxTime); model_->setNumberObjects(numberObjects); osiclp->setNested(saveNested); osiclp->setAlgorithm(saveAlgorithm); #else // start again very simply ClpSimplex temp(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); int returnCode; OsiClpSolverInterface temp2(&temp); temp2.setupForRepeatedUse(2); int numberColumns2 = temp.numberColumns(); const double * colUpper2 = temp2.getColUpper(); const double * colLower2 = temp2.getColLower(); const double * solution2 = temp.getColSolution(); double * cleanSolution2 = new double [numberColumns2]; for (i=0;i<numberColumns2;i++) { temp2.setInteger(i); double value = solution2[i]; value = CoinMin(CoinMax(value,colLower2[i]),colUpper2[i]); cleanSolution2[i] = value; } temp2.setColSolution(cleanSolution2); delete [] cleanSolution2; CbcModel modelSmall(temp2); modelSmall.setNumberStrong(0); CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); generator1.setMaxProbe(100); generator1.setMaxLook(50); generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglOddHole generator4; generator4.setMinimumViolation(0.005); generator4.setMinimumViolationPer(0.00002); // try larger limit generator4.setMaximumEntries(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding mixedGen; CglFlowCover flowGen; // Add in generators modelSmall.addCutGenerator(&generator1,-1,"Probing",true,false,false,-1); modelSmall.addCutGenerator(&generator2,-99,"Gomory",true,false,false,-99); modelSmall.addCutGenerator(&generator3,-99,"Knapsack",true,false,false,-99); modelSmall.addCutGenerator(&generator4,-99,"OddHole",true,false,false,-99); modelSmall.addCutGenerator(&generator5,-99,"Clique",true,false,false,-99); modelSmall.addCutGenerator(&flowGen,-99,"FlowCover",true,false,false,-99); modelSmall.addCutGenerator(&mixedGen,-99,"MixedIntegerRounding",true,false,false,-100); #if 1 const CoinPackedMatrix * matrix = temp2.getMatrixByCol(); const int * columnLength = matrix->getVectorLengths(); int * priority = new int [numberColumns2+1]; // do pseudo costs and priorities - take a reasonable guess CbcObject ** objects = new CbcObject * [numberColumns2+1]; int n=0; const double * objective = modelSmall.getObjCoefficients(); for (i=0;i<numberColumns2;i++) { CbcSimpleIntegerPseudoCost * newObject = new CbcSimpleIntegerPseudoCost(&modelSmall,n,i,objective[i],0.5*objective[i]); newObject->setMethod(3); objects[n]= newObject; priority[n++]=10000-columnLength[i]; } priority[n]=1; objects[n++]=new CbcFollowOn2(&modelSmall); modelSmall.addObjects(n,objects); for (i=0;i<n;i++) delete objects[i]; delete [] objects; modelSmall.passInPriorities(priority,false); delete [] priority; #endif modelSmall.setCutoff(model_->getCutoff()); //if (!onPathX&&modelSmall.getCutoff()>480.5) //modelSmall.setCutoff(480.5); //printf("cutoff %g\n",model_->getCutoff()); modelSmall.messageHandler()->setLogLevel(1); modelSmall.solver()->messageHandler()->setLogLevel(0); modelSmall.messagesPointer()->setDetailMessage(3,9); modelSmall.messagesPointer()->setDetailMessage(3,6); modelSmall.messagesPointer()->setDetailMessage(3,4); modelSmall.messagesPointer()->setDetailMessage(3,13); modelSmall.messagesPointer()->setDetailMessage(3,14); modelSmall.messagesPointer()->setDetailMessage(3,1); modelSmall.messagesPointer()->setDetailMessage(3,3007); modelSmall.branchAndBound(); temp2.releaseClp(); if (modelSmall.bestSolution()) { double objValue = 0.0; const double * solution2 = modelSmall.bestSolution(); double * solution = modelPtr_->primalColumnSolution(); const double * objective = modelPtr_->objective(); for (i=0;i<numberColumns;i++) solution[i]=colLower[i]; for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]=solution2[i]; } for (i=0;i<numberColumns;i++) objValue += solution[i]*objective[i]; assert (objValue<model_->getCutoff()); if (objValue<model_->getCutoff()) { //printf("good solution \n"); model_->setBestSolution(CBC_TREE_SOL,objValue,solution); returnCode = 0; } else { returnCode=2; } } else { returnCode=2; } #endif if (returnCode!=0&&returnCode!=2) { printf("pretending entire search done\n"); returnCode=0; } if (returnCode==0||returnCode==2) { modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; return; } } } if ((count_<100&&algorithm_==2)||!algorithm_) { delete [] whichRow; delete [] whichColumn; assert(!modelPtr_->specialOptions()); int saveOptions = modelPtr_->specialOptions(); int startFinishOptions; bool takeHint; OsiHintStrength strength; bool gotHint = (getHintParam(OsiDoInBranchAndCut,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore&&takeHint) { // could do something - think about it //printf("thin hint %d %c\n",strength,takeHint ? 'T' :'F'); } if((specialOptions_&1)==0) { startFinishOptions=0; modelPtr_->setSpecialOptions(saveOptions|(64|1024)); } else { startFinishOptions=1+2+4; if((specialOptions_&4)==0) modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|4096)); else modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|2048|4096)); } //printf("thin options %d size %d\n",modelPtr_->specialOptions(),modelPtr_->numberColumns()); setBasis(basis_,modelPtr_); //modelPtr_->setLogLevel(1); modelPtr_->dual(0,0); basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(saveOptions); if (modelPtr_->status()==0) { count_++; double * solution = modelPtr_->primalColumnSolution(); int i; for (i=0;i<numberColumns;i++) { if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } } else { if (!algorithm_==2) printf("infeasible early on\n"); } } else { // use counts int i; const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); setBasis(basis_,modelPtr_); ClpSimplex * temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); //temp->setLogLevel(2); //printf("small has %d rows and %d columns\n",nNewRow,nNewCol); temp->setSpecialOptions(128+512); temp->setDualObjectiveLimit(1.0e50); temp->dual(); if (temp->status()) { // In some cases we know that it must be infeasible if (believeInfeasible_||algorithm_==1) { modelPtr_->setProblemStatus(1); printf("assuming infeasible!\n"); //modelPtr_->writeMps("infeas.mps"); //temp->writeMps("infeas2.mps"); //abort(); delete temp; delete [] whichRow; delete [] whichColumn; return; } } double * solution = modelPtr_->primalColumnSolution(); if (!temp->status()) { const double * solution2 = temp->primalColumnSolution(); memset(solution,0,numberColumns*sizeof(double)); for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]=solution2[i]; modelPtr_->setStatus(iColumn,temp->getStatus(i)); } double * rowSolution = modelPtr_->primalRowSolution(); const double * rowSolution2 = temp->primalRowSolution(); double * dual = modelPtr_->dualRowSolution(); const double * dual2 = temp->dualRowSolution(); memset(dual,0,numberRows*sizeof(double)); for (i=0;i<nNewRow;i++) { int iRow=whichRow[i]; modelPtr_->setRowStatus(iRow,temp->getRowStatus(i)); rowSolution[iRow]=rowSolution2[i]; dual[iRow]=dual2[i]; } // See if optimal double * dj = modelPtr_->dualColumnSolution(); // get reduced cost for large problem // this assumes minimization memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double)); modelPtr_->transposeTimes(-1.0,dual,dj); modelPtr_->setObjectiveValue(temp->objectiveValue()); modelPtr_->setProblemStatus(0); int nBad=0; for (i=0;i<numberColumns;i++) { if (modelPtr_->getStatus(i)==ClpSimplex::atLowerBound &&upper[i]>lower[i]&&dj[i]<-1.0e-5) nBad++; } //modelPtr_->writeMps("bada.mps"); //temp->writeMps("badb.mps"); if (nBad) { assert (algorithm_==2); //printf("%d bad\n",nBad); timesBad_++; modelPtr_->primal(); } } else { // infeasible - do all modelPtr_->setSpecialOptions(64+128+512); setBasis(basis_,modelPtr_); //modelPtr_->setLogLevel(1); modelPtr_->dual(0,0); basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); if (modelPtr_->status()) { printf("really infeasible!\n"); delete temp; delete [] whichRow; delete [] whichColumn; return; } else { printf("initially infeasible\n"); } } delete temp; delete [] whichRow; delete [] whichColumn; basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); count_++; if ((count_%100)==0&&algorithm_==2) printf("count %d, bad %d\n",count_,timesBad_); for (i=0;i<numberColumns;i++) { if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } if (modelPtr_->objectiveValue()>=modelPtr_->dualObjectiveLimit()) modelPtr_->setProblemStatus(1); } }
int main (int argc, const char *argv[]) { CbcSolver3 solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); assert(numMpsReadErrors==0); double time1 = CoinCpuTime(); /* Options are: preprocess to do preprocessing time in minutes if 2 parameters and numeric taken as time */ bool preProcess=false; double minutes=-1.0; int nGoodParam=0; for (int iParam=2; iParam<argc;iParam++) { if (!strcmp(argv[iParam],"preprocess")) { preProcess=true; nGoodParam++; } else if (!strcmp(argv[iParam],"time")) { if (iParam+1<argc&&isdigit(argv[iParam+1][0])) { minutes=atof(argv[iParam+1]); if (minutes>=0.0) { nGoodParam+=2; iParam++; // skip time } } } } if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) { // If time is given then stop after that number of minutes minutes = atof(argv[2]); if (minutes>=0.0) nGoodParam=1; } if (nGoodParam!=argc-2) { printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n"); exit(1); } solver1.initialSolve(); // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); // Say we want scaling //solver1.setHintParam(OsiDoScale,true,OsiHintTry); //solver1.setCleanupScaling(1); // See if we want preprocessing OsiSolverInterface * solver2=&solver1; CglPreProcess process; if (preProcess) { /* Do not try and produce equality cliques and do up to 5 passes */ solver2 = process.preProcess(solver1,false,5); if (!solver2) { printf("Pre-processing says infeasible\n"); exit(2); } solver2->resolve(); } CbcModel model(*solver2); // Point to solver OsiSolverInterface * solver3 = model.solver(); CbcSolver3 * osiclp = dynamic_cast< CbcSolver3*> (solver3); assert (osiclp); const double fractionFix=0.985; osiclp->initialize(&model,NULL); osiclp->setAlgorithm(2); osiclp->setMemory(1000); osiclp->setNested(fractionFix); //osiclp->setNested(1.0); //off // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); // How far to follow the consequences generator1.setMaxLook(50); // Only look at rows with fewer than this number of elements generator1.setMaxElements(200); generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglOddHole generator4; generator4.setMinimumViolation(0.005); generator4.setMinimumViolationPer(0.00002); // try larger limit generator4.setMaximumEntries(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding mixedGen; /* This is same as default constructor - (1,true,1) I presume if maxAggregate larger then slower but maybe better criterion can be 1 through 3 Reference: Hugues Marchand and Laurence A. Wolsey Aggregation and Mixed Integer Rounding to Solve MIPs Operations Research, 49(3), May-June 2001. */ int maxAggregate=1; bool multiply=true; int criterion=1; CglMixedIntegerRounding2 mixedGen2(maxAggregate,multiply,criterion); CglFlowCover flowGen; // Add in generators // Experiment with -1 and -99 etc model.addCutGenerator(&generator1,-99,"Probing"); //model.addCutGenerator(&generator2,-1,"Gomory"); //model.addCutGenerator(&generator3,-1,"Knapsack"); //model.addCutGenerator(&generator4,-1,"OddHole"); //model.addCutGenerator(&generator5,-1,"Clique"); //model.addCutGenerator(&flowGen,-1,"FlowCover"); //model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding"); //model.addCutGenerator(&mixedGen2,-1,"MixedIntegerRounding2"); // Say we want timings int numberGenerators = model.numberCutGenerators(); int iGenerator; for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) { CbcCutGenerator * generator = model.cutGenerator(iGenerator); generator->setTiming(true); } // Allow rounding heuristic CbcRounding heuristic1(model); model.addHeuristic(&heuristic1); // And Greedy heuristic CbcHeuristicGreedyCover heuristic2(model); // Use original upper and perturb more heuristic2.setAlgorithm(11); model.addHeuristic(&heuristic2); // Redundant definition of default branching (as Default == User) CbcBranchUserDecision branch; model.setBranchingMethod(&branch); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); int iColumn; int numberColumns = solver3->getNumCols(); // do pseudo costs CbcObject ** objects = new CbcObject * [numberColumns+1]; const CoinPackedMatrix * matrix = solver3->getMatrixByCol(); // Column copy const int * columnLength = matrix->getVectorLengths(); const double * objective = model.getObjCoefficients(); int n=0; for (iColumn=0;iColumn<numberColumns;iColumn++) { if (solver3->isInteger(iColumn)) { double costPer = objective[iColumn]/ ((double) columnLength[iColumn]); CbcSimpleIntegerPseudoCost * newObject = new CbcSimpleIntegerPseudoCost(&model,n,iColumn, costPer,costPer); newObject->setMethod(3); objects[n++]= newObject; } } // and special fix lots branch objects[n++]=new CbcBranchToFixLots(&model,-1.0e-6,fractionFix+0.01,1,0,NULL); model.addObjects(n,objects); for (iColumn=0;iColumn<n;iColumn++) delete objects[iColumn]; delete [] objects; // High priority for odd object int followPriority=1; model.passInPriorities(&followPriority,true); // Do initial solve to continuous model.initialSolve(); // Could tune more model.setMinimumDrop(CoinMin(1.0, fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4)); if (model.getNumCols()<500) model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (model.getNumCols()<5000) model.setMaximumCutPassesAtRoot(100); // use minimum drop else model.setMaximumCutPassesAtRoot(20); //model.setMaximumCutPasses(1); // Do more strong branching if small //if (model.getNumCols()<5000) //model.setNumberStrong(10); // Switch off strong branching if wanted model.setNumberStrong(0); model.solver()->setIntParam(OsiMaxNumIterationHotStart,100); // If time is given then stop after that number of minutes if (minutes>=0.0) { std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl; model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes); } // Switch off most output if (model.getNumCols()<300000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } //model.messageHandler()->setLogLevel(2); //model.solver()->messageHandler()->setLogLevel(2); //model.setPrintFrequency(50); #define DEBUG_CUTS #ifdef DEBUG_CUTS // Set up debugger by name (only if no preprocesing) if (!preProcess) { std::string problemName ; //model.solver()->getStrParam(OsiProbName,problemName) ; //model.solver()->activateRowCutDebugger(problemName.c_str()) ; model.solver()->activateRowCutDebugger("cap6000a") ; } #endif // Do complete search try { model.branchAndBound(); } catch (CoinError e) { e.print(); if (e.lineNumber()>=0) std::cout<<"This was from a CoinAssert"<<std::endl; exit(0); } //void printHowMany(); //printHowMany(); std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, " <<model.getNodeCount()<<" nodes with objective " <<model.getObjValue() <<(!model.status() ? " Finished" : " Not finished") <<std::endl; // Print more statistics std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective() <<" to "<<model.rootObjectiveAfterCuts()<<std::endl; for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) { CbcCutGenerator * generator = model.cutGenerator(iGenerator); std::cout<<generator->cutGeneratorName()<<" was tried " <<generator->numberTimesEntered()<<" times and created " <<generator->numberCutsInTotal()<<" cuts of which " <<generator->numberCutsActive()<<" were active after adding rounds of cuts"; if (generator->timing()) std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl; else std::cout<<std::endl; } // Print solution if finished - we can't get names from Osi! if (model.getMinimizationObjValue()<1.0e50) { // post process if (preProcess) process.postProcess(*model.solver()); int numberColumns = model.solver()->getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14); std::cout<<"--------------------------------------"<<std::endl; for (iColumn=0;iColumn<numberColumns;iColumn++) { double value=solution[iColumn]; if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl; } std::cout<<"--------------------------------------"<<std::endl; std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific); } return 0; }