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

Last change on this file since 1468 was 1468, checked in by stefan, 9 years ago

do not require CbcConfig?.h in example to decide whether sample or miplib3 is present - do this in makefile

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