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

Last change on this file since 1898 was 1898, checked in by stefan, 5 years ago

fixup examples

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