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

Last change on this file since 1565 was 1549, checked in by lou, 9 years ago

Make Visual Studio v9 build work again.

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