source: trunk/Cbc/src/CbcBranchLotsize.cpp @ 912

Last change on this file since 912 was 912, checked in by ladanyi, 11 years ago

Incorporated changes from branches/heur

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.1 KB
Line 
1// Copyright (C) 2002, 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 <cstdlib>
9#include <cmath>
10#include <cfloat>
11
12#include "OsiSolverInterface.hpp"
13#include "CbcModel.hpp"
14#include "CbcMessage.hpp"
15#include "CbcBranchLotsize.hpp"
16#include "CoinSort.hpp"
17#include "CoinError.hpp"
18/*
19  CBC_PRINT 1 just does sanity checks - no printing
20            2
21*/
22//#define CBC_PRINT 1
23// First/last variable to print info on
24#if CBC_PRINT
25// preset does all - change to x,x to just do x
26static int firstPrint=0;
27static int lastPrint=1000000;
28static CbcModel * saveModel=NULL;
29#endif
30// Just for debug (CBC_PRINT defined in CbcBranchLotsize.cpp)
31void 
32CbcLotsize::printLotsize(double value,bool condition,int type) const
33{
34#if CBC_PRINT
35  if (columnNumber_>=firstPrint&&columnNumber_<=lastPrint) {
36    int printIt = CBC_PRINT-1;
37    // Get details
38    OsiSolverInterface * solver = saveModel->solver();
39    double currentLower = solver->getColLower()[columnNumber_];
40    double currentUpper = solver->getColUpper()[columnNumber_];
41    int i;
42    // See if in a valid range (with two tolerances)
43    bool inRange=false;
44    bool inRange2=false;
45    double integerTolerance = 
46      model_->getDblParam(CbcModel::CbcIntegerTolerance);
47    // increase if type 2
48    if (type==2) {
49      integerTolerance *= 100.0;
50      type=0;
51      printIt=2; // always print
52    }
53    // bounds should match some bound
54    int rangeL=-1;
55    int rangeU=-1;
56    if (rangeType_==1) {
57      for (i=0;i<numberRanges_;i++) {
58        if (fabs(currentLower-bound_[i])<1.0e-12)
59          rangeL=i;
60        if (fabs(currentUpper-bound_[i])<1.0e-12)
61          rangeU=i;
62        if (fabs(value-bound_[i])<integerTolerance)
63          inRange=true;
64        if (fabs(value-bound_[i])<1.0e8)
65          inRange2=true;
66      }
67    } else {
68      for (i=0;i<numberRanges_;i++) {
69        if (fabs(currentLower-bound_[2*i])<1.0e-12)
70          rangeL=i;
71        if (fabs(currentUpper-bound_[2*i+1])<1.0e-12)
72          rangeU=i;
73        if (value>bound_[2*i]-integerTolerance&&
74            value<bound_[2*i+1]+integerTolerance)
75          inRange=true;
76        if (value>bound_[2*i]-integerTolerance&&
77            value<bound_[2*i+1]+integerTolerance)
78          inRange=true;
79      }
80    }
81    assert (rangeL>=0&&rangeU>=0);
82    bool abortIt=false;
83    switch (type) {
84      // returning from findRange (fall through to just check)
85    case 0:
86      if (printIt) {
87        printf("findRange returns %s for column %d and value %g",
88               condition ? "true" : "false",columnNumber_,value);
89        if (printIt>1)
90          printf(" LP bounds %g, %g",currentLower,currentUpper);
91        printf("\n");
92      }
93      // Should match
94    case 1:
95      if (inRange!=condition) {
96        printIt=2;
97        abortIt=true;
98      }
99      break;
100      //
101    case 2:
102      break;
103      //
104    case 3:
105      break;
106      //
107    case 4:
108      break;
109    }
110  }
111#endif
112}
113/** Default Constructor
114
115*/
116CbcLotsize::CbcLotsize ()
117  : CbcObject(),
118    columnNumber_(-1),
119    rangeType_(0),
120    numberRanges_(0),
121    largestGap_(0),
122    bound_(NULL),
123    range_(0)
124{
125}
126
127/** Useful constructor
128
129  Loads actual upper & lower bounds for the specified variable.
130*/
131CbcLotsize::CbcLotsize (CbcModel * model, 
132                                    int iColumn, int numberPoints,
133                        const double * points, bool range)
134  : CbcObject(model)
135{
136#if CBC_PRINT
137  if (!saveModel)
138    saveModel=model;
139#endif
140  assert (numberPoints>0);
141  columnNumber_ = iColumn ;
142  // and set id so can be used for branching
143  id_=iColumn;
144  // sort ranges
145  int * sort = new int[numberPoints];
146  double * weight = new double [numberPoints];
147  int i;
148  if (range) {
149    rangeType_=2;
150  } else {
151    rangeType_=1;
152  }
153  for (i=0;i<numberPoints;i++) {
154    sort[i]=i;
155    weight[i]=points[i*rangeType_];
156  }
157  CoinSort_2(weight,weight+numberPoints,sort);
158  numberRanges_=1;
159  largestGap_=0;
160  if (rangeType_==1) {
161    bound_ = new double[numberPoints+1];
162    bound_[0]=weight[0];
163    for (i=1;i<numberPoints;i++) {
164      if (weight[i]!=weight[i-1]) 
165        bound_[numberRanges_++]=weight[i];
166    }
167    // and for safety
168    bound_[numberRanges_]=bound_[numberRanges_-1];
169    for (i=1;i<numberRanges_;i++) {
170      largestGap_ = CoinMax(largestGap_,bound_[i]-bound_[i-1]);
171    }
172  } else {
173    bound_ = new double[2*numberPoints+2];
174    bound_[0]=points[sort[0]*2];
175    bound_[1]=points[sort[0]*2+1];
176    double lo=bound_[0];
177    double hi=bound_[1];
178    assert (hi>=lo);
179    for (i=1;i<numberPoints;i++) {
180      double thisLo =points[sort[i]*2];
181      double thisHi =points[sort[i]*2+1];
182      assert (thisHi>=thisLo);
183      if (thisLo>hi) {
184        bound_[2*numberRanges_]=thisLo;
185        bound_[2*numberRanges_+1]=thisHi;
186        numberRanges_++;
187        lo=thisLo;
188        hi=thisHi;
189      } else {
190        //overlap
191        hi=CoinMax(hi,thisHi);
192        bound_[2*numberRanges_-1]=hi;
193      }
194    }
195    // and for safety
196    bound_[2*numberRanges_]=bound_[2*numberRanges_-2];
197    bound_[2*numberRanges_+1]=bound_[2*numberRanges_-1];
198    for (i=1;i<numberRanges_;i++) {
199      largestGap_ = CoinMax(largestGap_,bound_[2*i]-bound_[2*i-1]);
200    }
201  }
202  delete [] sort;
203  delete [] weight;
204  range_=0;
205}
206
207// Copy constructor
208CbcLotsize::CbcLotsize ( const CbcLotsize & rhs)
209  :CbcObject(rhs)
210
211{
212  columnNumber_ = rhs.columnNumber_;
213  rangeType_ = rhs.rangeType_;
214  numberRanges_ = rhs.numberRanges_;
215  range_ = rhs.range_;
216  largestGap_ = rhs.largestGap_;
217  if (numberRanges_) {
218    assert (rangeType_>0&&rangeType_<3);
219    bound_= new double [(numberRanges_+1)*rangeType_];
220    memcpy(bound_,rhs.bound_,(numberRanges_+1)*rangeType_*sizeof(double));
221  } else {
222    bound_=NULL;
223  }
224}
225
226// Clone
227CbcObject *
228CbcLotsize::clone() const
229{
230  return new CbcLotsize(*this);
231}
232
233// Assignment operator
234CbcLotsize & 
235CbcLotsize::operator=( const CbcLotsize& rhs)
236{
237  if (this!=&rhs) {
238    CbcObject::operator=(rhs);
239    columnNumber_ = rhs.columnNumber_;
240    rangeType_ = rhs.rangeType_;
241    numberRanges_ = rhs.numberRanges_;
242    largestGap_ = rhs.largestGap_;
243    delete [] bound_;
244    range_ = rhs.range_;
245    if (numberRanges_) {
246      assert (rangeType_>0&&rangeType_<3);
247      bound_= new double [(numberRanges_+1)*rangeType_];
248      memcpy(bound_,rhs.bound_,(numberRanges_+1)*rangeType_*sizeof(double));
249    } else {
250      bound_=NULL;
251    }
252  }
253  return *this;
254}
255
256// Destructor
257CbcLotsize::~CbcLotsize ()
258{
259  delete [] bound_;
260}
261/* Finds range of interest so value is feasible in range range_ or infeasible
262   between hi[range_] and lo[range_+1].  Returns true if feasible.
263*/
264bool 
265CbcLotsize::findRange(double value) const
266{
267  assert (range_>=0&&range_<numberRanges_+1);
268  double integerTolerance = 
269    model_->getDblParam(CbcModel::CbcIntegerTolerance);
270  int iLo;
271  int iHi;
272  double infeasibility=0.0;
273  if (rangeType_==1) {
274    if (value<bound_[range_]-integerTolerance) {
275      iLo=0;
276      iHi=range_-1;
277    } else if (value<bound_[range_]+integerTolerance) {
278#if CBC_PRINT
279      printLotsize(value,true,0);
280#endif
281      return true;
282    } else if (value<bound_[range_+1]-integerTolerance) {
283#ifdef CBC_PRINT
284      printLotsize(value,false,0);
285#endif
286      return false;
287    } else {
288      iLo=range_+1;
289      iHi=numberRanges_-1;
290    }
291    // check lo and hi
292    bool found=false;
293    if (value>bound_[iLo]-integerTolerance&&value<bound_[iLo+1]+integerTolerance) {
294      range_=iLo;
295      found=true;
296    } else if (value>bound_[iHi]-integerTolerance&&value<bound_[iHi+1]+integerTolerance) {
297      range_=iHi;
298      found=true;
299    } else {
300      range_ = (iLo+iHi)>>1;
301    }
302    //points
303    while (!found) {
304      if (value<bound_[range_]) {
305        if (value>=bound_[range_-1]) {
306          // found
307          range_--;
308          break;
309        } else {
310          iHi = range_;
311        }
312      } else {
313        if (value<bound_[range_+1]) {
314          // found
315          break;
316        } else {
317          iLo = range_;
318        }
319      }
320      range_ = (iLo+iHi)>>1;
321    }
322    if (value-bound_[range_]<=bound_[range_+1]-value) {
323      infeasibility = value-bound_[range_];
324    } else {
325      infeasibility = bound_[range_+1]-value;
326      if (infeasibility<integerTolerance)
327        range_++;
328    }
329#ifdef CBC_PRINT
330    printLotsize(value,(infeasibility<integerTolerance),0);
331#endif
332    return (infeasibility<integerTolerance);
333  } else {
334    // ranges
335    if (value<bound_[2*range_]-integerTolerance) {
336      iLo=0;
337      iHi=range_-1;
338    } else if (value<bound_[2*range_+1]+integerTolerance) {
339#ifdef CBC_PRINT
340      printLotsize(value,true,0);
341#endif
342      return true;
343    } else if (value<bound_[2*range_+2]-integerTolerance) {
344#ifdef CBC_PRINT
345      printLotsize(value,false,0);
346#endif
347      return false;
348    } else {
349      iLo=range_+1;
350      iHi=numberRanges_-1;
351    }
352    // check lo and hi
353    bool found=false;
354    if (value>bound_[2*iLo]-integerTolerance&&value<bound_[2*iLo+2]-integerTolerance) {
355      range_=iLo;
356      found=true;
357    } else if (value>=bound_[2*iHi]-integerTolerance) {
358      range_=iHi;
359      found=true;
360    } else {
361      range_ = (iLo+iHi)>>1;
362    }
363    //points
364    while (!found) {
365      if (value<bound_[2*range_]) {
366        if (value>=bound_[2*range_-2]) {
367          // found
368          range_--;
369          break;
370        } else {
371          iHi = range_;
372        }
373      } else {
374        if (value<bound_[2*range_+2]) {
375          // found
376          break;
377        } else {
378          iLo = range_;
379        }
380      }
381      range_ = (iLo+iHi)>>1;
382    }
383    if (value>=bound_[2*range_]-integerTolerance&&value<=bound_[2*range_+1]+integerTolerance)
384      infeasibility=0.0;
385    else if (value-bound_[2*range_+1]<bound_[2*range_+2]-value) {
386      infeasibility = value-bound_[2*range_+1];
387    } else {
388      infeasibility = bound_[2*range_+2]-value;
389    }
390#ifdef CBC_PRINT
391    printLotsize(value,(infeasibility<integerTolerance),0);
392#endif
393    return (infeasibility<integerTolerance);
394  }
395}
396/* Returns floor and ceiling
397 */
398void 
399CbcLotsize::floorCeiling(double & floorLotsize, double & ceilingLotsize, double value,
400                         double tolerance) const
401{
402  bool feasible=findRange(value);
403  if (rangeType_==1) {
404    floorLotsize=bound_[range_];
405    ceilingLotsize=bound_[range_+1];
406    // may be able to adjust
407    if (feasible&&fabs(value-floorLotsize)>fabs(value-ceilingLotsize)) {
408      floorLotsize=bound_[range_+1];
409      ceilingLotsize=bound_[range_+2];
410    }
411  } else {
412    // ranges
413    assert (value>=bound_[2*range_+1]);
414    floorLotsize=bound_[2*range_+1];
415    ceilingLotsize=bound_[2*range_+2];
416  }
417}
418
419// Infeasibility - large is 0.5
420double 
421CbcLotsize::infeasibility(int & preferredWay) const
422{
423  OsiSolverInterface * solver = model_->solver();
424  const double * solution = model_->testSolution();
425  const double * lower = solver->getColLower();
426  const double * upper = solver->getColUpper();
427  double value = solution[columnNumber_];
428  value = CoinMax(value, lower[columnNumber_]);
429  value = CoinMin(value, upper[columnNumber_]);
430  double integerTolerance = 
431    model_->getDblParam(CbcModel::CbcIntegerTolerance);
432  /*printf("%d %g %g %g %g\n",columnNumber_,value,lower[columnNumber_],
433    solution[columnNumber_],upper[columnNumber_]);*/
434  assert (value>=bound_[0]-integerTolerance
435          &&value<=bound_[rangeType_*numberRanges_-1]+integerTolerance);
436  double infeasibility=0.0;
437  bool feasible = findRange(value);
438  if (!feasible) {
439    if (rangeType_==1) {
440      if (value-bound_[range_]<bound_[range_+1]-value) {
441        preferredWay=-1;
442        infeasibility = value-bound_[range_];
443      } else {
444        preferredWay=1;
445        infeasibility = bound_[range_+1]-value;
446      }
447    } else {
448      // ranges
449      if (value-bound_[2*range_+1]<bound_[2*range_+2]-value) {
450        preferredWay=-1;
451        infeasibility = value-bound_[2*range_+1];
452      } else {
453        preferredWay=1;
454        infeasibility = bound_[2*range_+2]-value;
455      }
456    }
457  } else {
458    // always satisfied
459    preferredWay=-1;
460  }
461  if (infeasibility<integerTolerance)
462    infeasibility=0.0;
463  else
464    infeasibility /= largestGap_;
465#ifdef CBC_PRINT
466    printLotsize(value,infeasibility,1);
467#endif
468  return infeasibility;
469}
470/* Column number if single column object -1 otherwise,
471   so returns >= 0
472   Used by heuristics
473*/
474int 
475CbcLotsize::columnNumber() const
476{
477  return columnNumber_;
478}
479// This looks at solution and sets bounds to contain solution
480/** More precisely: it first forces the variable within the existing
481    bounds, and then tightens the bounds to make sure the variable is feasible
482*/
483void 
484CbcLotsize::feasibleRegion()
485{
486  OsiSolverInterface * solver = model_->solver();
487  const double * lower = solver->getColLower();
488  const double * upper = solver->getColUpper();
489  const double * solution = model_->testSolution();
490  double value = solution[columnNumber_];
491  value = CoinMax(value, lower[columnNumber_]);
492  value = CoinMin(value, upper[columnNumber_]);
493  findRange(value);
494  double nearest;
495  if (rangeType_==1) {
496    nearest = bound_[range_];
497    solver->setColLower(columnNumber_,nearest);
498    solver->setColUpper(columnNumber_,nearest);
499  } else {
500    // ranges
501    solver->setColLower(columnNumber_,bound_[2*range_]);
502    solver->setColUpper(columnNumber_,bound_[2*range_+1]);
503    if (value>bound_[2*range_+1]) 
504      nearest=bound_[2*range_+1];
505    else if (value<bound_[2*range_]) 
506      nearest = bound_[2*range_];
507    else
508      nearest = value;
509  }
510#ifdef CBC_PRINT
511  // print details
512  printLotsize(value,true,2);
513#endif
514  // Scaling may have moved it a bit
515  // Lotsizing variables could be a lot larger
516#ifndef NDEBUG
517  double integerTolerance = 
518    model_->getDblParam(CbcModel::CbcIntegerTolerance);
519  assert (fabs(value-nearest)<=(100.0+10.0*fabs(nearest))*integerTolerance);
520#endif
521}
522
523// Creates a branching object
524CbcBranchingObject * 
525CbcLotsize::createBranch(int way) 
526{
527  OsiSolverInterface * solver = model_->solver();
528  const double * solution = model_->testSolution();
529  const double * lower = solver->getColLower();
530  const double * upper = solver->getColUpper();
531  double value = solution[columnNumber_];
532  value = CoinMax(value, lower[columnNumber_]);
533  value = CoinMin(value, upper[columnNumber_]);
534  assert (!findRange(value));
535  return new CbcLotsizeBranchingObject(model_,columnNumber_,way,
536                                             value,this);
537}
538
539
540/* Given valid solution (i.e. satisfied) and reduced costs etc
541   returns a branching object which would give a new feasible
542   point in direction reduced cost says would be cheaper.
543   If no feasible point returns null
544*/
545CbcBranchingObject * 
546CbcLotsize::preferredNewFeasible() const
547{
548  OsiSolverInterface * solver = model_->solver();
549
550  assert (findRange(model_->testSolution()[columnNumber_]));
551  double dj = solver->getObjSense()*solver->getReducedCost()[columnNumber_];
552  CbcLotsizeBranchingObject * object = NULL;
553  double lo,up;
554  if (dj>=0.0) {
555    // can we go down
556    if (range_) {
557      // yes
558      if (rangeType_==1) {
559        lo = bound_[range_-1];
560        up = bound_[range_-1];
561      } else {
562        lo = bound_[2*range_-2];
563        up = bound_[2*range_-1];
564      }
565      object = new CbcLotsizeBranchingObject(model_,columnNumber_,-1,
566                                             lo,up);
567    }
568  } else {
569    // can we go up
570    if (range_<numberRanges_-1) {
571      // yes
572      if (rangeType_==1) {
573        lo = bound_[range_+1];
574        up = bound_[range_+1];
575      } else {
576        lo = bound_[2*range_+2];
577        up = bound_[2*range_+3];
578      }
579      object = new CbcLotsizeBranchingObject(model_,columnNumber_,-1,
580                                             lo,up);
581    }
582  }
583  return object;
584}
585 
586/* Given valid solution (i.e. satisfied) and reduced costs etc
587   returns a branching object which would give a new feasible
588   point in direction opposite to one reduced cost says would be cheaper.
589   If no feasible point returns null
590*/
591CbcBranchingObject * 
592CbcLotsize::notPreferredNewFeasible() const 
593{
594  OsiSolverInterface * solver = model_->solver();
595
596#ifndef NDEBUG
597  double value = model_->testSolution()[columnNumber_];
598  double nearest = floor(value+0.5);
599  double integerTolerance = 
600    model_->getDblParam(CbcModel::CbcIntegerTolerance);
601  // Scaling may have moved it a bit
602  // Lotsizing variables could be a lot larger
603  assert (fabs(value-nearest)<=(10.0+10.0*fabs(nearest))*integerTolerance);
604#endif
605  double dj = solver->getObjSense()*solver->getReducedCost()[columnNumber_];
606  CbcLotsizeBranchingObject * object = NULL;
607  double lo,up;
608  if (dj<=0.0) {
609    // can we go down
610    if (range_) {
611      // yes
612      if (rangeType_==1) {
613        lo = bound_[range_-1];
614        up = bound_[range_-1];
615      } else {
616        lo = bound_[2*range_-2];
617        up = bound_[2*range_-1];
618      }
619      object = new CbcLotsizeBranchingObject(model_,columnNumber_,-1,
620                                             lo,up);
621    }
622  } else {
623    // can we go up
624    if (range_<numberRanges_-1) {
625      // yes
626      if (rangeType_==1) {
627        lo = bound_[range_+1];
628        up = bound_[range_+1];
629      } else {
630        lo = bound_[2*range_+2];
631        up = bound_[2*range_+3];
632      }
633      object = new CbcLotsizeBranchingObject(model_,columnNumber_,-1,
634                                             lo,up);
635    }
636  }
637  return object;
638}
639 
640/*
641  Bounds may be tightened, so it may be good to be able to refresh the local
642  copy of the original bounds.
643 */
644void 
645CbcLotsize::resetBounds(const OsiSolverInterface * solver)
646{
647}
648
649
650// Default Constructor
651CbcLotsizeBranchingObject::CbcLotsizeBranchingObject()
652  :CbcBranchingObject()
653{
654  down_[0] = 0.0;
655  down_[1] = 0.0;
656  up_[0] = 0.0;
657  up_[1] = 0.0;
658}
659
660// Useful constructor
661CbcLotsizeBranchingObject::CbcLotsizeBranchingObject (CbcModel * model, 
662                                                      int variable, int way , double value,
663                                                      const CbcLotsize * lotsize)
664  :CbcBranchingObject(model,variable,way,value)
665{
666  int iColumn = lotsize->modelSequence();
667  assert (variable==iColumn);
668  down_[0] = model_->solver()->getColLower()[iColumn];
669  double integerTolerance = 
670    model_->getDblParam(CbcModel::CbcIntegerTolerance);
671  lotsize->floorCeiling(down_[1],up_[0],value,integerTolerance);
672  up_[1] = model->getColUpper()[iColumn];
673}
674// Useful constructor for fixing
675CbcLotsizeBranchingObject::CbcLotsizeBranchingObject (CbcModel * model, 
676                                                      int variable, int way,
677                                                      double lowerValue, 
678                                                      double upperValue)
679  :CbcBranchingObject(model,variable,way,lowerValue)
680{
681  setNumberBranchesLeft(1);
682  down_[0] = lowerValue;
683  down_[1] = upperValue;
684  up_[0] = lowerValue;
685  up_[1] = upperValue;
686}
687 
688
689// Copy constructor
690CbcLotsizeBranchingObject::CbcLotsizeBranchingObject ( const CbcLotsizeBranchingObject & rhs) :CbcBranchingObject(rhs)
691{
692  down_[0] = rhs.down_[0];
693  down_[1] = rhs.down_[1];
694  up_[0] = rhs.up_[0];
695  up_[1] = rhs.up_[1];
696}
697
698// Assignment operator
699CbcLotsizeBranchingObject & 
700CbcLotsizeBranchingObject::operator=( const CbcLotsizeBranchingObject& rhs)
701{
702  if (this != &rhs) {
703    CbcBranchingObject::operator=(rhs);
704    down_[0] = rhs.down_[0];
705    down_[1] = rhs.down_[1];
706    up_[0] = rhs.up_[0];
707    up_[1] = rhs.up_[1];
708  }
709  return *this;
710}
711CbcBranchingObject * 
712CbcLotsizeBranchingObject::clone() const
713{ 
714  return (new CbcLotsizeBranchingObject(*this));
715}
716
717
718// Destructor
719CbcLotsizeBranchingObject::~CbcLotsizeBranchingObject ()
720{
721}
722
723/*
724  Perform a branch by adjusting the bounds of the specified variable. Note
725  that each arm of the branch advances the object to the next arm by
726  advancing the value of way_.
727
728  Providing new values for the variable's lower and upper bounds for each
729  branching direction gives a little bit of additional flexibility and will
730  be easily extensible to multi-way branching.
731*/
732double
733CbcLotsizeBranchingObject::branch()
734{
735  decrementNumberBranchesLeft();
736  int iColumn = variable_;
737  if (way_<0) {
738#ifdef CBC_DEBUG
739  { double olb,oub ;
740    olb = model_->solver()->getColLower()[iColumn] ;
741    oub = model_->solver()->getColUpper()[iColumn] ;
742    printf("branching down on var %d: [%g,%g] => [%g,%g]\n",
743           iColumn,olb,oub,down_[0],down_[1]) ; }
744#endif
745    model_->solver()->setColLower(iColumn,down_[0]);
746    model_->solver()->setColUpper(iColumn,down_[1]);
747    way_=1;
748  } else {
749#ifdef CBC_DEBUG
750  { double olb,oub ;
751    olb = model_->solver()->getColLower()[iColumn] ;
752    oub = model_->solver()->getColUpper()[iColumn] ;
753    printf("branching up on var %d: [%g,%g] => [%g,%g]\n",
754           iColumn,olb,oub,up_[0],up_[1]) ; }
755#endif
756    model_->solver()->setColLower(iColumn,up_[0]);
757    model_->solver()->setColUpper(iColumn,up_[1]);
758    way_=-1;      // Swap direction
759  }
760  return 0.0;
761}
762// Print
763void
764CbcLotsizeBranchingObject::print()
765{
766  int iColumn = variable_;
767  if (way_<0) {
768  { double olb,oub ;
769    olb = model_->solver()->getColLower()[iColumn] ;
770    oub = model_->solver()->getColUpper()[iColumn] ;
771    printf("branching down on var %d: [%g,%g] => [%g,%g]\n",
772           iColumn,olb,oub,down_[0],down_[1]) ; }
773  } else {
774  { double olb,oub ;
775    olb = model_->solver()->getColLower()[iColumn] ;
776    oub = model_->solver()->getColUpper()[iColumn] ;
777    printf("branching up on var %d: [%g,%g] => [%g,%g]\n",
778           iColumn,olb,oub,up_[0],up_[1]) ; }
779  }
780}
781
782/** Compare the \c this with \c brObj. \c this and \c brObj must be os the
783    same type and must have the same original object, but they may have
784    different feasible regions.
785    Return the appropriate CbcRangeCompare value (first argument being the
786    sub/superset if that's the case). In case of overlap (and if \c
787    replaceIfOverlap is true) replace the current branching object with one
788    whose feasible region is the overlap.
789*/
790CbcRangeCompare
791CbcLotsizeBranchingObject::compareBranchingObject
792(const CbcBranchingObject* brObj, const bool replaceIfOverlap)
793{
794  const CbcLotsizeBranchingObject* br =
795    dynamic_cast<const CbcLotsizeBranchingObject*>(brObj);
796  assert(br);
797  double* thisBd = way_ == -1 ? down_ : up_;
798  const double* otherBd = br->way_ == -1 ? br->down_ : br->up_;
799  return CbcCompareRanges(thisBd, otherBd, replaceIfOverlap);
800}
Note: See TracBrowser for help on using the repository browser.