source: trunk/Samples/sample2.cpp @ 152

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

stuff

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.0 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#include "OsiClpSolverInterface.hpp"
20
21// Cuts
22
23#include "CglGomory.hpp"
24#include "CglProbing.hpp"
25#include "CglKnapsackCover.hpp"
26#include "CglOddHole.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  // Decided too slow
154  //CglOddHole generator4;
155  //generator4.setMinimumViolation(0.005);
156  //generator4.setMinimumViolationPer(0.00002);
157  // try larger limit
158  //generator4.setMaximumEntries(200);
159
160  CglClique generator5;
161  generator5.setStarCliqueReport(false);
162  generator5.setRowCliqueReport(false);
163
164  CglMixedIntegerRounding2 mixedGen;
165  CglFlowCover flowGen;
166 
167  // Add in generators
168  // Experiment with -1 and -99 etc
169  model.addCutGenerator(&generator1,-1,"Probing");
170  model.addCutGenerator(&generator2,-1,"Gomory");
171  model.addCutGenerator(&generator3,-1,"Knapsack");
172  //model.addCutGenerator(&generator4,-1,"OddHole");
173  model.addCutGenerator(&generator5,-1,"Clique");
174  model.addCutGenerator(&flowGen,-1,"FlowCover");
175  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
176  // Say we want timings
177  int numberGenerators = model.numberCutGenerators();
178  int iGenerator;
179  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
180    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
181    generator->setTiming(true);
182  }
183  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
184  // go faster stripes
185  if (osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
186    //osiclp->setupForRepeatedUse(2,0);
187    osiclp->setupForRepeatedUse(0,0);
188  } 
189  model.messagesPointer()->setDetailMessage(0,61);
190  // Allow rounding heuristic
191
192  CbcRounding heuristic1(model);
193  model.addHeuristic(&heuristic1);
194
195  // And local search when new solution found
196
197  CbcLocalSearch heuristic2(model);
198  model.addHeuristic(&heuristic2);
199
200  // Redundant definition of default branching (as Default == User)
201  CbcBranchUserDecision branch;
202  model.setBranchingMethod(&branch);
203
204  // Definition of node choice
205  CbcCompareUser compare;
206  model.setNodeComparison(compare);
207
208  // Do initial solve to continuous
209  model.initialSolve();
210
211  // Could tune more
212  double objValue = model.solver()->getObjSense()*model.solver()->getObjValue();
213  double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4);
214  double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4;
215  printf("min drop %g (A %g)\n",minimumDrop,minimumDropA);
216  model.setMinimumDrop(minimumDrop);
217
218  if (model.getNumCols()<500)
219    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
220  else if (model.getNumCols()<5000)
221    model.setMaximumCutPassesAtRoot(100); // use minimum drop
222  else
223    model.setMaximumCutPassesAtRoot(20);
224  model.setMaximumCutPasses(10);
225  //model.setMaximumCutPasses(2);
226
227  // Switch off strong branching if wanted
228  // model.setNumberStrong(0);
229  // Do more strong branching if small
230  if (model.getNumCols()<5000)
231    model.setNumberStrong(10);
232  model.setNumberStrong(20);
233
234  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);
235
236  // If time is given then stop after that number of minutes
237  if (minutes>=0.0) {
238    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
239    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
240  }
241  // Switch off most output
242  if (model.getNumCols()<3000) {
243    model.messageHandler()->setLogLevel(1);
244    //model.solver()->messageHandler()->setLogLevel(0);
245  } else {
246    model.messageHandler()->setLogLevel(2);
247    model.solver()->messageHandler()->setLogLevel(1);
248  }
249  //model.messageHandler()->setLogLevel(2);
250  //model.solver()->messageHandler()->setLogLevel(2);
251  //model.setPrintFrequency(50);
252  //#define DEBUG_CUTS
253#ifdef DEBUG_CUTS
254  // Set up debugger by name (only if no preprocesing)
255  if (!preProcess) {
256    std::string problemName ;
257    model.solver()->getStrParam(OsiProbName,problemName) ;
258    model.solver()->activateRowCutDebugger(problemName.c_str()) ;
259  }
260#endif
261
262  // Do complete search
263 
264  model.branchAndBound(3);
265
266  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
267           <<model.getNodeCount()<<" nodes with objective "
268           <<model.getObjValue()
269           <<(!model.status() ? " Finished" : " Not finished")
270           <<std::endl;
271
272  // Print more statistics
273  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
274           <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;
275
276  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
277    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
278    std::cout<<generator->cutGeneratorName()<<" was tried "
279             <<generator->numberTimesEntered()<<" times and created "
280             <<generator->numberCutsInTotal()<<" cuts of which "
281             <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
282    if (generator->timing())
283      std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
284    else
285      std::cout<<std::endl;
286  }
287  // Print solution if finished - we can't get names from Osi! - so get from OsiClp
288
289  if (model.getMinimizationObjValue()<1.0e50) {
290    // post process
291    OsiSolverInterface * solver;
292    if (preProcess) {
293      process.postProcess(*model.solver());
294      // Solution now back in solver1
295      solver = & solver1;
296    } else {
297      solver = model.solver();
298    }
299    int numberColumns = solver->getNumCols();
300   
301    const double * solution = solver->getColSolution();
302
303    // Get names from solver1 (as OsiSolverInterface may lose)
304    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();
305   
306    int iColumn;
307    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
308   
309    std::cout<<"--------------------------------------"<<std::endl;
310    for (iColumn=0;iColumn<numberColumns;iColumn++) {
311      double value=solution[iColumn];
312      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) 
313        std::cout<<std::setw(6)<<iColumn<<" "
314                 <<columnNames[iColumn]<<" "
315                 <<value<<std::endl;
316    }
317    std::cout<<"--------------------------------------"<<std::endl;
318 
319    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
320  }
321  return 0;
322}   
Note: See TracBrowser for help on using the repository browser.