source: trunk/Cbc/examples/driver4.cpp

Last change on this file was 2498, checked in by unxusr, 2 months ago

updated driver 3 and 4 examples

  • Property svn:keywords set to Author Date Id Revision
File size: 12.1 KB
Line 
1// $Id: driver4.cpp 2498 2019-02-20 13:07:32Z stefan $
2// Copyright (C) 2007, 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#include "CbcModel.hpp"
11#include "OsiClpSolverInterface.hpp"
12#include "CbcSolver.hpp"
13#include "CbcHeuristicDiveCoefficient.hpp"
14#include "CbcHeuristicDiveFractional.hpp"
15#include "CbcHeuristicDiveGuided.hpp"
16#include "CbcHeuristicDiveVectorLength.hpp"
17#include "CbcHeuristicDivePseudoCost.hpp"
18#include "CbcHeuristicDiveLineSearch.hpp"
19
20#include "CoinTime.hpp"
21
22//#############################################################################
23
24/************************************************************************
25
26This main program shows how to take advantage of the standalone cbc in your program,
27while still making major modifications.
28First it reads in an integer model from an mps file
29Then it initializes the integer model with cbc defaults
30Then it calls CbcMain1 passing all parameters apart from first but with callBack to modify stuff
31Finally it prints solution
32
33************************************************************************/
34/* Meaning of whereFrom:
35   1 after initial solve by dualsimplex etc
36   2 after preprocessing
37   3 just before branchAndBound (so user can override)
38   4 just after branchAndBound (before postprocessing)
39   5 after postprocessing
40*/
41/* Meaning of model status is as normal
42   status
43      -1 before branchAndBound
44      0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found
45      (or check value of best solution)
46      1 stopped - on maxnodes, maxsols, maxtime
47      2 difficulties so run was abandoned
48      (5 event user programmed event occurred)
49
50      cbc secondary status of problem
51        -1 unset (status_ will also be -1)
52        0 search completed with solution
53        1 linear relaxation not feasible (or worse than cutoff)
54        2 stopped on gap
55        3 stopped on nodes
56        4 stopped on time
57        5 stopped on user event
58        6 stopped on solutions
59        7 linear relaxation unbounded
60
61   but initially check if status is 0 and secondary status is 1 -> infeasible
62   or you can check solver status.
63*/
64/* Return non-zero to return quickly */
65static int callBack(CbcModel *model, int whereFrom)
66{
67  int returnCode = 0;
68  switch (whereFrom) {
69  case 1:
70  case 2:
71    if (!model->status() && model->secondaryStatus())
72      returnCode = 1;
73    break;
74  case 3: {
75    // Add in some diving heuristics with different options
76    CbcHeuristicDiveCoefficient heuristicDC(*model);
77    heuristicDC.setHeuristicName("DiveCoefficient");
78    // do if no solution
79    heuristicDC.setWhen(3);
80    // 150 passes and fix general integers
81    heuristicDC.setMaxIterations(151);
82    // make sure can do as many simplex iterations as wanted
83    heuristicDC.setMaxSimplexIterations(COIN_INT_MAX);
84    heuristicDC.setMaxSimplexIterationsAtRoot(COIN_INT_MAX);
85    model->addHeuristic(&heuristicDC);
86    CbcHeuristicDiveFractional heuristicDF(*model);
87    heuristicDF.setHeuristicName("DiveFractional");
88    // do if no solution
89    heuristicDF.setWhen(3);
90    // 150 passes and don't fix general integers
91    heuristicDF.setMaxIterations(150);
92    // make sure can do as many simplex iterations as wanted
93    heuristicDF.setMaxSimplexIterations(COIN_INT_MAX);
94    heuristicDF.setMaxSimplexIterationsAtRoot(COIN_INT_MAX);
95    model->addHeuristic(&heuristicDF);
96    CbcHeuristicDiveGuided heuristicDG(*model);
97    heuristicDG.setHeuristicName("DiveGuided");
98    // do if no solution
99    heuristicDG.setWhen(3);
100    // 200 passes and fix general integers
101    heuristicDG.setMaxIterations(201);
102    // make sure can do as many simplex iterations as wanted
103    heuristicDG.setMaxSimplexIterations(COIN_INT_MAX);
104    heuristicDG.setMaxSimplexIterationsAtRoot(COIN_INT_MAX);
105    model->addHeuristic(&heuristicDG);
106    CbcHeuristicDiveVectorLength heuristicDV(*model);
107    heuristicDV.setHeuristicName("DiveVectorLength");
108    // do if no solution
109    heuristicDV.setWhen(3);
110    // 150 passes and fix general integers
111    heuristicDV.setMaxIterations(151);
112    // make sure can do as many simplex iterations as wanted
113    heuristicDV.setMaxSimplexIterations(COIN_INT_MAX);
114    heuristicDV.setMaxSimplexIterationsAtRoot(COIN_INT_MAX);
115    model->addHeuristic(&heuristicDV);
116    // Second version!
117    CbcHeuristicDiveVectorLength heuristicDV2(*model);
118    heuristicDV2.setHeuristicName("DiveVectorLength");
119    // do if no solution
120    heuristicDV2.setWhen(3);
121    // 300 passes and don't fix general integers
122    heuristicDV2.setMaxIterations(300);
123    // fix fewer
124    heuristicDV2.setPercentageToFix(0.05);
125    // make sure can do as many simplex iterations as wanted
126    heuristicDV2.setMaxSimplexIterations(COIN_INT_MAX);
127    heuristicDV2.setMaxSimplexIterationsAtRoot(COIN_INT_MAX);
128    model->addHeuristic(&heuristicDV2);
129    CbcHeuristicDivePseudoCost heuristicDP(*model);
130    heuristicDP.setHeuristicName("DivePseudoCost");
131    // do if no solution
132    heuristicDP.setWhen(3);
133    // 100 passes and don't fix general integers
134    heuristicDP.setMaxIterations(100);
135    // make sure can do as many simplex iterations as wanted
136    heuristicDP.setMaxSimplexIterations(COIN_INT_MAX);
137    heuristicDP.setMaxSimplexIterationsAtRoot(COIN_INT_MAX);
138    model->addHeuristic(&heuristicDP);
139    CbcHeuristicDiveLineSearch heuristicDL(*model);
140    heuristicDL.setHeuristicName("DiveLineSearch");
141    // do if no solution
142    heuristicDL.setWhen(3);
143    // 150 passes and fix general integers
144    heuristicDL.setMaxIterations(151);
145    // make sure can do as many simplex iterations as wanted
146    heuristicDL.setMaxSimplexIterations(COIN_INT_MAX);
147    heuristicDL.setMaxSimplexIterationsAtRoot(COIN_INT_MAX);
148    model->addHeuristic(&heuristicDL);
149    //CbcCompareUser compare;
150    //model->setNodeComparison(compare);
151  } break;
152  case 4:
153    // If not good enough could skip postprocessing
154    break;
155  case 5:
156    break;
157  default:
158    abort();
159  }
160  return returnCode;
161}
162#include "CbcEventHandler.hpp"
163/** This is so user can trap events and do useful stuff. 
164
165    CbcModel model_ is available as well as anything else you care
166    to pass in
167*/
168
169class MyEventHandler3 : public CbcEventHandler {
170
171public:
172  /**@name Overrides */
173  //@{
174  virtual CbcAction event(CbcEvent whichEvent);
175  //@}
176
177  /**@name Constructors, destructor etc*/
178  //@{
179  /** Default constructor. */
180  MyEventHandler3();
181  /// Constructor with pointer to model (redundant as setEventHandler does)
182  MyEventHandler3(CbcModel *model);
183  /** Destructor */
184  virtual ~MyEventHandler3();
185  /** The copy constructor. */
186  MyEventHandler3(const MyEventHandler3 &rhs);
187  /// Assignment
188  MyEventHandler3 &operator=(const MyEventHandler3 &rhs);
189  /// Clone
190  virtual CbcEventHandler *clone() const;
191  //@}
192
193protected:
194  // data goes here
195};
196//-------------------------------------------------------------------
197// Default Constructor
198//-------------------------------------------------------------------
199MyEventHandler3::MyEventHandler3()
200  : CbcEventHandler()
201{
202}
203
204//-------------------------------------------------------------------
205// Copy constructor
206//-------------------------------------------------------------------
207MyEventHandler3::MyEventHandler3(const MyEventHandler3 &rhs)
208  : CbcEventHandler(rhs)
209{
210}
211
212// Constructor with pointer to model
213MyEventHandler3::MyEventHandler3(CbcModel *model)
214  : CbcEventHandler(model)
215{
216}
217
218//-------------------------------------------------------------------
219// Destructor
220//-------------------------------------------------------------------
221MyEventHandler3::~MyEventHandler3()
222{
223}
224
225//----------------------------------------------------------------
226// Assignment operator
227//-------------------------------------------------------------------
228MyEventHandler3 &
229MyEventHandler3::operator=(const MyEventHandler3 &rhs)
230{
231  if (this != &rhs) {
232    CbcEventHandler::operator=(rhs);
233  }
234  return *this;
235}
236//-------------------------------------------------------------------
237// Clone
238//-------------------------------------------------------------------
239CbcEventHandler *MyEventHandler3::clone() const
240{
241  return new MyEventHandler3(*this);
242}
243
244CbcEventHandler::CbcAction
245MyEventHandler3::event(CbcEvent whichEvent)
246{
247  // If in sub tree carry on
248  if (!model_->parentModel()) {
249    if (whichEvent == solution || whichEvent == heuristicSolution) {
250#ifdef STOP_EARLY
251      return stop; // say finished
252#else
253      // If preprocessing was done solution will be to processed model
254      int numberColumns = model_->getNumCols();
255      const double *bestSolution = model_->bestSolution();
256      assert(bestSolution);
257      printf("event handler received a solution with cost %g\n", model_->getObjValue());
258      // printing solution contents
259      //for (int i = 0; i < numberColumns; i++) {
260      //  if (fabs(bestSolution[i]) > 1.0e-8)
261      //    printf("%d %g\n", i, bestSolution[i]);
262      //}
263      return noAction; // carry on
264#endif
265    } else {
266      return noAction; // carry on
267    }
268  } else {
269    return noAction; // carry on
270  }
271}
272
273int main(int argc, const char *argv[])
274{
275
276  OsiClpSolverInterface solver1;
277  //#define USE_OSI_NAMES
278#ifdef USE_OSI_NAMES
279  // Say we are keeping names (a bit slower this way)
280  solver1.setIntParam(OsiNameDiscipline, 1);
281#endif
282  // Read in model using argv[1]
283  // and assert that it is a clean model
284  std::string mpsFileName;
285#if defined(SAMPLEDIR)
286  mpsFileName = SAMPLEDIR "/p0033.mps";
287#else
288  if (argc < 2) {
289    fprintf(stderr, "Do not know where to find sample MPS files.\n");
290    exit(1);
291  }
292#endif
293  if (argc >= 2)
294    mpsFileName = argv[1];
295  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(), "");
296  if (numMpsReadErrors != 0) {
297    printf("%d errors reading MPS file\n", numMpsReadErrors);
298    return numMpsReadErrors;
299  }
300  // Tell solver to return fast if presolve or initial solve infeasible
301  solver1.getModelPtr()->setMoreSpecialOptions(3);
302
303  /* Two ways of doing this depending on whether NEW_STYLE_SOLVER defined.
304     So we need pointer to model.  Old way could use modelA. rather than model->
305   */
306  // Messy code below copied from CbcSolver.cpp
307  // Pass to Cbc initialize defaults
308  CbcModel modelA(solver1);
309  CbcModel *model = &modelA;
310  CbcMain0(modelA);
311  // Event handler
312  MyEventHandler3 eventHandler;
313  model->passInEventHandler(&eventHandler);
314  /* Now go into code for standalone solver
315     Could copy arguments and add -quit at end to be safe
316     but this will do
317  */
318  if (argc > 2) {
319    CbcMain1(argc - 1, argv + 1, modelA, callBack);
320  } else {
321    const char *argv2[] = { "driver4", "-solve", "-quit" };
322    CbcMain1(3, argv2, modelA, callBack);
323  }
324  // Solver was cloned so get current copy
325  OsiSolverInterface *solver = model->solver();
326  // Print solution if finished (could get from model->bestSolution() as well
327
328  if (model->bestSolution()) {
329
330    const double *solution = solver->getColSolution();
331
332    int iColumn;
333    int numberColumns = solver->getNumCols();
334    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14);
335
336    std::cout << "--------------------------------------" << std::endl;
337#ifdef USE_OSI_NAMES
338
339    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
340      double value = solution[iColumn];
341      if (fabs(value) > 1.0e-7 && solver->isInteger(iColumn))
342        std::cout << std::setw(6) << iColumn << " " << std::setw(8) << setiosflags(std::ios::left) << solver->getColName(iColumn)
343                  << resetiosflags(std::ios::adjustfield) << std::setw(14) << " " << value << std::endl;
344    }
345#else
346    // names may not be in current solver - use original
347
348    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
349      double value = solution[iColumn];
350      if (fabs(value) > 1.0e-7 && solver->isInteger(iColumn))
351        std::cout << std::setw(6) << iColumn << " " << std::setw(8) << setiosflags(std::ios::left) << solver1.getModelPtr()->columnName(iColumn)
352                  << resetiosflags(std::ios::adjustfield) << std::setw(14) << " " << value << std::endl;
353    }
354#endif
355    std::cout << "--------------------------------------" << std::endl;
356
357    std::cout << std::resetiosflags(std::ios::fixed | std::ios::showpoint | std::ios::scientific);
358  } else {
359    std::cout << " No solution!" << std::endl;
360  }
361  return 0;
362}
Note: See TracBrowser for help on using the repository browser.