source: trunk/Samples/sample2.cpp @ 80

Last change on this file since 80 was 80, checked in by forrest, 17 years ago

out error if no parameters

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 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 "CbcHeuristicUser.hpp"
19#ifdef COIN_USE_CLP
20#include "OsiClpSolverInterface.hpp"
21#endif
22#ifdef COIN_USE_OSL
23#include "OsiOslSolverInterface.hpp"
24#endif
25
26// Cuts
27
28#include "CglGomory.hpp"
29#include "CglProbing.hpp"
30#include "CglKnapsackCover.hpp"
31#include "CglOddHole.hpp"
32#include "CglClique.hpp"
33#include "CglFlowCover.hpp"
34#include "CglMixedIntegerRounding.hpp"
35// Preprocessing
36#include "CglPreProcess.hpp"
37
38// Heuristics
39
40#include "CbcHeuristic.hpp"
41
42#include  "CoinTime.hpp"
43
44//#############################################################################
45
46
47/************************************************************************
48
49This main program reads in an integer model from an mps file.
50
51It then sets up some Cgl cut generators and calls branch and cut.
52
53Branching is simple binary branching on integer variables.
54
55Node selection is depth first until first solution is found and then
56based on objective and number of unsatisfied integer variables.
57In this example the functionality is the same as default but it is
58a user comparison function.
59
60Variable branching selection is on maximum minimum-of-up-down change
61after strong branching on 5 variables closest to 0.5.
62
63A simple rounding heuristic is used.
64
65
66************************************************************************/
67
68// ****** define comparison to choose best next node
69
70int main (int argc, const char *argv[])
71{
72
73  // Define your favorite OsiSolver
74 
75#ifdef COIN_USE_CLP
76  OsiClpSolverInterface solver1;
77#elif COIN_USE_OSL
78  OsiOslSolverInterface solver1;
79#endif
80
81  // Read in model using argv[1]
82  // and assert that it is a clean model
83  std::string mpsFileName = "../../Mps/Sample/p0033.mps";
84  if (argc>=2) mpsFileName = argv[1];
85  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
86  assert(numMpsReadErrors==0);
87  double time1 = CoinCpuTime();
88
89  /* Options are:
90     preprocess to do preprocessing
91     time in minutes
92     if 2 parameters and numeric taken as time
93  */
94  bool preProcess=false;
95  double minutes=-1.0;
96  int nGoodParam=0;
97  for (int iParam=2; iParam<argc;iParam++) {
98    if (!strcmp(argv[iParam],"preprocess")) {
99      preProcess=true;
100      nGoodParam++;
101    } else if (!strcmp(argv[iParam],"time")) {
102      if (iParam+1<argc&&isdigit(argv[iParam+1][0])) {
103        minutes=atof(argv[iParam+1]);
104        if (minutes>=0.0) {
105          nGoodParam+=2;
106          iParam++; // skip time
107        }
108      }
109    }
110  }
111  if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) {
112    // If time is given then stop after that number of minutes
113    minutes = atof(argv[2]);
114    if (minutes>=0.0) 
115      nGoodParam=1;
116  }
117  if (nGoodParam!=argc-2&&argc>=2) {
118    printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n");
119    exit(1);
120  }
121  solver1.initialSolve();
122  // Reduce printout
123  solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
124  // See if we want preprocessing
125  OsiSolverInterface * solver2=&solver1;
126  CglPreProcess process;
127  if (preProcess) {
128    /* Do not try and produce equality cliques and
129       do up to 5 passes */
130    solver2 = process.preProcess(solver1,false,5);
131    if (!solver2) {
132      printf("Pre-processing says infeasible\n");
133      exit(2);
134    }
135    solver2->resolve();
136  }
137  CbcModel model(*solver2);
138  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
139  // Set up some cut generators and defaults
140  // Probing first as gets tight bounds on continuous
141
142  CglProbing generator1;
143  generator1.setUsingObjective(true);
144  generator1.setMaxPass(3);
145  // Number of unsatisfied variables to look at
146  generator1.setMaxProbe(10);
147  // How far to follow the consequences
148  generator1.setMaxLook(50);
149  // Only look at rows with fewer than this number of elements
150  generator1.setMaxElements(200);
151  generator1.setRowCuts(3);
152
153  CglGomory generator2;
154  // try larger limit
155  generator2.setLimit(300);
156
157  CglKnapsackCover generator3;
158
159  CglOddHole generator4;
160  generator4.setMinimumViolation(0.005);
161  generator4.setMinimumViolationPer(0.00002);
162  // try larger limit
163  generator4.setMaximumEntries(200);
164
165  CglClique generator5;
166  generator5.setStarCliqueReport(false);
167  generator5.setRowCliqueReport(false);
168
169  CglMixedIntegerRounding mixedGen;
170  CglFlowCover flowGen;
171 
172  // Add in generators
173  // Experiment with -1 and -99 etc
174  model.addCutGenerator(&generator1,-1,"Probing");
175  model.addCutGenerator(&generator2,-1,"Gomory");
176  model.addCutGenerator(&generator3,-1,"Knapsack");
177  model.addCutGenerator(&generator4,-1,"OddHole");
178  model.addCutGenerator(&generator5,-1,"Clique");
179  model.addCutGenerator(&flowGen,-1,"FlowCover");
180  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
181  // Say we want timings
182  int numberGenerators = model.numberCutGenerators();
183  int iGenerator;
184  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
185    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
186    generator->setTiming(true);
187  }
188#ifdef COIN_USE_CLP
189  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
190  // go faster stripes
191  if (osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
192    osiclp->setupForRepeatedUse(2,0);
193    printf("trying slightly less reliable but faster version (? Gomory cuts okay?)\n");
194    printf("may not be safe if doing cuts in tree which need accuracy (level 2 anyway)\n");
195  }
196#endif
197
198  // Allow rounding heuristic
199
200  CbcRounding heuristic1(model);
201  model.addHeuristic(&heuristic1);
202
203  // And local search when new solution found
204
205  CbcLocalSearch heuristic2(model);
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  model.setMinimumDrop(min(1.0,
221                             fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4));
222
223  if (model.getNumCols()<500)
224    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
225  else if (model.getNumCols()<5000)
226    model.setMaximumCutPassesAtRoot(100); // use minimum drop
227  else
228    model.setMaximumCutPassesAtRoot(20);
229  //model.setMaximumCutPasses(5);
230
231  // Switch off strong branching if wanted
232  // model.setNumberStrong(0);
233  // Do more strong branching if small
234  if (model.getNumCols()<5000)
235    model.setNumberStrong(10);
236
237  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);
238
239  // If time is given then stop after that number of minutes
240  if (minutes>=0.0) {
241    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
242    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
243  }
244  // Switch off most output
245  if (model.getNumCols()<3000) {
246    model.messageHandler()->setLogLevel(1);
247    //model.solver()->messageHandler()->setLogLevel(0);
248  } else {
249    model.messageHandler()->setLogLevel(2);
250    model.solver()->messageHandler()->setLogLevel(1);
251  }
252  //model.messageHandler()->setLogLevel(2);
253  //model.solver()->messageHandler()->setLogLevel(2);
254  //model.setPrintFrequency(50);
255#ifdef DEBUG_CUTS
256  // Set up debugger by name (only if no preprocesing)
257  if (!preProcess) {
258    std::string problemName ;
259    model.solver()->getStrParam(OsiProbName,problemName) ;
260    model.solver()->activateRowCutDebugger(problemName.c_str()) ;
261  }
262#endif
263
264  // Do complete search
265 
266  model.branchAndBound();
267
268  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
269           <<model.getNodeCount()<<" nodes with objective "
270           <<model.getObjValue()
271           <<(!model.status() ? " Finished" : " Not finished")
272           <<std::endl;
273
274  // Print more statistics
275  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
276           <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;
277
278  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
279    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
280    std::cout<<generator->cutGeneratorName()<<" was tried "
281             <<generator->numberTimesEntered()<<" times and created "
282             <<generator->numberCutsInTotal()<<" cuts of which "
283             <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
284    if (generator->timing())
285      std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
286    else
287      std::cout<<std::endl;
288  }
289  // Print solution if finished - we can't get names from Osi!
290
291  if (model.getMinimizationObjValue()<1.0e50) {
292    // post process
293    if (preProcess)
294      process.postProcess(*model.solver());
295    int numberColumns = model.solver()->getNumCols();
296   
297    const double * solution = model.solver()->getColSolution();
298   
299    int iColumn;
300    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
301   
302    std::cout<<"--------------------------------------"<<std::endl;
303    for (iColumn=0;iColumn<numberColumns;iColumn++) {
304      double value=solution[iColumn];
305      if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) 
306        std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl;
307    }
308    std::cout<<"--------------------------------------"<<std::endl;
309 
310    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
311  }
312  return 0;
313}   
Note: See TracBrowser for help on using the repository browser.