source: branches/devel/Cbc/examples/sample2.cpp

Last change on this file was 655, checked in by forrest, 13 years ago

add heuristic names

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.8 KB
Line 
1// Copyright (C) 2002, 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 "CbcBranchUser.hpp"
16#include "CbcCompareUser.hpp"
17#include "CbcCutGenerator.hpp"
18#include "CbcStrategy.hpp"
19#include "CbcHeuristicLocal.hpp"
20#include "OsiClpSolverInterface.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
61Preprocessing may be selected in two ways - the second is preferred now
62
63************************************************************************/
64#define PREPROCESS 2
65
66int main (int argc, const char *argv[])
67{
68
69  // Define your favorite OsiSolver
70 
71  OsiClpSolverInterface solver1;
72
73  // Read in model using argv[1]
74  // and assert that it is a clean model
75  std::string mpsFileName = "../../Data/Sample/p0033.mps";
76  if (argc>=2) mpsFileName = argv[1];
77  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
78  assert(numMpsReadErrors==0);
79  double time1 = CoinCpuTime();
80
81  /* Options are:
82     preprocess to do preprocessing
83     time in minutes
84     if 2 parameters and numeric taken as time
85  */
86  bool preProcess=false;
87  double minutes=-1.0;
88  int nGoodParam=0;
89  for (int iParam=2; iParam<argc;iParam++) {
90    if (!strcmp(argv[iParam],"preprocess")) {
91      preProcess=true;
92      nGoodParam++;
93    } else if (!strcmp(argv[iParam],"time")) {
94      if (iParam+1<argc&&isdigit(argv[iParam+1][0])) {
95        minutes=atof(argv[iParam+1]);
96        if (minutes>=0.0) {
97          nGoodParam+=2;
98          iParam++; // skip time
99        }
100      }
101    }
102  }
103  if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) {
104    // If time is given then stop after that number of minutes
105    minutes = atof(argv[2]);
106    if (minutes>=0.0) 
107      nGoodParam=1;
108  }
109  if (nGoodParam!=argc-2&&argc>=2) {
110    printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n");
111    exit(1);
112  }
113  solver1.initialSolve();
114  // Reduce printout
115  solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
116  // See if we want preprocessing
117  OsiSolverInterface * solver2=&solver1;
118#if PREPROCESS==1
119  CglPreProcess process;
120  if (preProcess) {
121    /* Do not try and produce equality cliques and
122       do up to 5 passes */
123    solver2 = process.preProcess(solver1,false,5);
124    if (!solver2) {
125      printf("Pre-processing says infeasible\n");
126      exit(2);
127    }
128    solver2->resolve();
129  }
130#endif
131  CbcModel model(*solver2);
132  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
133  // Set up some cut generators and defaults
134  // Probing first as gets tight bounds on continuous
135
136  CglProbing generator1;
137  generator1.setUsingObjective(true);
138  generator1.setMaxPass(1);
139  generator1.setMaxPassRoot(5);
140  // Number of unsatisfied variables to look at
141  generator1.setMaxProbe(10);
142  generator1.setMaxProbeRoot(1000);
143  // How far to follow the consequences
144  generator1.setMaxLook(50);
145  generator1.setMaxLookRoot(500);
146  // Only look at rows with fewer than this number of elements
147  generator1.setMaxElements(200);
148  generator1.setRowCuts(3);
149
150  CglGomory generator2;
151  // try larger limit
152  generator2.setLimit(300);
153
154  CglKnapsackCover generator3;
155
156  CglRedSplit generator4;
157  // try larger limit
158  generator4.setLimit(200);
159
160  CglClique generator5;
161  generator5.setStarCliqueReport(false);
162  generator5.setRowCliqueReport(false);
163
164  CglMixedIntegerRounding2 mixedGen;
165  CglFlowCover flowGen;
166 
167  // Add in generators
168  // Experiment with -1 and -99 etc
169  model.addCutGenerator(&generator1,-1,"Probing");
170  model.addCutGenerator(&generator2,-1,"Gomory");
171  model.addCutGenerator(&generator3,-1,"Knapsack");
172  // model.addCutGenerator(&generator4,-1,"RedSplit");
173  model.addCutGenerator(&generator5,-1,"Clique");
174  model.addCutGenerator(&flowGen,-1,"FlowCover");
175  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
176  // Say we want timings
177  int numberGenerators = model.numberCutGenerators();
178  int iGenerator;
179  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
180    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
181    generator->setTiming(true);
182  }
183  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
184  // go faster stripes
185  if (osiclp) {
186    // Turn this off if you get problems
187    // Used to be automatically set
188    osiclp->setSpecialOptions(128);
189    if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
190      //osiclp->setupForRepeatedUse(2,0);
191      osiclp->setupForRepeatedUse(0,0);
192    }
193  } 
194  // Uncommenting this should switch off all CBC messages
195  // model.messagesPointer()->setDetailMessages(10,10000,NULL);
196  // Allow rounding heuristic
197
198  CbcRounding heuristic1(model);
199  heuristic1.setHeuristicName("rounding");
200  model.addHeuristic(&heuristic1);
201
202  // And local search when new solution found
203
204  CbcHeuristicLocal heuristic2(model);
205  heuristic2.setHeuristicName("join solutions");
206  model.addHeuristic(&heuristic2);
207
208  // Redundant definition of default branching (as Default == User)
209  CbcBranchUserDecision branch;
210  model.setBranchingMethod(&branch);
211
212  // Definition of node choice
213  CbcCompareUser compare;
214  model.setNodeComparison(compare);
215
216  // Do initial solve to continuous
217  model.initialSolve();
218
219  // Could tune more
220  double objValue = model.solver()->getObjSense()*model.solver()->getObjValue();
221  double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4);
222  double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4;
223  printf("min drop %g (A %g)\n",minimumDrop,minimumDropA);
224  model.setMinimumDrop(minimumDrop);
225
226  if (model.getNumCols()<500)
227    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
228  else if (model.getNumCols()<5000)
229    model.setMaximumCutPassesAtRoot(100); // use minimum drop
230  else
231    model.setMaximumCutPassesAtRoot(20);
232  model.setMaximumCutPasses(10);
233  //model.setMaximumCutPasses(2);
234
235  // Switch off strong branching if wanted
236  // model.setNumberStrong(0);
237  // Do more strong branching if small
238  if (model.getNumCols()<5000)
239    model.setNumberStrong(10);
240  model.setNumberStrong(20);
241  //model.setNumberStrong(5);
242  model.setNumberBeforeTrust(5);
243
244  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);
245
246  // If time is given then stop after that number of minutes
247  if (minutes>=0.0) {
248    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
249    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
250  }
251  // Switch off most output
252  if (model.getNumCols()<3000) {
253    model.messageHandler()->setLogLevel(1);
254    //model.solver()->messageHandler()->setLogLevel(0);
255  } else {
256    model.messageHandler()->setLogLevel(2);
257    model.solver()->messageHandler()->setLogLevel(1);
258  }
259  //model.messageHandler()->setLogLevel(2);
260  //model.solver()->messageHandler()->setLogLevel(2);
261  //model.setPrintFrequency(50);
262  //#define DEBUG_CUTS
263#ifdef DEBUG_CUTS
264  // Set up debugger by name (only if no preprocesing)
265  if (!preProcess) {
266    std::string problemName ;
267    model.solver()->getStrParam(OsiProbName,problemName) ;
268    model.solver()->activateRowCutDebugger(problemName.c_str()) ;
269  }
270#endif
271#if PREPROCESS==2
272  // Default strategy will leave cut generators as they exist already
273  // so cutsOnlyAtRoot (1) ignored
274  // numberStrong (2) is 5 (default)
275  // numberBeforeTrust (3) is 5 (default is 0)
276  // printLevel (4) defaults (0)
277  CbcStrategyDefault strategy(true,5,5);
278  // Set up pre-processing to find sos if wanted
279  if (preProcess)
280    strategy.setupPreProcessing(2);
281  model.setStrategy(strategy);
282#endif
283  // Do complete search
284 
285  model.branchAndBound();
286
287  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
288           <<model.getNodeCount()<<" nodes with objective "
289           <<model.getObjValue()
290           <<(!model.status() ? " Finished" : " Not finished")
291           <<std::endl;
292
293  // Print more statistics
294  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
295           <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;
296
297  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
298    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
299    std::cout<<generator->cutGeneratorName()<<" was tried "
300             <<generator->numberTimesEntered()<<" times and created "
301             <<generator->numberCutsInTotal()<<" cuts of which "
302             <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
303    if (generator->timing())
304      std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
305    else
306      std::cout<<std::endl;
307  }
308  // Print solution if finished - we can't get names from Osi! - so get from OsiClp
309
310  if (model.getMinimizationObjValue()<1.0e50) {
311#if PREPROCESS==1
312    // post process
313    OsiSolverInterface * solver;
314    if (preProcess) {
315      process.postProcess(*model.solver());
316      // Solution now back in solver1
317      solver = & solver1;
318    } else {
319      solver = model.solver();
320    }
321#else
322    OsiSolverInterface * solver = model.solver();
323#endif
324    int numberColumns = solver->getNumCols();
325   
326    const double * solution = solver->getColSolution();
327
328    // Get names from solver1 (as OsiSolverInterface may lose)
329    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();
330   
331    int iColumn;
332    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
333   
334    std::cout<<"--------------------------------------"<<std::endl;
335    for (iColumn=0;iColumn<numberColumns;iColumn++) {
336      double value=solution[iColumn];
337      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) 
338        std::cout<<std::setw(6)<<iColumn<<" "
339                 <<columnNames[iColumn]<<" "
340                 <<value<<std::endl;
341    }
342    std::cout<<"--------------------------------------"<<std::endl;
343 
344    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
345  }
346  return 0;
347}   
Note: See TracBrowser for help on using the repository browser.