source: trunk/Cbc/examples/driver4.cpp @ 1464

Last change on this file since 1464 was 1464, checked in by stefan, 9 years ago

merge split branch into trunk; fix some examples

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