source: trunk/Cbc/examples/driver6.cpp @ 2496

Last change on this file since 2496 was 2469, checked in by unxusr, 8 months ago

formatting

File size: 9.3 KB
Line 
1// $Id: driver6.cpp 1898 2013-04-09 18:06:04Z 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
14#include "CoinTime.hpp"
15#include "CoinSignal.hpp"
16/*
17  This shows how to trap signals.
18  This just traps ctrl-c and allows user to pause and then hit S or C
19  In this simple version Stop may not be effective until a heuristic has exited
20 */
21
22static CbcModel *currentBranchModel = NULL;
23extern "C" {
24static void signal_handler(int whichSignal)
25{
26  int gotChar = 'X';
27  while (toupper(gotChar) != 'S' && toupper(gotChar) != 'C') {
28    // See what user wants to do
29    fprintf(stderr, "Enter S to stop, C to continue:");
30    gotChar = getchar();
31  }
32  if (currentBranchModel != NULL && toupper(gotChar) == 'S') {
33    currentBranchModel->sayEventHappened(); // say why stopped
34    if (currentBranchModel->heuristicModel())
35      currentBranchModel->heuristicModel()->sayEventHappened();
36  }
37  return;
38}
39}
40static CoinSighandler_t saveSignal = signal(SIGINT, signal_handler);
41//#############################################################################
42
43/************************************************************************
44
45This main program shows how to take advantage of the standalone cbc in your program,
46while still making major modifications.
47First it reads in an integer model from an mps file
48Then it initializes the integer model with cbc defaults
49Then it calls CbcMain1 passing all parameters apart from first but with callBack to modify stuff
50Finally it prints solution
51
52************************************************************************/
53/* Meaning of whereFrom:
54   1 after initial solve by dualsimplex etc
55   2 after preprocessing
56   3 just before branchAndBound (so user can override)
57   4 just after branchAndBound (before postprocessing)
58   5 after postprocessing
59*/
60/* Meaning of model status is as normal
61   status
62      -1 before branchAndBound
63      0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found
64      (or check value of best solution)
65      1 stopped - on maxnodes, maxsols, maxtime
66      2 difficulties so run was abandoned
67      (5 event user programmed event occurred)
68
69      cbc secondary status of problem
70        -1 unset (status_ will also be -1)
71        0 search completed with solution
72        1 linear relaxation not feasible (or worse than cutoff)
73        2 stopped on gap
74        3 stopped on nodes
75        4 stopped on time
76        5 stopped on user event
77        6 stopped on solutions
78        7 linear relaxation unbounded
79
80   but initially check if status is 0 and secondary status is 1 -> infeasible
81   or you can check solver status.
82*/
83/* Return non-zero to return quickly */
84static int callBack(CbcModel *model, int whereFrom)
85{
86  int returnCode = 0;
87  switch (whereFrom) {
88  case 1:
89  case 2:
90    if (!model->status() && model->secondaryStatus())
91      returnCode = 1;
92    break;
93  case 3: {
94    // set up signal trapping
95    saveSignal = signal(SIGINT, signal_handler);
96    currentBranchModel = model;
97  } break;
98  case 4: {
99    // restore
100    signal(SIGINT, saveSignal);
101    currentBranchModel = NULL;
102  }
103  // If not good enough could skip postprocessing
104  break;
105  case 5:
106    break;
107  default:
108    abort();
109  }
110  return returnCode;
111}
112#include "CbcEventHandler.hpp"
113/** This is so user can trap events and do useful stuff. 
114
115    CbcModel model_ is available as well as anything else you care
116    to pass in
117*/
118
119class MyEventHandler3 : public CbcEventHandler {
120
121public:
122  /**@name Overrides */
123  //@{
124  virtual CbcAction event(CbcEvent whichEvent);
125  //@}
126
127  /**@name Constructors, destructor etc*/
128  //@{
129  /** Default constructor. */
130  MyEventHandler3();
131  /// Constructor with pointer to model (redundant as setEventHandler does)
132  MyEventHandler3(CbcModel *model);
133  /** Destructor */
134  virtual ~MyEventHandler3();
135  /** The copy constructor. */
136  MyEventHandler3(const MyEventHandler3 &rhs);
137  /// Assignment
138  MyEventHandler3 &operator=(const MyEventHandler3 &rhs);
139  /// Clone
140  virtual CbcEventHandler *clone() const;
141  //@}
142
143protected:
144  // data goes here
145};
146//-------------------------------------------------------------------
147// Default Constructor
148//-------------------------------------------------------------------
149MyEventHandler3::MyEventHandler3()
150  : CbcEventHandler()
151{
152}
153
154//-------------------------------------------------------------------
155// Copy constructor
156//-------------------------------------------------------------------
157MyEventHandler3::MyEventHandler3(const MyEventHandler3 &rhs)
158  : CbcEventHandler(rhs)
159{
160}
161
162// Constructor with pointer to model
163MyEventHandler3::MyEventHandler3(CbcModel *model)
164  : CbcEventHandler(model)
165{
166}
167
168//-------------------------------------------------------------------
169// Destructor
170//-------------------------------------------------------------------
171MyEventHandler3::~MyEventHandler3()
172{
173}
174
175//----------------------------------------------------------------
176// Assignment operator
177//-------------------------------------------------------------------
178MyEventHandler3 &
179MyEventHandler3::operator=(const MyEventHandler3 &rhs)
180{
181  if (this != &rhs) {
182    CbcEventHandler::operator=(rhs);
183  }
184  return *this;
185}
186//-------------------------------------------------------------------
187// Clone
188//-------------------------------------------------------------------
189CbcEventHandler *MyEventHandler3::clone() const
190{
191  return new MyEventHandler3(*this);
192}
193
194CbcEventHandler::CbcAction
195MyEventHandler3::event(CbcEvent whichEvent)
196{
197  // If in sub tree carry on
198  if (!model_->parentModel()) {
199    if (whichEvent == solution || whichEvent == heuristicSolution) {
200#ifdef STOP_EARLY
201      return stop; // say finished
202#else
203      // If preprocessing was done solution will be to processed model
204      int numberColumns = model_->getNumCols();
205      const double *bestSolution = model_->bestSolution();
206      assert(bestSolution);
207      printf("value of solution is %g\n", model_->getObjValue());
208      for (int i = 0; i < numberColumns; i++) {
209        if (fabs(bestSolution[i]) > 1.0e-8)
210          printf("%d %g\n", i, bestSolution[i]);
211      }
212      return noAction; // carry on
213#endif
214    } else {
215      return noAction; // carry on
216    }
217  } else {
218    return noAction; // carry on
219  }
220}
221
222int main(int argc, const char *argv[])
223{
224
225  OsiClpSolverInterface solver1;
226  //#define USE_OSI_NAMES
227#ifdef USE_OSI_NAMES
228  // Say we are keeping names (a bit slower this way)
229  solver1.setIntParam(OsiNameDiscipline, 1);
230#endif
231  // Read in model using argv[1]
232  // and assert that it is a clean model
233  std::string mpsFileName;
234#if defined(SAMPLEDIR)
235  mpsFileName = SAMPLEDIR "/p0033.mps";
236#else
237  if (argc < 2) {
238    fprintf(stderr, "Do not know where to find sample MPS files.\n");
239    exit(1);
240  }
241#endif
242  if (argc >= 2)
243    mpsFileName = argv[1];
244  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(), "");
245  if (numMpsReadErrors != 0) {
246    printf("%d errors reading MPS file\n", numMpsReadErrors);
247    return numMpsReadErrors;
248  }
249  // Tell solver to return fast if presolve or initial solve infeasible
250  solver1.getModelPtr()->setMoreSpecialOptions(3);
251
252  // Pass to Cbc initialize defaults
253  CbcModel modelA(solver1);
254  CbcModel *model = &modelA;
255  CbcMain0(modelA);
256  // Event handler
257  MyEventHandler3 eventHandler;
258  model->passInEventHandler(&eventHandler);
259  /* Now go into code for standalone solver
260     Could copy arguments and add -quit at end to be safe
261     but this will do
262  */
263  if (argc > 2) {
264    CbcMain1(argc - 1, argv + 1, modelA, callBack);
265  } else {
266    const char *argv2[] = { "driver6", "-solve", "-quit" };
267    CbcMain1(3, argv2, modelA, callBack);
268  }
269  // Solver was cloned so get current copy
270  OsiSolverInterface *solver = model->solver();
271  // Print solution if finished (could get from model->bestSolution() as well
272
273  if (model->bestSolution()) {
274
275    const double *solution = solver->getColSolution();
276
277    int iColumn;
278    int numberColumns = solver->getNumCols();
279    std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14);
280
281    std::cout << "--------------------------------------" << std::endl;
282#ifdef USE_OSI_NAMES
283
284    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
285      double value = solution[iColumn];
286      if (fabs(value) > 1.0e-7 && solver->isInteger(iColumn))
287        std::cout << std::setw(6) << iColumn << " " << std::setw(8) << setiosflags(std::ios::left) << solver->getColName(iColumn)
288                  << resetiosflags(std::ios::adjustfield) << std::setw(14) << " " << value << std::endl;
289    }
290#else
291    // names may not be in current solver - use original
292
293    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
294      double value = solution[iColumn];
295      if (fabs(value) > 1.0e-7 && solver->isInteger(iColumn))
296        std::cout << std::setw(6) << iColumn << " " << std::setw(8) << setiosflags(std::ios::left) << solver1.getModelPtr()->columnName(iColumn)
297                  << resetiosflags(std::ios::adjustfield) << std::setw(14) << " " << value << std::endl;
298    }
299#endif
300    std::cout << "--------------------------------------" << std::endl;
301
302    std::cout << std::resetiosflags(std::ios::fixed | std::ios::showpoint | std::ios::scientific);
303  } else {
304    std::cout << " No solution!" << std::endl;
305  }
306  return 0;
307}
Note: See TracBrowser for help on using the repository browser.