source: trunk/CbcCutGenerator.cpp @ 216

Last change on this file since 216 was 208, checked in by forrest, 15 years ago

large number of changes

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