source: trunk/CbcCutGenerator.cpp @ 129

Last change on this file since 129 was 66, checked in by forrest, 16 years ago

few additional methods

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.4 KB
Line 
1// Copyright (C) 2003, 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#include <cassert>
8#include <cmath>
9#include <cfloat>
10
11#include "OsiSolverInterface.hpp"
12#include "CbcModel.hpp"
13#include "CbcMessage.hpp"
14#include "CbcCutGenerator.hpp"
15#include "CglProbing.hpp"
16#include "CoinTime.hpp"
17
18// Default Constructor
19CbcCutGenerator::CbcCutGenerator ()
20  : model_(NULL),
21    generator_(NULL),
22    whenCutGenerator_(-1),
23    whenCutGeneratorInSub_(-100),
24    depthCutGenerator_(-1),
25    depthCutGeneratorInSub_(-1),
26    generatorName_(NULL),
27    normal_(true),
28    atSolution_(false),
29    whenInfeasible_(false),
30    timing_(false),
31    timeInCutGenerator_(0.0),
32    numberTimes_(0),
33    numberCuts_(0),
34    numberCutsActive_(0)
35{
36}
37// Normal constructor
38CbcCutGenerator::CbcCutGenerator(CbcModel * model,CglCutGenerator * generator,
39                                 int howOften, const char * name,
40                                 bool normal, bool atSolution, 
41                                 bool infeasible, int howOftenInSub,
42                                 int whatDepth, int whatDepthInSub)
43  : 
44    depthCutGenerator_(whatDepth),
45    depthCutGeneratorInSub_(whatDepthInSub),
46    timing_(false),
47    timeInCutGenerator_(0.0),
48    numberTimes_(0),
49    numberCuts_(0),
50    numberCutsActive_(0)
51{
52  model_ = model;
53  generator_=generator->clone();
54  generator_->refreshSolver(model_->solver());
55  whenCutGenerator_=howOften;
56  whenCutGeneratorInSub_ = howOftenInSub;
57  if (name)
58    generatorName_=strdup(name);
59  else
60    generatorName_ = strdup("Unknown");
61  normal_=normal;
62  atSolution_=atSolution;
63  whenInfeasible_=infeasible;
64}
65
66// Copy constructor
67CbcCutGenerator::CbcCutGenerator ( const CbcCutGenerator & rhs)
68{
69  model_ = rhs.model_;
70  generator_=rhs.generator_->clone();
71  generator_->refreshSolver(model_->solver());
72  whenCutGenerator_=rhs.whenCutGenerator_;
73  whenCutGeneratorInSub_ = rhs.whenCutGeneratorInSub_;
74  depthCutGenerator_=rhs.depthCutGenerator_;
75  depthCutGeneratorInSub_ = rhs.depthCutGeneratorInSub_;
76  generatorName_=strdup(rhs.generatorName_);
77  normal_=rhs.normal_;
78  atSolution_=rhs.atSolution_;
79  whenInfeasible_=rhs.whenInfeasible_;
80  timing_ = rhs.timing_;
81  timeInCutGenerator_ = rhs.timeInCutGenerator_;
82  numberTimes_ = rhs.numberTimes_;
83  numberCuts_ = rhs.numberCuts_;
84  numberCutsActive_ = rhs.numberCutsActive_;
85}
86
87// Assignment operator
88CbcCutGenerator & 
89CbcCutGenerator::operator=( const CbcCutGenerator& rhs)
90{
91  if (this!=&rhs) {
92    delete generator_;
93    free(generatorName_);
94    model_ = rhs.model_;
95    generator_=rhs.generator_->clone();
96    generator_->refreshSolver(model_->solver());
97    whenCutGenerator_=rhs.whenCutGenerator_;
98    whenCutGeneratorInSub_ = rhs.whenCutGeneratorInSub_;
99    depthCutGenerator_=rhs.depthCutGenerator_;
100    depthCutGeneratorInSub_ = rhs.depthCutGeneratorInSub_;
101    generatorName_=strdup(rhs.generatorName_);
102    normal_=rhs.normal_;
103    atSolution_=rhs.atSolution_;
104    whenInfeasible_=rhs.whenInfeasible_;
105    timing_ = rhs.timing_;
106    timeInCutGenerator_ = rhs.timeInCutGenerator_;
107    numberTimes_ = rhs.numberTimes_;
108    numberCuts_ = rhs.numberCuts_;
109    numberCutsActive_ = rhs.numberCutsActive_;
110  }
111  return *this;
112}
113
114// Destructor
115CbcCutGenerator::~CbcCutGenerator ()
116{
117  free(generatorName_);
118  delete generator_;
119}
120
121/* This is used to refresh any inforamtion.
122   It also refreshes the solver in the cut generator
123   in case generator wants to do some work
124*/
125void 
126CbcCutGenerator::refreshModel(CbcModel * model)
127{
128  model_=model;
129  generator_->refreshSolver(model_->solver());
130}
131/* Generate cuts for the model data contained in si.
132   The generated cuts are inserted into and returned in the
133   collection of cuts cs.
134*/
135bool
136CbcCutGenerator::generateCuts( OsiCuts & cs , bool fullScan, CbcNode * node)
137{
138  int howOften = whenCutGenerator_;
139  if (howOften==-100)
140    return false;
141  if (howOften>0)
142    howOften = howOften % 1000000;
143  else 
144    howOften=1;
145  if (!howOften)
146    howOften=1;
147  bool returnCode=false;
148  OsiSolverInterface * solver = model_->solver();
149  int depth;
150  if (node)
151    depth=node->depth();
152  else
153    depth=0;
154  int pass=model_->getCurrentPassNumber()-1;
155  bool doThis=(model_->getNodeCount()%howOften)==0;
156  if (depthCutGenerator_>0) 
157    doThis = (depth % depthCutGenerator_) ==0;
158  // But turn off if 100
159  if (howOften==100)
160    doThis=false;
161  if (fullScan||doThis) {
162    double time1=0.0;
163    if (timing_)
164      time1 = CoinCpuTime();
165    CglTreeInfo info;
166    info.level = depth;
167    info.pass = pass;
168    info.formulation_rows = model_->numberRowsAtContinuous();
169    info.inTree = node!=NULL;
170    incrementNumberTimesEntered();
171    CglProbing* generator =
172      dynamic_cast<CglProbing*>(generator_);
173    if (!generator) {
174      // Pass across model information in case it could be useful
175      //OsiSolverInterface * solver = model_->solver();
176      //void * saveData = solver->getApplicationData();
177      //solver->setApplicationData(model_);
178      generator_->generateCuts(*solver,cs,info);
179      //solver->setApplicationData(saveData);
180    } else {
181      // Probing - return tight column bounds
182      generator->generateCutsAndModify(*solver,cs,info);
183      const double * tightLower = generator->tightLower();
184      const double * lower = solver->getColLower();
185      const double * tightUpper = generator->tightUpper();
186      const double * upper = solver->getColUpper();
187      const double * solution = solver->getColSolution();
188      int j;
189      int numberColumns = solver->getNumCols();
190      double primalTolerance = 1.0e-8;
191      for (j=0;j<numberColumns;j++) {
192        if (tightUpper[j]==tightLower[j]&&
193            upper[j]>lower[j]) {
194          // fix
195          solver->setColLower(j,tightLower[j]);
196          solver->setColUpper(j,tightUpper[j]);
197          if (tightLower[j]>solution[j]+primalTolerance||
198              tightUpper[j]<solution[j]-primalTolerance)
199            returnCode=true;
200        }
201      }
202    }
203    if (timing_)
204      timeInCutGenerator_ += CoinCpuTime()-time1;
205  }
206  return returnCode;
207}
208void 
209CbcCutGenerator::setHowOften(int howOften) 
210{
211 
212  if (howOften>=1000000) {
213    // leave Probing every 10
214    howOften = howOften % 1000000;
215    CglProbing* generator =
216      dynamic_cast<CglProbing*>(generator_);
217   
218    if (generator&&howOften>10) 
219      howOften=10+1000000;
220    else
221      howOften += 1000000;
222  }
223  whenCutGenerator_ = howOften;
224}
225void 
226CbcCutGenerator::setWhatDepth(int value) 
227{
228  depthCutGenerator_ = value;
229}
230void 
231CbcCutGenerator::setWhatDepthInSub(int value) 
232{
233  depthCutGeneratorInSub_ = value;
234}
Note: See TracBrowser for help on using the repository browser.