source: stable/2.8/Cbc/examples/driver4.cpp @ 1902

Last change on this file since 1902 was 1902, checked in by stefan, 6 years ago

sync with trunk rev 1901

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