source: trunk/Cbc/examples/CbcCompareUser.cpp @ 640

Last change on this file since 640 was 640, checked in by forrest, 12 years ago

trunk from branches/devel

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.2 KB
Line 
1// Copyright (C) 2004, 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//#define CBC_DEBUG
11
12#include "CbcMessage.hpp"
13#include "CbcModel.hpp"
14#include "CbcTree.hpp"
15#include "CbcCompareUser.hpp"
16#include "CoinError.hpp"
17#include "CoinHelperFunctions.hpp"
18
19/** Default Constructor
20
21*/
22CbcCompareUser::CbcCompareUser ()
23  : CbcCompareBase(),
24    weight_(-1.0),
25    saveWeight_(0.0),
26    numberSolutions_(0),
27    count_(0),
28    treeSize_(0)
29{
30  test_=this;
31}
32
33// Constructor with weight
34CbcCompareUser::CbcCompareUser (double weight) 
35  : CbcCompareBase(),
36    weight_(weight) ,
37    saveWeight_(0.0),
38    numberSolutions_(0),
39    count_(0),
40    treeSize_(0)
41{
42  test_=this;
43}
44
45
46// Copy constructor
47CbcCompareUser::CbcCompareUser ( const CbcCompareUser & rhs)
48  :CbcCompareBase(rhs)
49
50{
51  weight_=rhs.weight_;
52  saveWeight_ = rhs.saveWeight_;
53  numberSolutions_=rhs.numberSolutions_;
54  count_ = rhs.count_;
55  treeSize_ = rhs.treeSize_;
56}
57
58// Clone
59CbcCompareBase *
60CbcCompareUser::clone() const
61{
62  return new CbcCompareUser(*this);
63}
64
65// Assignment operator
66CbcCompareUser & 
67CbcCompareUser::operator=( const CbcCompareUser& rhs)
68{
69  if (this!=&rhs) {
70    CbcCompareBase::operator=(rhs);
71    weight_=rhs.weight_;
72    saveWeight_ = rhs.saveWeight_;
73    numberSolutions_=rhs.numberSolutions_;
74    count_ = rhs.count_;
75    treeSize_ = rhs.treeSize_;
76  }
77  return *this;
78}
79
80// Destructor
81CbcCompareUser::~CbcCompareUser ()
82{
83}
84// For moment go to default
85#if 0
86// Returns true if y better than x
87bool
88CbcCompareUser::test (CbcNode * x, CbcNode * y)
89{
90  if (x) {
91    if (y) {
92      if (weight_==-1.0) {
93        // before solution
94        /* printf("x %d %d %g, y %d %d %g\n",
95           x->numberUnsatisfied(),x->depth(),x->objectiveValue(),
96           y->numberUnsatisfied(),y->depth(),y->objectiveValue()); */
97        if (x->numberUnsatisfied() > y->numberUnsatisfied())
98          return true;
99        else if (x->numberUnsatisfied() < y->numberUnsatisfied())
100          return false;
101        else
102          return x->depth() < y->depth();
103      } else {
104        // after solution
105        double weight = CoinMax(weight_,0.0);
106        return x->objectiveValue()+ weight*x->numberUnsatisfied() >
107          y->objectiveValue() + weight*y->numberUnsatisfied();
108        //return x->guessedObjectiveValue()>y->guessedObjectiveValue();
109      }
110    } else {
111      return false;
112    }
113  } else {
114    return true;
115  }
116}
117// This allows method to change behavior as it is called
118// after each solution
119void
120CbcCompareUser::newSolution(CbcModel * model,
121                               double objectiveAtContinuous,
122                               int numberInfeasibilitiesAtContinuous)
123{
124  // set to get close to this solution
125  double costPerInteger =
126    (model->getObjValue()-objectiveAtContinuous)/
127    ((double) numberInfeasibilitiesAtContinuous);
128  weight_ = 0.95*costPerInteger;
129  saveWeight_=weight_;
130  if (model->getSolutionCount()==model->getNumberHeuristicSolutions())
131    return; // solution was got by rounding
132  numberSolutions_++;
133  if (numberSolutions_>5)
134    weight_ =0.0; // this searches on objective
135}
136// This allows method to change behavior
137bool
138CbcCompareUser::every1000Nodes(CbcModel * model, int numberNodes)
139{
140  if (numberNodes>10000)
141    weight_ =0.0; // this searches on objective
142  else if (numberNodes==1000&&weight_==-2.0)
143    weight_=-1.0; // Go to depth first
144  // get size of tree
145  treeSize_ = model->tree()->size();
146  if (treeSize_>10000) {
147    // set weight to reduce size most of time
148    if (treeSize_>20000)
149      weight_=-1.0;
150    else if ((numberNodes%4000)!=0)
151      weight_=-1.0;
152    else
153      weight_=saveWeight_;
154  }
155  return numberNodes==11000; // resort if first time
156}
157// Returns true if wants code to do scan with alternate criterion
158bool
159CbcCompareUser::fullScan() const
160{
161  count_++;
162  if (weight_)
163    return (count_%10)==0;
164  else
165    return false;
166}
167// This is alternate test function
168bool
169CbcCompareUser::alternateTest (CbcNode * x, CbcNode * y)
170{
171  if (x) {
172    if (y) {
173      return x->objectiveValue() >
174        y->objectiveValue() ;
175    } else {
176      return false;
177    }
178  } else {
179    return true;
180  }
181}
182#else
183
184// Returns true if y better than x
185bool
186CbcCompareUser::test (CbcNode * x, CbcNode * y)
187{
188  if (weight_==-1.0&&(y->depth()>7||x->depth()>7)) {
189    // before solution
190    /* printf("x %d %d %g, y %d %d %g\n",
191       x->numberUnsatisfied(),x->depth(),x->objectiveValue(),
192       y->numberUnsatisfied(),y->depth(),y->objectiveValue()); */
193    if (x->numberUnsatisfied() > y->numberUnsatisfied()) {
194      return true;
195    } else if (x->numberUnsatisfied() < y->numberUnsatisfied()) {
196      return false;
197    } else {
198      int testX = x->depth();
199      int testY = y->depth();
200      if (testX!=testY)
201        return testX < testY;
202      else
203        return equalityTest(x,y); // so ties will be broken in consistent manner
204    }
205  } else {
206    // after solution
207    double weight = CoinMax(weight_,0.0);
208    double testX =  x->objectiveValue()+ weight*x->numberUnsatisfied();
209    double testY = y->objectiveValue() + weight*y->numberUnsatisfied();
210    if (testX!=testY)
211      return testX > testY;
212    else
213      return equalityTest(x,y); // so ties will be broken in consistent manner
214  }
215}
216// This allows method to change behavior as it is called
217// after each solution
218void
219CbcCompareUser::newSolution(CbcModel * model,
220                               double objectiveAtContinuous,
221                               int numberInfeasibilitiesAtContinuous)
222{
223  if (model->getSolutionCount()==model->getNumberHeuristicSolutions()&&
224      model->getSolutionCount()<5&&model->getNodeCount()<500)
225    return; // solution was got by rounding
226  // set to get close to this solution
227  double costPerInteger =
228    (model->getObjValue()-objectiveAtContinuous)/
229    ((double) numberInfeasibilitiesAtContinuous);
230  weight_ = 0.95*costPerInteger;
231  saveWeight_ = 0.95*weight_;
232  numberSolutions_++;
233  if (numberSolutions_>5)
234    weight_ =0.0; // this searches on objective
235}
236// This allows method to change behavior
237bool
238CbcCompareUser::every1000Nodes(CbcModel * model, int numberNodes)
239{
240  double saveWeight=weight_;
241  int numberNodes1000 = numberNodes/1000;
242  if (numberNodes>10000) {
243    weight_ =0.0; // this searches on objective
244    // but try a bit of other stuff
245    if ((numberNodes1000%4)==1)
246      weight_=saveWeight_;
247  } else if (numberNodes==1000&&weight_==-2.0) {
248    weight_=-1.0; // Go to depth first
249  }
250  // get size of tree
251  treeSize_ = model->tree()->size();
252  if (treeSize_>10000) {
253    int n1 = model->solver()->getNumRows()+model->solver()->getNumCols();
254    int n2 = model->numberObjects();
255    double size = n1*0.1 + n2*2.0;
256    // set weight to reduce size most of time
257    if (treeSize_*size>5.0e7)
258      weight_=-1.0;
259    else if ((numberNodes1000%4)==0&&treeSize_*size>1.0e6)
260      weight_=-1.0;
261    else if ((numberNodes1000%4)==1)
262      weight_=0.0;
263    else
264      weight_=saveWeight_;
265  }
266  return (weight_!=saveWeight);
267}
268// Returns true if wants code to do scan with alternate criterion
269bool
270CbcCompareUser::fullScan() const
271{
272  return false;
273}
274// This is alternate test function
275bool
276CbcCompareUser::alternateTest (CbcNode * x, CbcNode * y)
277{
278  // not used
279  abort();
280  return false;
281}
282#endif
Note: See TracBrowser for help on using the repository browser.