source: trunk/Cbc/examples/driver4.cpp

Last change on this file was 2469, checked in by unxusr, 6 weeks ago

formatting

  • Property svn:keywords set to Author Date Id Revision
File size: 12.0 KB
Line 
1// $Id: driver4.cpp 2469 2019-01-06 23:17:46Z unxusr $
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("value of solution is %g\n", model_->getObjValue());
258      for (int i = 0; i < numberColumns; i++) {
259        if (fabs(bestSolution[i]) > 1.0e-8)
260          printf("%d %g\n", i, bestSolution[i]);
261      }
262      return noAction; // carry on
263#endif
264    } else {
265      return noAction; // carry on
266    }
267  } else {
268    return noAction; // carry on
269  }
270}
271
272int main(int argc, const char *argv[])
273{
274
275  OsiClpSolverInterface solver1;
276  //#define USE_OSI_NAMES
277#ifdef USE_OSI_NAMES
278  // Say we are keeping names (a bit slower this way)
279  solver1.setIntParam(OsiNameDiscipline, 1);
280#endif
281  // Read in model using argv[1]
282  // and assert that it is a clean model
283  std::string mpsFileName;
284#if defined(SAMPLEDIR)
285  mpsFileName = SAMPLEDIR "/p0033.mps";
286#else
287  if (argc < 2) {
288    fprintf(stderr, "Do not know where to find sample MPS files.\n");
289    exit(1);
290  }
291#endif
292  if (argc >= 2)
293    mpsFileName = argv[1];
294  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(), "");
295  if (numMpsReadErrors != 0) {
296    printf("%d errors reading MPS file\n", numMpsReadErrors);
297    return numMpsReadErrors;
298  }
299  // Tell solver to return fast if presolve or initial solve infeasible
300  solver1.getModelPtr()->setMoreSpecialOptions(3);
301
302  /* Two ways of doing this depending on whether NEW_STYLE_SOLVER defined.
303     So we need pointer to model.  Old way could use modelA. rather than model->
304   */
305  // Messy code below copied from CbcSolver.cpp
306  // Pass to Cbc initialize defaults
307  CbcModel modelA(solver1);
308  CbcModel *model = &modelA;
309  CbcMain0(modelA);
310  // Event handler
311  MyEventHandler3 eventHandler;
312  model->passInEventHandler(&eventHandler);
313  /* Now go into code for standalone solver
314     Could copy arguments and add -quit at end to be safe
315     but this will do
316  */
317  if (argc > 2) {
318    CbcMain1(argc - 1, argv + 1, modelA, callBack);
319  } else {
320    const char *argv2[] = { "driver4", "-solve", "-quit" };
321    CbcMain1(3, argv2, modelA, callBack);
322  }
323  // Solver was cloned so get current copy
324  OsiSolverInterface *solver = model->solver();
325  // Print solution if finished (could get from model->bestSolution() as well
326
327  if (model->bestSolution()) {
328
329    const double *solution = solver->getColSolution();
330
331    int iColumn;
332    int numberColumns = solver->getNumCols();
333    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14);
334
335    std::cout << "--------------------------------------" << std::endl;
336#ifdef USE_OSI_NAMES
337
338    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
339      double value = solution[iColumn];
340      if (fabs(value) > 1.0e-7 && solver->isInteger(iColumn))
341        std::cout << std::setw(6) << iColumn << " " << std::setw(8) << setiosflags(std::ios::left) << solver->getColName(iColumn)
342                  << resetiosflags(std::ios::adjustfield) << std::setw(14) << " " << value << std::endl;
343    }
344#else
345    // names may not be in current solver - use original
346
347    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
348      double value = solution[iColumn];
349      if (fabs(value) > 1.0e-7 && solver->isInteger(iColumn))
350        std::cout << std::setw(6) << iColumn << " " << std::setw(8) << setiosflags(std::ios::left) << solver1.getModelPtr()->columnName(iColumn)
351                  << resetiosflags(std::ios::adjustfield) << std::setw(14) << " " << value << std::endl;
352    }
353#endif
354    std::cout << "--------------------------------------" << std::endl;
355
356    std::cout << std::resetiosflags(std::ios::fixed | std::ios::showpoint | std::ios::scientific);
357  } else {
358    std::cout << " No solution!" << std::endl;
359  }
360  return 0;
361}
Note: See TracBrowser for help on using the repository browser.