source: trunk/Cbc/examples/repeat.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: 10.3 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 "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
49This is designed to show two things :-
50
511) Use of CbcStrategy to do preprocessing - this should be cleaner than old way
522) Looping round modifying solver and redoing branch and cut.  This uses resetToReferenceCopy
53   which resets stuff like the cutoff and any memory of previous branch and cut.
54
55************************************************************************/
56
57
58int main (int argc, const char *argv[])
59{
60
61  // Define your favorite OsiSolver
62 
63  OsiClpSolverInterface solver1;
64
65  // Read in model using argv[1]
66  // and assert that it is a clean model
67  std::string mpsFileName;
68#if defined(SAMPLEDIR)
69  mpsFileName = SAMPLEDIR "/p0033.mps";
70#else
71  if (argc < 2) {
72    fprintf(stderr, "Do not know where to find sample MPS files.\n");
73    exit(1);
74  }
75#endif
76  if (argc>=2) mpsFileName = argv[1];
77  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
78  assert(numMpsReadErrors==0);
79  double time1 = CoinCpuTime();
80
81  /* Options are:
82     preprocess to do preprocessing
83     time in minutes
84     if 2 parameters and numeric taken as time
85  */
86  bool preProcess=false;
87  double minutes=-1.0;
88  int nGoodParam=0;
89  for (int iParam=2; iParam<argc;iParam++) {
90    if (!strcmp(argv[iParam],"preprocess")) {
91      preProcess=true;
92      nGoodParam++;
93    } else if (!strcmp(argv[iParam],"time")) {
94      if (iParam+1<argc&&isdigit(argv[iParam+1][0])) {
95        minutes=atof(argv[iParam+1]);
96        if (minutes>=0.0) {
97          nGoodParam+=2;
98          iParam++; // skip time
99        }
100      }
101    }
102  }
103  if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) {
104    // If time is given then stop after that number of minutes
105    minutes = atof(argv[2]);
106    if (minutes>=0.0) 
107      nGoodParam=1;
108  }
109  if (nGoodParam!=argc-2&&argc>=2) {
110    printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n");
111    exit(1);
112  }
113  //solver1.getModelPtr()->setLogLevel(0);
114  solver1.messageHandler()->setLogLevel(0);
115  solver1.initialSolve();
116  // Reduce printout
117  solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
118  CbcModel model(solver1);
119  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
120  // Set up some cut generators and defaults
121  // Probing first as gets tight bounds on continuous
122
123  CglProbing generator1;
124  generator1.setUsingObjective(true);
125  generator1.setMaxPass(1);
126  generator1.setMaxPassRoot(5);
127  // Number of unsatisfied variables to look at
128  generator1.setMaxProbe(10);
129  generator1.setMaxProbeRoot(1000);
130  // How far to follow the consequences
131  generator1.setMaxLook(50);
132  generator1.setMaxLookRoot(500);
133  // Only look at rows with fewer than this number of elements
134  generator1.setMaxElements(200);
135  generator1.setRowCuts(3);
136
137  CglGomory generator2;
138  // try larger limit
139  generator2.setLimit(300);
140
141  CglKnapsackCover generator3;
142
143  CglRedSplit generator4;
144  // try larger limit
145  generator4.setLimit(200);
146
147  CglClique generator5;
148  generator5.setStarCliqueReport(false);
149  generator5.setRowCliqueReport(false);
150
151  CglMixedIntegerRounding2 mixedGen;
152  CglFlowCover flowGen;
153 
154  // Add in generators
155  // Experiment with -1 and -99 etc
156  model.addCutGenerator(&generator1,-1,"Probing");
157  model.addCutGenerator(&generator2,-1,"Gomory");
158  model.addCutGenerator(&generator3,-1,"Knapsack");
159  // model.addCutGenerator(&generator4,-1,"RedSplit");
160  model.addCutGenerator(&generator5,-1,"Clique");
161  model.addCutGenerator(&flowGen,-1,"FlowCover");
162  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
163  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
164  // go faster stripes
165  if (osiclp) {
166    // Turn this off if you get problems
167    // Used to be automatically set
168    osiclp->setSpecialOptions(128);
169    if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
170      //osiclp->setupForRepeatedUse(2,1);
171      osiclp->setupForRepeatedUse(0,1);
172    }
173  } 
174  // Uncommenting this should switch off most CBC messages
175  //model.messagesPointer()->setDetailMessages(10,5,5000);
176  // Allow rounding heuristic
177
178  CbcRounding heuristic1(model);
179  model.addHeuristic(&heuristic1);
180
181  // And local search when new solution found
182
183  CbcHeuristicLocal heuristic2(model);
184  model.addHeuristic(&heuristic2);
185
186  // Redundant definition of default branching (as Default == User)
187  CbcBranchUserDecision branch;
188  model.setBranchingMethod(&branch);
189
190  // Definition of node choice
191  CbcCompareUser compare;
192  model.setNodeComparison(compare);
193
194  // Do initial solve to continuous
195  model.initialSolve();
196
197  // Could tune more
198  double objValue = model.solver()->getObjSense()*model.solver()->getObjValue();
199  double minimumDropA=CoinMin(1.0,fabs(objValue)*1.0e-3+1.0e-4);
200  double minimumDrop= fabs(objValue)*1.0e-4+1.0e-4;
201  printf("min drop %g (A %g)\n",minimumDrop,minimumDropA);
202  model.setMinimumDrop(minimumDrop);
203
204  if (model.getNumCols()<500)
205    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
206  else if (model.getNumCols()<5000)
207    model.setMaximumCutPassesAtRoot(100); // use minimum drop
208  else
209    model.setMaximumCutPassesAtRoot(20);
210  model.setMaximumCutPasses(10);
211  //model.setMaximumCutPasses(2);
212
213  // Switch off strong branching if wanted
214  // model.setNumberStrong(0);
215  // Do more strong branching if small
216  if (model.getNumCols()<5000)
217    model.setNumberStrong(10);
218  model.setNumberStrong(20);
219  //model.setNumberStrong(5);
220  model.setNumberBeforeTrust(5);
221  //model.setSizeMiniTree(2);
222
223  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);
224
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  // Switch off most output
231  if (model.getNumCols()<3000) {
232    model.messageHandler()->setLogLevel(1);
233    //model.solver()->messageHandler()->setLogLevel(0);
234  } else {
235    model.messageHandler()->setLogLevel(2);
236    model.solver()->messageHandler()->setLogLevel(1);
237  }
238  // Default strategy will leave cut generators as they exist already
239  // so cutsOnlyAtRoot (1) ignored
240  // numberStrong (2) is 5 (default)
241  // numberBeforeTrust (3) is 5 (default is 0)
242  // printLevel (4) defaults (0)
243  CbcStrategyDefault strategy(true,5,5);
244  // Set up pre-processing to find sos if wanted
245  if (preProcess)
246    strategy.setupPreProcessing(2);
247  model.setStrategy(strategy);
248
249  // Go round adding cuts to cutoff last solution
250  // Stop after finding 20 best solutions
251  for (int iPass=0;iPass<20;iPass++) {
252    time1 = CoinCpuTime();
253    // Do complete search
254    model.branchAndBound();
255   
256    std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
257             <<model.getNodeCount()<<" nodes with objective "
258             <<model.getObjValue()
259             <<(!model.status() ? " Finished" : " Not finished")
260             <<std::endl;
261    // Stop if infeasible
262    if (model.isProvenInfeasible())
263      break;
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 = model.bestSolution();
271    //const double * lower = solver->getColLower();
272    //const double * upper = solver->getColUpper();
273
274    // Get names from solver1 (as OsiSolverInterface may lose)
275    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();
276   
277    int iColumn;
278    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
279   
280    std::cout<<"--------------------------------------"<<std::endl;
281    for (iColumn=0;iColumn<numberColumns;iColumn++) {
282      double value=solution[iColumn];
283      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) 
284        std::cout<<std::setw(6)<<iColumn<<" "
285                 <<columnNames[iColumn]<<" "
286                 <<value
287          //<<" "<<lower[iColumn]<<" "<<upper[iColumn]
288                 <<std::endl;
289    }
290    std::cout<<"--------------------------------------"<<std::endl;
291 
292    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
293    /* Now add cut to reference copy.
294       resetting to reference copy also gets rid of best solution so we
295       should either save best solution, reset, add cut OR
296       add cut to reference copy then reset - this is doing latter
297    */
298    OsiSolverInterface * refSolver = model.referenceSolver();
299    const double * bestSolution = model.bestSolution();
300    const double * originalLower = refSolver->getColLower();
301    const double * originalUpper = refSolver->getColUpper();
302    CoinPackedVector cut;
303    double rhs = 1.0;
304    for (iColumn=0;iColumn<numberColumns;iColumn++) {
305      double value=bestSolution[iColumn];
306      if (solver->isInteger(iColumn)) {
307        // only works for 0-1 variables
308        assert (originalLower[iColumn]==0.0&&
309                originalUpper[iColumn]==1.0);
310        // double check integer
311        assert (fabs(floor(value+0.5)-value)<1.0e-5);
312        if (value>0.5) {
313          // at 1.0
314          cut.insert(iColumn,-1.0);
315          rhs -= 1.0;
316        } else {
317          // at 0.0
318          cut.insert(iColumn,1.0);
319        }
320      }
321    }
322    // now add cut
323    refSolver->addRow(cut,rhs,COIN_DBL_MAX);
324    model.resetToReferenceSolver();
325  }
326  return 0;
327}   
Note: See TracBrowser for help on using the repository browser.