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

Last change on this file since 1565 was 1468, checked in by stefan, 9 years ago

do not require CbcConfig?.h in example to decide whether sample or miplib3 is present - do this in makefile

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
Line 
1// Copyright (C) 2005, 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 "CbcStrategy.hpp"
16#include "CbcBranchUser.hpp"
17#include "CbcCompareUser.hpp"
18#include "CbcCutGenerator.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
48Then it uses solution as hot start
49
50************************************************************************/
51
52
53int main (int argc, const char *argv[])
54{
55
56  // Define your favorite OsiSolver
57 
58  OsiClpSolverInterface solver1;
59
60  // Read in model using argv[1]
61  // and assert that it is a clean model
62  std::string mpsFileName;
63#if defined(SAMPLEDIR)
64  mpsFileName = SAMPLEDIR "/p0033.mps";
65#else
66  if (argc < 2) {
67    fprintf(stderr, "Do not know where to find sample MPS files.\n");
68    exit(1);
69  }
70#endif
71  if (argc>=2) mpsFileName = argv[1];
72  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
73  assert(numMpsReadErrors==0);
74  double time1 = CoinCpuTime();
75
76  /* Options are:
77     preprocess to do preprocessing
78     time in minutes
79     if 2 parameters and numeric taken as time
80  */
81  bool preProcess=false;
82  double minutes=-1.0;
83  int nGoodParam=0;
84  for (int iParam=2; iParam<argc;iParam++) {
85    if (!strcmp(argv[iParam],"preprocess")) {
86      preProcess=true;
87      nGoodParam++;
88    } else if (!strcmp(argv[iParam],"time")) {
89      if (iParam+1<argc&&isdigit(argv[iParam+1][0])) {
90        minutes=atof(argv[iParam+1]);
91        if (minutes>=0.0) {
92          nGoodParam+=2;
93          iParam++; // skip time
94        }
95      }
96    }
97  }
98  if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) {
99    // If time is given then stop after that number of minutes
100    minutes = atof(argv[2]);
101    if (minutes>=0.0) 
102      nGoodParam=1;
103  }
104  if (nGoodParam!=argc-2&&argc>=2) {
105    printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n");
106    exit(1);
107  }
108  //solver1.getModelPtr()->setLogLevel(0);
109  solver1.messageHandler()->setLogLevel(0);
110  solver1.initialSolve();
111  // Reduce printout
112  solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
113  CbcModel model(solver1);
114  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
115  // Set up some cut generators and defaults
116  // Probing first as gets tight bounds on continuous
117
118  CglProbing generator1;
119  generator1.setUsingObjective(true);
120  generator1.setMaxPass(1);
121  generator1.setMaxPassRoot(5);
122  // Number of unsatisfied variables to look at
123  generator1.setMaxProbe(10);
124  generator1.setMaxProbeRoot(1000);
125  // How far to follow the consequences
126  generator1.setMaxLook(50);
127  generator1.setMaxLookRoot(500);
128  // Only look at rows with fewer than this number of elements
129  generator1.setMaxElements(200);
130  generator1.setRowCuts(3);
131
132  CglGomory generator2;
133  // try larger limit
134  generator2.setLimit(300);
135
136  CglKnapsackCover generator3;
137
138  CglRedSplit generator4;
139  // try larger limit
140  generator4.setLimit(200);
141
142  CglClique generator5;
143  generator5.setStarCliqueReport(false);
144  generator5.setRowCliqueReport(false);
145
146  CglMixedIntegerRounding2 mixedGen;
147  CglFlowCover flowGen;
148 
149  // Add in generators
150  // Experiment with -1 and -99 etc
151  model.addCutGenerator(&generator1,-1,"Probing");
152  model.addCutGenerator(&generator2,-1,"Gomory");
153  model.addCutGenerator(&generator3,-1,"Knapsack");
154  // model.addCutGenerator(&generator4,-1,"RedSplit");
155  model.addCutGenerator(&generator5,-1,"Clique");
156  model.addCutGenerator(&flowGen,-1,"FlowCover");
157  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
158  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
159  // go faster stripes
160  if (osiclp) {
161    // Turn this off if you get problems
162    // Used to be automatically set
163    osiclp->setSpecialOptions(128);
164    if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
165      //osiclp->setupForRepeatedUse(2,1);
166      osiclp->setupForRepeatedUse(0,1);
167    }
168  } 
169  // Uncommenting this should switch off most CBC messages
170  //model.messagesPointer()->setDetailMessages(10,5,5000);
171  // Allow rounding heuristic
172
173  CbcRounding heuristic1(model);
174  model.addHeuristic(&heuristic1);
175
176  // Redundant definition of default branching (as Default == User)
177  CbcBranchUserDecision branch;
178  model.setBranchingMethod(&branch);
179
180  // Definition of node choice
181  CbcCompareUser compare;
182  model.setNodeComparison(compare);
183
184  // Do initial solve to continuous
185  model.initialSolve();
186
187  // Could tune more
188  double objValue = model.solver()->getObjSense()*model.solver()->getObjValue();
189  double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4);
190  double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4;
191  printf("min drop %g (A %g)\n",minimumDrop,minimumDropA);
192  model.setMinimumDrop(minimumDrop);
193
194  if (model.getNumCols()<500)
195    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
196  else if (model.getNumCols()<5000)
197    model.setMaximumCutPassesAtRoot(100); // use minimum drop
198  else
199    model.setMaximumCutPassesAtRoot(20);
200  model.setMaximumCutPasses(10);
201  //model.setMaximumCutPasses(2);
202
203  // Switch off strong branching if wanted
204  // model.setNumberStrong(0);
205  // Do more strong branching if small
206  if (model.getNumCols()<5000)
207    model.setNumberStrong(10);
208  model.setNumberStrong(20);
209  //model.setNumberStrong(5);
210  model.setNumberBeforeTrust(5);
211  //model.setSizeMiniTree(2);
212
213  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);
214
215  // Switch off most output
216  if (model.getNumCols()<3000) {
217    model.messageHandler()->setLogLevel(1);
218    //model.solver()->messageHandler()->setLogLevel(0);
219  } else {
220    model.messageHandler()->setLogLevel(2);
221    model.solver()->messageHandler()->setLogLevel(1);
222  }
223  model.messageHandler()->setLogLevel(6);
224  model.solver()->messageHandler()->setLogLevel(1);
225  // If time is given then stop after that number of minutes
226  if (minutes>=0.0) {
227    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
228    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
229  }
230  // Default strategy will leave cut generators as they exist already
231  // so cutsOnlyAtRoot (1) ignored
232  // numberStrong (2) is 5 (default)
233  // numberBeforeTrust (3) is 5 (default is 0)
234  // printLevel (4) defaults (0)
235  CbcStrategyDefault strategy(true,5,5);
236  // Set up pre-processing to find sos if wanted
237  if (preProcess)
238    strategy.setupPreProcessing(2);
239  model.setStrategy(strategy);
240  int numberColumns = model.solver()->getNumCols();
241  double * bestSolution=NULL;
242  int * priority = new int[numberColumns];
243  // Do two passes
244  for (int iPass=0;iPass<2;iPass++) {
245    time1 = CoinCpuTime();
246    // Do hot start on second pass
247    if (bestSolution) {
248      model.setHotstartSolution(bestSolution,priority);
249      delete [] bestSolution;
250      bestSolution=NULL;
251      delete [] priority;
252      model.setMaximumNodes(40000);
253    } else {
254      model.setMaximumNodes(40000);
255    }
256    // Do complete search
257    model.branchAndBound();
258   
259    std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
260             <<model.getNodeCount()<<" nodes with objective "
261             <<model.getObjValue()
262             <<(!model.status() ? " Finished" : " Not finished")
263             <<std::endl;
264    // Print solution if finished - we can't get names from Osi! - so get from OsiClp
265   
266    assert (model.getMinimizationObjValue()<1.0e50);
267    OsiSolverInterface * solver = model.solver();
268    int numberColumns = solver->getNumCols();
269   
270    const double * solution = solver->getColSolution();
271    // save solution
272    if (!iPass) {
273      bestSolution = CoinCopyOfArray(solution,numberColumns);
274      for (int i=0;i<numberColumns;i++) {
275        if (solution[i]>0.5)
276          priority[i]=-1;
277        else
278          priority[i]=2;
279      }
280    }
281    //const double * lower = solver->getColLower();
282    //const double * upper = solver->getColUpper();
283
284    // Get names from solver1 (as OsiSolverInterface may lose)
285    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();
286   
287    int iColumn;
288    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
289   
290    std::cout<<"--------------------------------------"<<std::endl;
291    for (iColumn=0;iColumn<numberColumns;iColumn++) {
292      double value=solution[iColumn];
293      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) 
294        std::cout<<std::setw(6)<<iColumn<<" "
295                 <<columnNames[iColumn]<<" "
296                 <<value
297          //<<" "<<lower[iColumn]<<" "<<upper[iColumn]
298                 <<std::endl;
299    }
300    std::cout<<"--------------------------------------"<<std::endl;
301 
302    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
303    model.resetToReferenceSolver();
304  }
305  return 0;
306}   
Note: See TracBrowser for help on using the repository browser.