source: trunk/Cbc/examples/sample2.cpp

Last change on this file was 1898, checked in by stefan, 5 years ago

fixup examples

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