source: branches/sandbox/Cbc/examples/sample2.cpp @ 1335

Last change on this file since 1335 was 1335, checked in by bjarni, 10 years ago

Check CoinFindSeparator? and set Windows directory to ..\..\..\..\Data\Sample

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