source: trunk/Cbc/examples/fast0507b.cpp

Last change on this file 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: 10.5 KB
Line 
1// $Id: fast0507b.cpp 1898 2013-04-09 18:06:04Z forrest $
2// Copyright (C) 2002, 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 "CbcConfig.h"
7
8#include <cassert>
9#include <iomanip>
10
11#include "CoinPragma.hpp"
12
13// For Branch and bound
14#include "OsiSolverInterface.hpp"
15#include "CbcModel.hpp"
16#include "CbcBranchUser.hpp"
17#include "CbcBranchFollow2.hpp"
18#include "CbcCompareUser.hpp"
19#include "CbcCutGenerator.hpp"
20#include "CbcHeuristicGreedy.hpp"
21#include "OsiClpSolverInterface.hpp"
22#include "CbcSolver2.hpp"
23
24// Cuts
25
26#include "CglGomory.hpp"
27#include "CglProbing.hpp"
28#include "CglKnapsackCover.hpp"
29#include "CglOddHole.hpp"
30#include "CglClique.hpp"
31#include "CglFlowCover.hpp"
32#include "CglMixedIntegerRounding.hpp"
33#include "CglMixedIntegerRounding2.hpp"
34// Preprocessing
35#include "CglPreProcess.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#ifdef COIN_USE_CLPxx
71  OsiClpSolverInterface solver1;
72#else
73  CbcSolver2 solver1;
74#endif
75
76  // Read in model using argv[1]
77  // and assert that it is a clean model
78  std::string mpsFileName;
79  if (argc>=2) mpsFileName = argv[1];
80  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
81  if( numMpsReadErrors != 0 )
82  {
83     printf("%d errors reading MPS file\n", numMpsReadErrors);
84     return numMpsReadErrors;
85  }
86  double time1 = CoinCpuTime();
87  /* Options are:
88     preprocess to do preprocessing
89     time in minutes
90     if 2 parameters and numeric taken as time
91  */
92  bool preProcess=false;
93  double minutes=-1.0;
94  int nGoodParam=0;
95  for (int iParam=2; iParam<argc;iParam++) {
96    if (!strcmp(argv[iParam],"preprocess")) {
97      preProcess=true;
98      nGoodParam++;
99    } else if (!strcmp(argv[iParam],"time")) {
100      if (iParam+1<argc&&isdigit(argv[iParam+1][0])) {
101        minutes=atof(argv[iParam+1]);
102        if (minutes>=0.0) {
103          nGoodParam+=2;
104          iParam++; // skip time
105        }
106      }
107    }
108  }
109  if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) {
110    // If time is given then stop after that number of minutes
111    minutes = atof(argv[2]);
112    if (minutes>=0.0) 
113      nGoodParam=1;
114  }
115  if (nGoodParam!=argc-2) {
116    printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n");
117    exit(1);
118  }
119  solver1.initialSolve();
120  // Reduce printout
121  //solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
122  // Say we want scaling
123  //solver1.setHintParam(OsiDoScale,true,OsiHintTry);
124  //solver1.setCleanupScaling(1);
125  // See if we want preprocessing
126  OsiSolverInterface * solver2=&solver1;
127  CglPreProcess process;
128  if (preProcess) {
129    /* Do not try and produce equality cliques and
130       do up to 5 passes */
131    solver2 = process.preProcess(solver1,false,5);
132    if (!solver2) {
133      printf("Pre-processing says infeasible\n");
134      exit(2);
135    }
136    solver2->resolve();
137  }
138  CbcModel model(*solver2);
139  // Point to solver
140  OsiSolverInterface * solver3 = model.solver();
141  CbcSolver2 * osiclp = dynamic_cast< CbcSolver2*> (solver3);
142  assert (osiclp);
143  osiclp->initialize(&model,NULL);
144  osiclp->setAlgorithm(2);
145  int numberColumns = osiclp->getNumCols();
146  int * priority = new int [numberColumns+1];
147  int n=0;
148  int iColumn;
149  for ( iColumn=0;iColumn<numberColumns;iColumn++) {
150    priority[n++]=10000;
151  }
152  priority[n]=1;
153  CbcObject * newObject =new CbcFollowOn2(&model);
154  model.addObjects(1,&newObject);
155  delete newObject;
156  model.passInPriorities(priority,false);
157  delete [] priority;
158  // Set up some cut generators and defaults
159  // Probing first as gets tight bounds on continuous
160
161  CglProbing generator1;
162  generator1.setUsingObjective(true);
163  generator1.setMaxPass(3);
164  // Number of unsatisfied variables to look at
165  generator1.setMaxProbe(10);
166  // How far to follow the consequences
167  generator1.setMaxLook(50);
168  // Only look at rows with fewer than this number of elements
169  generator1.setMaxElements(200);
170  generator1.setRowCuts(3);
171
172  CglGomory generator2;
173  // try larger limit
174  generator2.setLimit(300);
175
176  CglKnapsackCover generator3;
177
178  CglOddHole generator4;
179  generator4.setMinimumViolation(0.005);
180  generator4.setMinimumViolationPer(0.00002);
181  // try larger limit
182  generator4.setMaximumEntries(200);
183
184  CglClique generator5;
185  generator5.setStarCliqueReport(false);
186  generator5.setRowCliqueReport(false);
187
188  CglMixedIntegerRounding mixedGen;
189  /* This is same as default constructor -
190     (1,true,1)
191      I presume if maxAggregate larger then slower but maybe better
192      criterion can be  1 through 3
193      Reference:
194      Hugues Marchand and Laurence A. Wolsey
195      Aggregation and Mixed Integer Rounding to Solve MIPs
196      Operations Research, 49(3), May-June 2001.
197   */
198  int maxAggregate=1;
199  bool multiply=true;
200  int criterion=1;
201  CglMixedIntegerRounding2 mixedGen2(maxAggregate,multiply,criterion);
202  CglFlowCover flowGen;
203 
204  // Add in generators
205  // Experiment with -1 and -99 etc
206  //model.addCutGenerator(&generator1,-1,"Probing");
207  //model.addCutGenerator(&generator2,-1,"Gomory");
208  //model.addCutGenerator(&generator3,-1,"Knapsack");
209  //model.addCutGenerator(&generator4,-1,"OddHole");
210  //model.addCutGenerator(&generator5,-1,"Clique");
211  //model.addCutGenerator(&flowGen,-1,"FlowCover");
212  //model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
213  //model.addCutGenerator(&mixedGen2,-1,"MixedIntegerRounding2");
214  // Say we want timings
215  int numberGenerators = model.numberCutGenerators();
216  int iGenerator;
217  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
218    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
219    generator->setTiming(true);
220  }
221
222  // Allow rounding heuristic
223
224  CbcRounding heuristic1(model);
225  model.addHeuristic(&heuristic1);
226
227  // And Greedy heuristic
228
229  CbcHeuristicGreedyCover heuristic2(model);
230  // Use original upper and perturb more
231  heuristic2.setAlgorithm(0);
232  heuristic2.setWhen(13); // say do even though looks odd (nObjects>nInts)
233  model.addHeuristic(&heuristic2);
234
235  // Redundant definition of default branching (as Default == User)
236  CbcBranchUserDecision branch;
237  model.setBranchingMethod(&branch);
238
239  // Definition of node choice
240  CbcCompareUser compare;
241  model.setNodeComparison(compare);
242
243  // Do initial solve to continuous
244  model.initialSolve();
245
246  // Could tune more
247  model.setMinimumDrop(CoinMin(1.0,
248                             fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4));
249
250  if (model.getNumCols()<500)
251    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
252  else if (model.getNumCols()<5000)
253    model.setMaximumCutPassesAtRoot(100); // use minimum drop
254  else
255    model.setMaximumCutPassesAtRoot(20);
256  //model.setMaximumCutPasses(1);
257
258  // Do more strong branching if small
259  //if (model.getNumCols()<5000)
260  //model.setNumberStrong(10);
261  // Switch off strong branching if wanted
262  model.setNumberStrong(0);
263
264  model.solver()->setIntParam(OsiMaxNumIterationHotStart,50);
265
266  // If time is given then stop after that number of minutes
267  if (minutes>=0.0) {
268    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
269    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
270  }
271  // Switch off most output
272  if (model.getNumCols()<3000) {
273    model.messageHandler()->setLogLevel(1);
274    //model.solver()->messageHandler()->setLogLevel(0);
275  } else {
276    model.messageHandler()->setLogLevel(2);
277    model.solver()->messageHandler()->setLogLevel(1);
278  }
279  //model.messageHandler()->setLogLevel(2);
280  //model.solver()->messageHandler()->setLogLevel(2);
281  //model.setPrintFrequency(50);
282#define DEBUG_CUTS
283#ifdef DEBUG_CUTS
284  // Set up debugger by name (only if no preprocesing)
285  if (!preProcess) {
286    std::string problemName ;
287    //model.solver()->getStrParam(OsiProbName,problemName) ;
288    //model.solver()->activateRowCutDebugger(problemName.c_str()) ;
289    model.solver()->activateRowCutDebugger("cap6000a") ;
290  }
291#endif
292
293  // Do complete search
294 
295  model.branchAndBound();
296  //void printHowMany();
297  //printHowMany();
298  std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, "
299           <<model.getNodeCount()<<" nodes with objective "
300           <<model.getObjValue()
301           <<(!model.status() ? " Finished" : " Not finished")
302           <<std::endl;
303
304  // Print more statistics
305  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
306           <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;
307
308  for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
309    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
310    std::cout<<generator->cutGeneratorName()<<" was tried "
311             <<generator->numberTimesEntered()<<" times and created "
312             <<generator->numberCutsInTotal()<<" cuts of which "
313             <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
314    if (generator->timing())
315      std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
316    else
317      std::cout<<std::endl;
318  }
319  // Print solution if finished - we can't get names from Osi!
320
321  if (model.getMinimizationObjValue()<1.0e50) {
322    // post process
323    if (preProcess)
324      process.postProcess(*model.solver());
325    int numberColumns = model.solver()->getNumCols();
326   
327    const double * solution = model.solver()->getColSolution();
328   
329    int iColumn;
330    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
331   
332    std::cout<<"--------------------------------------"<<std::endl;
333    for (iColumn=0;iColumn<numberColumns;iColumn++) {
334      double value=solution[iColumn];
335      if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) 
336        std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl;
337    }
338    std::cout<<"--------------------------------------"<<std::endl;
339 
340    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
341  }
342  return 0;
343}   
Note: See TracBrowser for help on using the repository browser.