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

Last change on this file since 1574 was 1574, checked in by lou, 8 years ago

Change to EPL license notice.

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