source: trunk/Cbc/examples/sample2.cpp @ 333

Last change on this file since 333 was 333, checked in by andreasw, 13 years ago

finished examples subdir

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.7 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  model.addHeuristic(&heuristic1);
200
201  // And local search when new solution found
202
203  CbcHeuristicLocal heuristic2(model);
204  model.addHeuristic(&heuristic2);
205
206  // Redundant definition of default branching (as Default == User)
207  CbcBranchUserDecision branch;
208  model.setBranchingMethod(&branch);
209
210  // Definition of node choice
211  CbcCompareUser compare;
212  model.setNodeComparison(compare);
213
214  // Do initial solve to continuous
215  model.initialSolve();
216
217  // Could tune more
218  double objValue = model.solver()->getObjSense()*model.solver()->getObjValue();
219  double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4);
220  double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4;
221  printf("min drop %g (A %g)\n",minimumDrop,minimumDropA);
222  model.setMinimumDrop(minimumDrop);
223
224  if (model.getNumCols()<500)
225    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
226  else if (model.getNumCols()<5000)
227    model.setMaximumCutPassesAtRoot(100); // use minimum drop
228  else
229    model.setMaximumCutPassesAtRoot(20);
230  model.setMaximumCutPasses(10);
231  //model.setMaximumCutPasses(2);
232
233  // Switch off strong branching if wanted
234  // model.setNumberStrong(0);
235  // Do more strong branching if small
236  if (model.getNumCols()<5000)
237    model.setNumberStrong(10);
238  model.setNumberStrong(20);
239  //model.setNumberStrong(5);
240  model.setNumberBeforeTrust(5);
241
242  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);
243
244  // If time is given then stop after that number of minutes
245  if (minutes>=0.0) {
246    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
247    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
248  }
249  // Switch off most output
250  if (model.getNumCols()<3000) {
251    model.messageHandler()->setLogLevel(1);
252    //model.solver()->messageHandler()->setLogLevel(0);
253  } else {
254    model.messageHandler()->setLogLevel(2);
255    model.solver()->messageHandler()->setLogLevel(1);
256  }
257  //model.messageHandler()->setLogLevel(2);
258  //model.solver()->messageHandler()->setLogLevel(2);
259  //model.setPrintFrequency(50);
260  //#define DEBUG_CUTS
261#ifdef DEBUG_CUTS
262  // Set up debugger by name (only if no preprocesing)
263  if (!preProcess) {
264    std::string problemName ;
265    model.solver()->getStrParam(OsiProbName,problemName) ;
266    model.solver()->activateRowCutDebugger(problemName.c_str()) ;
267  }
268#endif
269#if PREPROCESS==2
270  // Default strategy will leave cut generators as they exist already
271  // so cutsOnlyAtRoot (1) ignored
272  // numberStrong (2) is 5 (default)
273  // numberBeforeTrust (3) is 5 (default is 0)
274  // printLevel (4) defaults (0)
275  CbcStrategyDefault strategy(true,5,5);
276  // Set up pre-processing to find sos if wanted
277  if (preProcess)
278    strategy.setupPreProcessing(2);
279  model.setStrategy(strategy);
280#endif
281  // Do complete search
282 
283  model.branchAndBound();
284
285  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
286           <<model.getNodeCount()<<" nodes with objective "
287           <<model.getObjValue()
288           <<(!model.status() ? " Finished" : " Not finished")
289           <<std::endl;
290
291  // Print more statistics
292  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
293           <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;
294
295  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
296    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
297    std::cout<<generator->cutGeneratorName()<<" was tried "
298             <<generator->numberTimesEntered()<<" times and created "
299             <<generator->numberCutsInTotal()<<" cuts of which "
300             <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
301    if (generator->timing())
302      std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
303    else
304      std::cout<<std::endl;
305  }
306  // Print solution if finished - we can't get names from Osi! - so get from OsiClp
307
308  if (model.getMinimizationObjValue()<1.0e50) {
309#if PREPROCESS==1
310    // post process
311    OsiSolverInterface * solver;
312    if (preProcess) {
313      process.postProcess(*model.solver());
314      // Solution now back in solver1
315      solver = & solver1;
316    } else {
317      solver = model.solver();
318    }
319#else
320    OsiSolverInterface * solver = model.solver();
321#endif
322    int numberColumns = solver->getNumCols();
323   
324    const double * solution = solver->getColSolution();
325
326    // Get names from solver1 (as OsiSolverInterface may lose)
327    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();
328   
329    int iColumn;
330    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
331   
332    std::cout<<"--------------------------------------"<<std::endl;
333    for (iColumn=0;iColumn<numberColumns;iColumn++) {
334      double value=solution[iColumn];
335      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) 
336        std::cout<<std::setw(6)<<iColumn<<" "
337                 <<columnNames[iColumn]<<" "
338                 <<value<<std::endl;
339    }
340    std::cout<<"--------------------------------------"<<std::endl;
341 
342    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
343  }
344  return 0;
345}   
Note: See TracBrowser for help on using the repository browser.