source: trunk/Cbc/examples/sample5.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.7 KB
Line 
1// $Id: sample5.cpp 1898 2013-04-09 18:06:04Z stefan $
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 "CoinPragma.hpp"
9
10#include <cassert>
11#include <iomanip>
12
13
14// For Branch and bound
15#include "OsiSolverInterface.hpp"
16#include "CbcModel.hpp"
17#include "CbcBranchUser.hpp"
18#include "CbcCompareUser.hpp"
19#include "CbcCutGenerator.hpp"
20#include "CbcHeuristicLocal.hpp"
21#include "OsiClpSolverInterface.hpp"
22
23// Cuts
24
25#include "CglGomory.hpp"
26#include "CglProbing.hpp"
27#include "CglKnapsackCover.hpp"
28#include "CglOddHole.hpp"
29#include "CglClique.hpp"
30#include "CglFlowCover.hpp"
31#include "CglMixedIntegerRounding.hpp"
32
33// Heuristics
34
35#include "CbcHeuristic.hpp"
36
37// Methods of building
38
39#include "CoinBuild.hpp"
40#include "CoinModel.hpp"
41
42#include "CoinTime.hpp"
43
44
45/************************************************************************
46
47This main program creates an integer model and then solves it
48
49It then sets up some Cgl cut generators and calls branch and cut.
50
51Branching is simple binary branching on integer variables.
52
53Node selection is depth first until first solution is found and then
54based on objective and number of unsatisfied integer variables.
55In this example the functionality is the same as default but it is
56a user comparison function.
57
58Variable branching selection is on maximum minimum-of-up-down change
59after strong branching on 5 variables closest to 0.5.
60
61A simple rounding heuristic is used.
62
63
64************************************************************************/
65
66
67int main (int argc, const char *argv[])
68{
69
70  /* Define your favorite OsiSolver.
71
72     CbcModel clones the solver so use solver1 up to the time you pass it
73     to CbcModel then use a pointer to cloned solver (model.solver())
74  */
75 
76  OsiClpSolverInterface solver1;
77  /* From now on we can build model in a solver independent way.
78     You can add rows one at a time but for large problems this is slow so
79     this example uses CoinBuild or CoinModel
80  */
81  OsiSolverInterface * solver = &solver1;
82  // Data (is exmip1.mps in Mps/Sample
83  // Objective
84  double objValue[]={1.0,2.0,0.0,0.0,0.0,0.0,0.0,-1.0};
85  // Lower bounds for columns
86  double columnLower[]={2.5,0.0,0.0,0.0,0.5,0.0,0.0,0.0};
87  // Upper bounds for columns
88  double columnUpper[]={COIN_DBL_MAX,4.1,1.0,1.0,4.0,
89                  COIN_DBL_MAX,COIN_DBL_MAX,4.3};
90  // Lower bounds for row activities
91  double rowLower[]={2.5,-COIN_DBL_MAX,-COIN_DBL_MAX,1.8,3.0};
92  // Upper bounds for row activities
93  double rowUpper[]={COIN_DBL_MAX,2.1,4.0,5.0,15.0};
94  // Matrix stored packed
95  int column[] = {0,1,3,4,7,
96                  1,2,
97                  2,5,
98                  3,6,
99                  4,7};
100  double element[] = {3.0,1.0,-2.0,-1.0,-1.0,
101                      2.0,1.1,
102                      1.0,1.0,
103                      2.8,-1.2,
104                      1.0,1.9};
105  int starts[]={0,5,7,9,11,13};
106  // Integer variables (note upper bound already 1.0)
107  int whichInt[]={2,3};
108  int numberRows=(int) (sizeof(rowLower)/sizeof(double));
109  int numberColumns=(int) (sizeof(columnLower)/sizeof(double));
110#define BUILD 2
111#if BUILD==1
112  // Using CoinBuild
113  // First do columns (objective and bounds)
114  int i;
115  // We are not adding elements
116  for (i=0;i<numberColumns;i++) {
117    solver->addCol(0,NULL,NULL,columnLower[i],columnUpper[i],
118                    objValue[i]);
119  }
120  // mark as integer
121  for (i=0;i<(int) (sizeof(whichInt)/sizeof(int));i++)
122    solver->setInteger(whichInt[i]);
123  // Now build rows
124  CoinBuild build;
125  for (i=0;i<numberRows;i++) {
126    int startRow = starts[i];
127    int numberInRow = starts[i+1]-starts[i];
128    build.addRow(numberInRow,column+startRow,element+startRow,
129                 rowLower[i],rowUpper[i]);
130  } 
131  // add rows into solver
132  solver->addRows(build);
133#else
134  /* using CoinModel - more flexible but still beta.
135     Can do exactly same way but can mix and match much more.
136     Also all operations are on building object
137  */
138  CoinModel build;
139  // First do columns (objective and bounds)
140  int i;
141  for (i=0;i<numberColumns;i++) {
142    build.setColumnBounds(i,columnLower[i],columnUpper[i]);
143    build.setObjective(i,objValue[i]);
144  }
145  // mark as integer
146  for (i=0;i<(int) (sizeof(whichInt)/sizeof(int));i++)
147    build.setInteger(whichInt[i]);
148  // Now build rows
149  for (i=0;i<numberRows;i++) {
150    int startRow = starts[i];
151    int numberInRow = starts[i+1]-starts[i];
152    build.addRow(numberInRow,column+startRow,element+startRow,
153                 rowLower[i],rowUpper[i]);
154  } 
155  // add rows into solver
156  solver->loadFromCoinModel(build);
157#endif
158
159  // Pass to solver
160  CbcModel model(*solver);
161  model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
162
163
164  // Set up some cut generators and defaults
165  // Probing first as gets tight bounds on continuous
166
167  CglProbing generator1;
168  generator1.setUsingObjective(true);
169  generator1.setMaxPass(3);
170  generator1.setMaxProbe(100);
171  generator1.setMaxLook(50);
172  generator1.setRowCuts(3);
173  //  generator1.snapshot(*model.solver());
174  //generator1.createCliques(*model.solver(),2,1000,true);
175  //generator1.setMode(0);
176
177  CglGomory generator2;
178  // try larger limit
179  generator2.setLimit(300);
180
181  CglKnapsackCover generator3;
182
183  CglOddHole generator4;
184  generator4.setMinimumViolation(0.005);
185  generator4.setMinimumViolationPer(0.00002);
186  // try larger limit
187  generator4.setMaximumEntries(200);
188
189  CglClique generator5;
190  generator5.setStarCliqueReport(false);
191  generator5.setRowCliqueReport(false);
192
193  CglMixedIntegerRounding mixedGen;
194  CglFlowCover flowGen;
195 
196  // Add in generators
197  model.addCutGenerator(&generator1,-1,"Probing");
198  model.addCutGenerator(&generator2,-1,"Gomory");
199  model.addCutGenerator(&generator3,-1,"Knapsack");
200  model.addCutGenerator(&generator4,-1,"OddHole");
201  model.addCutGenerator(&generator5,-1,"Clique");
202  model.addCutGenerator(&flowGen,-1,"FlowCover");
203  model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding");
204
205  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
206  // go faster stripes
207  if (osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
208    osiclp->setupForRepeatedUse(2,0);
209    printf("trying slightly less reliable but faster version (? Gomory cuts okay?)\n");
210    printf("may not be safe if doing cuts in tree which need accuracy (level 2 anyway)\n");
211  }
212
213  // Allow rounding heuristic
214
215  CbcRounding heuristic1(model);
216  model.addHeuristic(&heuristic1);
217
218  // And local search when new solution found
219
220  CbcHeuristicLocal heuristic2(model);
221  model.addHeuristic(&heuristic2);
222
223  // Redundant definition of default branching (as Default == User)
224  CbcBranchUserDecision branch;
225  model.setBranchingMethod(&branch);
226
227  // Definition of node choice
228  CbcCompareUser compare;
229  model.setNodeComparison(compare);
230
231  // Do initial solve to continuous
232  model.initialSolve();
233
234  // Could tune more
235  model.setMinimumDrop(CoinMin(1.0,
236                             fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4));
237
238  if (model.getNumCols()<500)
239    model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible
240  else if (model.getNumCols()<5000)
241    model.setMaximumCutPassesAtRoot(100); // use minimum drop
242  else
243    model.setMaximumCutPassesAtRoot(20);
244  //model.setMaximumCutPasses(5);
245
246  // Switch off strong branching if wanted
247  // model.setNumberStrong(0);
248  // Do more strong branching if small
249  if (model.getNumCols()<5000)
250    model.setNumberStrong(10);
251
252  model.solver()->setIntParam(OsiMaxNumIterationHotStart,100);
253
254  // If time is given then stop after that number of minutes
255  if (argc>2) {
256    int minutes = atoi(argv[2]);
257    std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl;
258    assert (minutes>=0);
259    model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes);
260  }
261  // Switch off most output
262  if (model.getNumCols()<3000) {
263    model.messageHandler()->setLogLevel(1);
264    //model.solver()->messageHandler()->setLogLevel(0);
265  } else {
266    model.messageHandler()->setLogLevel(2);
267    model.solver()->messageHandler()->setLogLevel(1);
268  }
269  double time1 = CoinCpuTime();
270
271  // Do complete search
272 
273  model.branchAndBound();
274
275  std::cout<<" Branch and cut took "<<CoinCpuTime()-time1<<" seconds, "
276           <<model.getNodeCount()<<" nodes with objective "
277           <<model.getObjValue()
278           <<(!model.status() ? " Finished" : " Not finished")
279           <<std::endl;
280
281  // Print more statistics
282  std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective()
283           <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;
284
285  int numberGenerators = model.numberCutGenerators();
286  for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
287    CbcCutGenerator * generator = model.cutGenerator(iGenerator);
288    std::cout<<generator->cutGeneratorName()<<" was tried "
289             <<generator->numberTimesEntered()<<" times and created "
290             <<generator->numberCutsInTotal()<<" cuts of which "
291             <<generator->numberCutsActive()<<" were active after adding rounds of cuts"
292             <<std::endl;
293  }
294  // Print solution if any - we can't get names from Osi!
295
296  if (model.getMinimizationObjValue()<1.0e50) {
297    int numberColumns = model.solver()->getNumCols();
298   
299    const double * solution = model.solver()->getColSolution();
300   
301    int iColumn;
302    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
303   
304    std::cout<<"--------------------------------------"<<std::endl;
305    for (iColumn=0;iColumn<numberColumns;iColumn++) {
306      double value=solution[iColumn];
307      if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) 
308        std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl;
309    }
310    std::cout<<"--------------------------------------"<<std::endl;
311 
312    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
313  }
314  return 0;
315}   
Note: See TracBrowser for help on using the repository browser.