source: branches/devel/Cbc/examples/sample6.cpp @ 529

Last change on this file since 529 was 495, checked in by forrest, 13 years ago

for osi integers

File size: 10.1 KB
Line 
1// Copyright (C) 2006, International Business Machines
2// Corporation and others.  All Rights Reserved.
3#if defined(_MSC_VER)
4// Turn off compiler warning about long names
5#  pragma warning(disable:4786)
6#endif
7
8#include <cassert>
9#include <iomanip>
10
11
12// For Branch and bound
13#include "OsiSolverInterface.hpp"
14#include "CbcModel.hpp"
15#include "CbcCutGenerator.hpp"
16#include "CbcStrategy.hpp"
17#include "CbcHeuristicLocal.hpp"
18#include "CbcBranchActual.hpp"
19#include "OsiClpSolverInterface.hpp"
20#include "OsiChooseVariable.hpp"
21
22// Cuts
23
24#include "CglGomory.hpp"
25#include "CglProbing.hpp"
26#include "CglKnapsackCover.hpp"
27#include "CglRedSplit.hpp"
28#include "CglClique.hpp"
29#include "CglFlowCover.hpp"
30#include "CglMixedIntegerRounding2.hpp"
31// Preprocessing
32#include "CglPreProcess.hpp"
33
34// Heuristics
35
36#include "CbcHeuristic.hpp"
37
38#include  "CoinTime.hpp"
39
40//#############################################################################
41
42
43/************************************************************************
44
45This main program reads in an integer model from an mps file.
46
47It then sets up some Cgl cut generators and calls branch and cut.
48
49Branching is simple binary branching on integer variables.
50
51Node selection is depth first until first solution is found and then
52based on objective and number of unsatisfied integer variables.
53In this example the functionality is the same as default but it is
54a user comparison function.
55
56Variable branching selection is on maximum minimum-of-up-down change
57after strong branching on 5 variables closest to 0.5.
58
59A simple rounding heuristic is used.
60
61This version shows use of Osi objects rather than Cbc objects
62************************************************************************/
63
64int main (int argc, const char *argv[])
65{
66
67  // Define your favorite OsiSolver
68 
69  OsiClpSolverInterface solver1;
70
71  // Read in model using argv[1]
72  // and assert that it is a clean model
73  std::string mpsFileName = "../../Data/Sample/p0033.mps";
74  if (argc>=2) mpsFileName = argv[1];
75  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
76  assert(numMpsReadErrors==0);
77  double time1 = CoinCpuTime();
78
79  /* Options are:
80     preprocess to do preprocessing
81     time in minutes
82     if 2 parameters and numeric taken as time
83  */
84  bool preProcess=false;
85  double minutes=-1.0;
86  int nGoodParam=0;
87  for (int iParam=2; iParam<argc;iParam++) {
88    if (!strcmp(argv[iParam],"preprocess")) {
89      preProcess=true;
90      nGoodParam++;
91    } else if (!strcmp(argv[iParam],"time")) {
92      if (iParam+1<argc&&isdigit(argv[iParam+1][0])) {
93        minutes=atof(argv[iParam+1]);
94        if (minutes>=0.0) {
95          nGoodParam+=2;
96          iParam++; // skip time
97        }
98      }
99    }
100  }
101  if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) {
102    // If time is given then stop after that number of minutes
103    minutes = atof(argv[2]);
104    if (minutes>=0.0) 
105      nGoodParam=1;
106  }
107  if (nGoodParam!=argc-2&&argc>=2) {
108    printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n");
109    exit(1);
110  }
111  solver1.initialSolve();
112  // Reduce printout
113  solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
114  // See if we want preprocessing
115  OsiSolverInterface * solver2=&solver1;
116  CbcModel model(*solver2);
117  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
118  // Set up some cut generators and defaults
119  // Probing first as gets tight bounds on continuous
120
121  CglProbing generator1;
122  generator1.setUsingObjective(true);
123  generator1.setMaxPass(1);
124  generator1.setMaxPassRoot(5);
125  // Number of unsatisfied variables to look at
126  generator1.setMaxProbe(10);
127  generator1.setMaxProbeRoot(1000);
128  // How far to follow the consequences
129  generator1.setMaxLook(50);
130  generator1.setMaxLookRoot(500);
131  // Only look at rows with fewer than this number of elements
132  generator1.setMaxElements(200);
133  generator1.setRowCuts(3);
134
135  CglGomory generator2;
136  // try larger limit
137  generator2.setLimit(300);
138
139  CglKnapsackCover generator3;
140
141  CglRedSplit generator4;
142  // try larger limit
143  generator4.setLimit(200);
144
145  CglClique generator5;
146  generator5.setStarCliqueReport(false);
147  generator5.setRowCliqueReport(false);
148
149  CglMixedIntegerRounding2 mixedGen;
150  CglFlowCover flowGen;
151 
152  // Add in generators
153  // Experiment with -1 and -99 etc
154  model.addCutGenerator(&generator1,-1,"Probing");
155  model.addCutGenerator(&generator2,-1,"Gomory");
156  model.addCutGenerator(&generator3,-1,"Knapsack");
157  // model.addCutGenerator(&generator4,-1,"RedSplit");
158  model.addCutGenerator(&generator5,-1,"Clique");
159  model.addCutGenerator(&flowGen,-1,"FlowCover");
160  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
161  // Say we want timings
162  int numberGenerators = model.numberCutGenerators();
163  int iGenerator;
164  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
165    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
166    generator->setTiming(true);
167  }
168  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
169  // go faster stripes
170  if (osiclp) {
171    // Turn this off if you get problems
172    // Used to be automatically set
173    osiclp->setSpecialOptions(128);
174    if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
175      //osiclp->setupForRepeatedUse(2,0);
176      osiclp->setupForRepeatedUse(0,0);
177    }
178  } 
179  // Uncommenting this should switch off all CBC messages
180  // model.messagesPointer()->setDetailMessages(10,10000,NULL);
181  // Allow rounding heuristic
182
183  CbcRounding heuristic1(model);
184  model.addHeuristic(&heuristic1);
185
186  // And local search when new solution found
187
188  CbcHeuristicLocal heuristic2(model);
189  model.addHeuristic(&heuristic2);
190
191  // Do initial solve to continuous
192  model.initialSolve();
193
194  // Could tune more
195  double objValue = model.solver()->getObjSense()*model.solver()->getObjValue();
196  double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4);
197  double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4;
198  printf("min drop %g (A %g)\n",minimumDrop,minimumDropA);
199  model.setMinimumDrop(minimumDrop);
200
201  if (model.getNumCols()<500)
202    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
203  else if (model.getNumCols()<5000)
204    model.setMaximumCutPassesAtRoot(100); // use minimum drop
205  else
206    model.setMaximumCutPassesAtRoot(20);
207  model.setMaximumCutPasses(10);
208  //model.setMaximumCutPasses(2);
209
210  /* This defines branching stuff.
211     The user can derive from OsiChoose to get required functionality
212  */
213  CbcBranchDefaultDecision decision;
214  // Need to find integers in Osi land
215  model.solver()->findIntegersAndSOS(false);
216  OsiChooseStrong choose(model.solver());
217  // Do more strong branching if small
218  if (model.getNumCols()<5000)
219    choose.setNumberStrong(10);
220  else
221    choose.setNumberStrong(5);
222  choose.setNumberBeforeTrusted(5);
223  //choose.setShadowPriceMode(0);
224  decision.setChooseMethod(choose);
225  model.setBranchingMethod(decision);
226
227  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);
228
229  // If time is given then stop after that number of minutes
230  if (minutes>=0.0) {
231    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
232    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
233  }
234  // Switch off most output
235  if (model.getNumCols()<3000) {
236    model.messageHandler()->setLogLevel(1);
237    //model.solver()->messageHandler()->setLogLevel(0);
238  } else {
239    model.messageHandler()->setLogLevel(2);
240    model.solver()->messageHandler()->setLogLevel(1);
241  }
242  //model.messageHandler()->setLogLevel(2);
243  //model.solver()->messageHandler()->setLogLevel(2);
244  //model.setPrintFrequency(50);
245  //#define DEBUG_CUTS
246#ifdef DEBUG_CUTS
247  // Set up debugger by name (only if no preprocesing)
248  if (!preProcess) {
249    std::string problemName ;
250    model.solver()->getStrParam(OsiProbName,problemName) ;
251    model.solver()->activateRowCutDebugger(problemName.c_str()) ;
252  }
253#endif
254  // Default strategy will leave cut generators as they exist already
255  // so cutsOnlyAtRoot (1) ignored
256  // numberStrong (2) is 5 (default)
257  // numberBeforeTrust (3) is 5 (default is 0)
258  // printLevel (4) defaults (0)
259  CbcStrategyDefault strategy(true,5,5);
260  // Set up pre-processing to find sos if wanted
261  if (preProcess)
262    strategy.setupPreProcessing(2);
263  model.setStrategy(strategy);
264  // Do complete search
265 
266  model.branchAndBound();
267
268  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
269           <<model.getNodeCount()<<" nodes with objective "
270           <<model.getObjValue()
271           <<(!model.status() ? " Finished" : " Not finished")
272           <<std::endl;
273
274  // Print more statistics
275  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
276           <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;
277
278  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
279    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
280    std::cout<<generator->cutGeneratorName()<<" was tried "
281             <<generator->numberTimesEntered()<<" times and created "
282             <<generator->numberCutsInTotal()<<" cuts of which "
283             <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
284    if (generator->timing())
285      std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
286    else
287      std::cout<<std::endl;
288  }
289  // Print solution if finished - we can't get names from Osi! - so get from OsiClp
290
291  if (model.getMinimizationObjValue()<1.0e50) {
292    OsiSolverInterface * solver = model.solver();
293    int numberColumns = solver->getNumCols();
294   
295    const double * solution = solver->getColSolution();
296
297    // Get names from solver1 (as OsiSolverInterface may lose)
298    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();
299   
300    int iColumn;
301    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
302   
303    std::cout<<"--------------------------------------"<<std::endl;
304    for (iColumn=0;iColumn<numberColumns;iColumn++) {
305      double value=solution[iColumn];
306      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) 
307        std::cout<<std::setw(6)<<iColumn<<" "
308                 <<columnNames[iColumn]<<" "
309                 <<value<<std::endl;
310    }
311    std::cout<<"--------------------------------------"<<std::endl;
312 
313    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
314  }
315  return 0;
316}   
Note: See TracBrowser for help on using the repository browser.