source: trunk/Samples/sample2.cpp @ 184

Last change on this file since 184 was 184, checked in by forrest, 16 years ago

change misleading detailmessages

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