source: trunk/Cbc/examples/driver4.cpp

Last change on this file was 2101, checked in by forrest, 4 years ago

minor print change to diving

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