int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; #if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR "/p0033.mps"; #else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } #endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); assert(numMpsReadErrors==0); double time1 = CoinCpuTime(); OsiClpSolverInterface solverSave = solver1; /* 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&&argc>=2) { printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n"); exit(1); } // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); // See if we want preprocessing OsiSolverInterface * solver2=&solver1; CglPreProcess process; // Never do preprocessing until dual tests out as can fix incorrectly preProcess=false; 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(); } // Turn L rows into cuts CglStoredUser stored; { int numberRows = solver2->getNumRows(); int * whichRow = new int[numberRows]; // get row copy const CoinPackedMatrix * rowCopy = solver2->getMatrixByRow(); const int * column = rowCopy->getIndices(); const int * rowLength = rowCopy->getVectorLengths(); const CoinBigIndex * rowStart = rowCopy->getVectorStarts(); const double * rowLower = solver2->getRowLower(); const double * rowUpper = solver2->getRowUpper(); const double * element = rowCopy->getElements(); int iRow,nDelete=0; for (iRow=0;iRow<numberRows;iRow++) { if (rowLower[iRow]<-1.0e20||rowUpper[iRow]>1.0e20) { // take out whichRow[nDelete++]=iRow; } } // leave some rows to avoid empty problem (Gomory does not like) nDelete = CoinMax(CoinMin(nDelete,numberRows-5),0); for (int jRow=0;jRow<nDelete;jRow++) { iRow=whichRow[jRow]; int start = rowStart[iRow]; stored.addCut(rowLower[iRow],rowUpper[iRow],rowLength[iRow], column+start,element+start); } /* The following is problem specific. Normally cuts are deleted if slack on cut basic. On some problems you may wish to leave cuts in as long as slack value zero */ int numberCuts=stored.sizeRowCuts(); for (int iCut=0;iCut<numberCuts;iCut++) { //stored.mutableRowCutPointer(iCut)->setEffectiveness(1.0e50); } solver2->deleteRows(nDelete,whichRow); delete [] whichRow; } CbcModel model(*solver2); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(1); generator1.setMaxPassRoot(5); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); generator1.setMaxProbeRoot(1000); // How far to follow the consequences generator1.setMaxLook(50); generator1.setMaxLookRoot(500); // 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; CglRedSplit generator4; // try larger limit generator4.setLimit(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding2 mixedGen; CglFlowCover flowGen; // Add in generators // Experiment with -1 and -99 etc // This is just for one particular model model.addCutGenerator(&generator1,-1,"Probing"); //model.addCutGenerator(&generator2,-1,"Gomory"); model.addCutGenerator(&generator2,1,"Gomory"); model.addCutGenerator(&generator3,-1,"Knapsack"); // model.addCutGenerator(&generator4,-1,"RedSplit"); //model.addCutGenerator(&generator5,-1,"Clique"); model.addCutGenerator(&generator5,1,"Clique"); model.addCutGenerator(&flowGen,-1,"FlowCover"); model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding"); // Add stored cuts (making sure at all depths) model.addCutGenerator(&stored,1,"Stored",true,false,false,-100,1,-1); int numberGenerators = model.numberCutGenerators(); int iGenerator; // Say we want timings for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) { CbcCutGenerator * generator = model.cutGenerator(iGenerator); generator->setTiming(true); } OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver()); // go faster stripes if (osiclp) { if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) { //osiclp->setupForRepeatedUse(2,0); osiclp->setupForRepeatedUse(0,0); } // Don't allow dual stuff osiclp->setSpecialOptions(osiclp->specialOptions()|262144); } // Uncommenting this should switch off all CBC messages // model.messagesPointer()->setDetailMessages(10,10000,NULL); // No heuristics // Do initial solve to continuous model.initialSolve(); /* You need the next few lines - a) so that cut generator will always be called again if it generated cuts b) it is known that matrix is not enough to define problem so do cuts even if it looks integer feasible at continuous optimum. c) a solution found by strong branching will be ignored. d) don't recompute a solution once found */ // Make sure cut generator called correctly (a) iGenerator=numberGenerators-1; model.cutGenerator(iGenerator)->setMustCallAgain(true); // Say cuts needed at continuous (b) OsiBabSolver oddCuts; oddCuts.setSolverType(4); // owing to bug must set after initialSolve model.passInSolverCharacteristics(&oddCuts); // Say no to all solutions by strong branching (c) CbcFeasibilityNoStrong noStrong; model.setProblemFeasibility(noStrong); // Say don't recompute solution d) model.setSpecialOptions(4); // Could tune more double objValue = model.solver()->getObjSense()*model.solver()->getObjValue(); double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4); double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4; printf("min drop %g (A %g)\n",minimumDrop,minimumDropA); model.setMinimumDrop(minimumDrop); 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(10); //model.setMaximumCutPasses(2); // Switch off strong branching if wanted // model.setNumberStrong(0); // Do more strong branching if small if (model.getNumCols()<5000) model.setNumberStrong(10); model.setNumberStrong(20); //model.setNumberStrong(5); model.setNumberBeforeTrust(5); 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()<30000) { 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()) ; } #endif // Do complete search model.branchAndBound(); 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! - so get from OsiClp if (model.getMinimizationObjValue()<1.0e50) { // post process OsiSolverInterface * solver; if (preProcess) { process.postProcess(*model.solver()); // Solution now back in solver1 solver = & solver1; } else { solver = model.solver(); } int numberColumns = solver->getNumCols(); const double * solution = solver->getColSolution(); // Get names from solver1 (as OsiSolverInterface may lose) std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames(); 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&&solver->isInteger(iColumn)) { std::cout<<std::setw(6)<<iColumn<<" " <<columnNames[iColumn]<<" " <<value<<std::endl; solverSave.setColLower(iColumn,value); solverSave.setColUpper(iColumn,value); } } std::cout<<"--------------------------------------"<<std::endl; std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific); solverSave.initialSolve(); } return 0; }
int main (int argc, const char *argv[]) { // Define your favorite OsiSolver OsiClpSolverInterface solver1; // Read in model using argv[1] // and assert that it is a clean model std::string dirsep(1,CoinFindDirSeparator()); std::string mpsFileName; # if defined(SAMPLEDIR) mpsFileName = SAMPLEDIR ; mpsFileName += dirsep+"p0033.mps"; # else if (argc < 2) { fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); } # endif if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); if( numMpsReadErrors != 0 ) { printf("%d errors reading MPS file\n", numMpsReadErrors); return numMpsReadErrors; } 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&&argc>=2) { printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n"); exit(1); } solver1.initialSolve(); // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); // See if we want preprocessing OsiSolverInterface * solver2=&solver1; #if PREPROCESS==1 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(); } #endif CbcModel model(*solver2); model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry); // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(1); generator1.setMaxPassRoot(5); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); generator1.setMaxProbeRoot(1000); // How far to follow the consequences generator1.setMaxLook(50); generator1.setMaxLookRoot(500); // 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; CglRedSplit generator4; // try larger limit generator4.setLimit(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding2 mixedGen; CglFlowCover flowGen; // Add in generators // Experiment with -1 and -99 etc model.addCutGenerator(&generator1,-1,"Probing"); model.addCutGenerator(&generator2,-1,"Gomory"); model.addCutGenerator(&generator3,-1,"Knapsack"); // model.addCutGenerator(&generator4,-1,"RedSplit"); model.addCutGenerator(&generator5,-1,"Clique"); model.addCutGenerator(&flowGen,-1,"FlowCover"); model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding"); // Say we want timings int numberGenerators = model.numberCutGenerators(); int iGenerator; for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) { CbcCutGenerator * generator = model.cutGenerator(iGenerator); generator->setTiming(true); } OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver()); // go faster stripes if (osiclp) { // Turn this off if you get problems // Used to be automatically set osiclp->setSpecialOptions(128); if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) { //osiclp->setupForRepeatedUse(2,0); osiclp->setupForRepeatedUse(0,0); } } // Uncommenting this should switch off all CBC messages // model.messagesPointer()->setDetailMessages(10,10000,NULL); // Allow rounding heuristic CbcRounding heuristic1(model); model.addHeuristic(&heuristic1); // And local search when new solution found CbcHeuristicLocal heuristic2(model); 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); // Do initial solve to continuous model.initialSolve(); // Could tune more double objValue = model.solver()->getObjSense()*model.solver()->getObjValue(); double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4); double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4; printf("min drop %g (A %g)\n",minimumDrop,minimumDropA); model.setMinimumDrop(minimumDrop); 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(10); //model.setMaximumCutPasses(2); // Switch off strong branching if wanted // model.setNumberStrong(0); // Do more strong branching if small if (model.getNumCols()<5000) model.setNumberStrong(10); model.setNumberStrong(20); //model.setNumberStrong(5); model.setNumberBeforeTrust(5); 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()<3000) { 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()) ; } #endif #if PREPROCESS==2 // Default strategy will leave cut generators as they exist already // so cutsOnlyAtRoot (1) ignored // numberStrong (2) is 5 (default) // numberBeforeTrust (3) is 5 (default is 0) // printLevel (4) defaults (0) CbcStrategyDefault strategy(true,5,5); // Set up pre-processing to find sos if wanted if (preProcess) strategy.setupPreProcessing(2); model.setStrategy(strategy); #endif // Do complete search model.branchAndBound(); 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! - so get from OsiClp if (model.getMinimizationObjValue()<1.0e50) { #if PREPROCESS==1 // post process OsiSolverInterface * solver; if (preProcess) { process.postProcess(*model.solver()); // Solution now back in solver1 solver = & solver1; } else { solver = model.solver(); } #else OsiSolverInterface * solver = model.solver(); #endif int numberColumns = solver->getNumCols(); const double * solution = solver->getColSolution(); // Get names from solver1 (as OsiSolverInterface may lose) std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames(); 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&&solver->isInteger(iColumn)) std::cout<<std::setw(6)<<iColumn<<" " <<columnNames[iColumn]<<" " <<value<<std::endl; } std::cout<<"--------------------------------------"<<std::endl; std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific); } return 0; }
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; }