source: stable/2.1/Cbc/src/CbcBranchLotsize.cpp @ 968

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

fix gams tests

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.3 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    assert (nearest>=lower[columnNumber_]&&
498            nearest<=upper[columnNumber_]);
499    solver->setColLower(columnNumber_,nearest);
500    solver->setColUpper(columnNumber_,nearest);
501  } else {
502    // ranges
503    solver->setColLower(columnNumber_,CoinMax(lower[columnNumber_],
504                                              bound_[2*range_]));
505    solver->setColUpper(columnNumber_,CoinMin(upper[columnNumber_],
506                                              bound_[2*range_+1]));
507    if (value>bound_[2*range_+1]) 
508      nearest=bound_[2*range_+1];
509    else if (value<bound_[2*range_]) 
510      nearest = bound_[2*range_];
511    else
512      nearest = value;
513  }
514#ifdef CBC_PRINT
515  // print details
516  printLotsize(value,true,2);
517#endif
518  // Scaling may have moved it a bit
519  // Lotsizing variables could be a lot larger
520#ifndef NDEBUG
521  double integerTolerance = 
522    model_->getDblParam(CbcModel::CbcIntegerTolerance);
523  assert (fabs(value-nearest)<=(100.0+10.0*fabs(nearest))*integerTolerance);
524#endif
525}
526
527// Creates a branching object
528CbcBranchingObject * 
529CbcLotsize::createBranch(int way) 
530{
531  OsiSolverInterface * solver = model_->solver();
532  const double * solution = model_->testSolution();
533  const double * lower = solver->getColLower();
534  const double * upper = solver->getColUpper();
535  double value = solution[columnNumber_];
536  value = CoinMax(value, lower[columnNumber_]);
537  value = CoinMin(value, upper[columnNumber_]);
538  assert (!findRange(value));
539  return new CbcLotsizeBranchingObject(model_,columnNumber_,way,
540                                             value,this);
541}
542
543
544/* Given valid solution (i.e. satisfied) and reduced costs etc
545   returns a branching object which would give a new feasible
546   point in direction reduced cost says would be cheaper.
547   If no feasible point returns null
548*/
549CbcBranchingObject * 
550CbcLotsize::preferredNewFeasible() const
551{
552  OsiSolverInterface * solver = model_->solver();
553
554  assert (findRange(model_->testSolution()[columnNumber_]));
555  double dj = solver->getObjSense()*solver->getReducedCost()[columnNumber_];
556  CbcLotsizeBranchingObject * object = NULL;
557  double lo,up;
558  if (dj>=0.0) {
559    // can we go down
560    if (range_) {
561      // yes
562      if (rangeType_==1) {
563        lo = bound_[range_-1];
564        up = bound_[range_-1];
565      } else {
566        lo = bound_[2*range_-2];
567        up = bound_[2*range_-1];
568      }
569      object = new CbcLotsizeBranchingObject(model_,columnNumber_,-1,
570                                             lo,up);
571    }
572  } else {
573    // can we go up
574    if (range_<numberRanges_-1) {
575      // yes
576      if (rangeType_==1) {
577        lo = bound_[range_+1];
578        up = bound_[range_+1];
579      } else {
580        lo = bound_[2*range_+2];
581        up = bound_[2*range_+3];
582      }
583      object = new CbcLotsizeBranchingObject(model_,columnNumber_,-1,
584                                             lo,up);
585    }
586  }
587  return object;
588}
589 
590/* Given valid solution (i.e. satisfied) and reduced costs etc
591   returns a branching object which would give a new feasible
592   point in direction opposite to one reduced cost says would be cheaper.
593   If no feasible point returns null
594*/
595CbcBranchingObject * 
596CbcLotsize::notPreferredNewFeasible() const 
597{
598  OsiSolverInterface * solver = model_->solver();
599
600#ifndef NDEBUG
601  double value = model_->testSolution()[columnNumber_];
602  double nearest = floor(value+0.5);
603  double integerTolerance = 
604    model_->getDblParam(CbcModel::CbcIntegerTolerance);
605  // Scaling may have moved it a bit
606  // Lotsizing variables could be a lot larger
607  assert (fabs(value-nearest)<=(10.0+10.0*fabs(nearest))*integerTolerance);
608#endif
609  double dj = solver->getObjSense()*solver->getReducedCost()[columnNumber_];
610  CbcLotsizeBranchingObject * object = NULL;
611  double lo,up;
612  if (dj<=0.0) {
613    // can we go down
614    if (range_) {
615      // yes
616      if (rangeType_==1) {
617        lo = bound_[range_-1];
618        up = bound_[range_-1];
619      } else {
620        lo = bound_[2*range_-2];
621        up = bound_[2*range_-1];
622      }
623      object = new CbcLotsizeBranchingObject(model_,columnNumber_,-1,
624                                             lo,up);
625    }
626  } else {
627    // can we go up
628    if (range_<numberRanges_-1) {
629      // yes
630      if (rangeType_==1) {
631        lo = bound_[range_+1];
632        up = bound_[range_+1];
633      } else {
634        lo = bound_[2*range_+2];
635        up = bound_[2*range_+3];
636      }
637      object = new CbcLotsizeBranchingObject(model_,columnNumber_,-1,
638                                             lo,up);
639    }
640  }
641  return object;
642}
643 
644/*
645  Bounds may be tightened, so it may be good to be able to refresh the local
646  copy of the original bounds.
647 */
648void 
649CbcLotsize::resetBounds(const OsiSolverInterface * solver)
650{
651}
652
653
654// Default Constructor
655CbcLotsizeBranchingObject::CbcLotsizeBranchingObject()
656  :CbcBranchingObject()
657{
658  down_[0] = 0.0;
659  down_[1] = 0.0;
660  up_[0] = 0.0;
661  up_[1] = 0.0;
662}
663
664// Useful constructor
665CbcLotsizeBranchingObject::CbcLotsizeBranchingObject (CbcModel * model, 
666                                                      int variable, int way , double value,
667                                                      const CbcLotsize * lotsize)
668  :CbcBranchingObject(model,variable,way,value)
669{
670  int iColumn = lotsize->modelSequence();
671  assert (variable==iColumn);
672  down_[0] = model_->solver()->getColLower()[iColumn];
673  double integerTolerance = 
674    model_->getDblParam(CbcModel::CbcIntegerTolerance);
675  lotsize->floorCeiling(down_[1],up_[0],value,integerTolerance);
676  up_[1] = model->getColUpper()[iColumn];
677}
678// Useful constructor for fixing
679CbcLotsizeBranchingObject::CbcLotsizeBranchingObject (CbcModel * model, 
680                                                      int variable, int way,
681                                                      double lowerValue, 
682                                                      double upperValue)
683  :CbcBranchingObject(model,variable,way,lowerValue)
684{
685  setNumberBranchesLeft(1);
686  down_[0] = lowerValue;
687  down_[1] = upperValue;
688  up_[0] = lowerValue;
689  up_[1] = upperValue;
690}
691 
692
693// Copy constructor
694CbcLotsizeBranchingObject::CbcLotsizeBranchingObject ( const CbcLotsizeBranchingObject & rhs) :CbcBranchingObject(rhs)
695{
696  down_[0] = rhs.down_[0];
697  down_[1] = rhs.down_[1];
698  up_[0] = rhs.up_[0];
699  up_[1] = rhs.up_[1];
700}
701
702// Assignment operator
703CbcLotsizeBranchingObject & 
704CbcLotsizeBranchingObject::operator=( const CbcLotsizeBranchingObject& rhs)
705{
706  if (this != &rhs) {
707    CbcBranchingObject::operator=(rhs);
708    down_[0] = rhs.down_[0];
709    down_[1] = rhs.down_[1];
710    up_[0] = rhs.up_[0];
711    up_[1] = rhs.up_[1];
712  }
713  return *this;
714}
715CbcBranchingObject * 
716CbcLotsizeBranchingObject::clone() const
717{ 
718  return (new CbcLotsizeBranchingObject(*this));
719}
720
721
722// Destructor
723CbcLotsizeBranchingObject::~CbcLotsizeBranchingObject ()
724{
725}
726
727/*
728  Perform a branch by adjusting the bounds of the specified variable. Note
729  that each arm of the branch advances the object to the next arm by
730  advancing the value of way_.
731
732  Providing new values for the variable's lower and upper bounds for each
733  branching direction gives a little bit of additional flexibility and will
734  be easily extensible to multi-way branching.
735*/
736double
737CbcLotsizeBranchingObject::branch()
738{
739  decrementNumberBranchesLeft();
740  int iColumn = variable_;
741  if (way_<0) {
742#ifdef CBC_DEBUG
743  { double olb,oub ;
744    olb = model_->solver()->getColLower()[iColumn] ;
745    oub = model_->solver()->getColUpper()[iColumn] ;
746    printf("branching down on var %d: [%g,%g] => [%g,%g]\n",
747           iColumn,olb,oub,down_[0],down_[1]) ; }
748#endif
749    model_->solver()->setColLower(iColumn,down_[0]);
750    model_->solver()->setColUpper(iColumn,down_[1]);
751    way_=1;
752  } else {
753#ifdef CBC_DEBUG
754  { double olb,oub ;
755    olb = model_->solver()->getColLower()[iColumn] ;
756    oub = model_->solver()->getColUpper()[iColumn] ;
757    printf("branching up on var %d: [%g,%g] => [%g,%g]\n",
758           iColumn,olb,oub,up_[0],up_[1]) ; }
759#endif
760    model_->solver()->setColLower(iColumn,up_[0]);
761    model_->solver()->setColUpper(iColumn,up_[1]);
762    way_=-1;      // Swap direction
763  }
764  return 0.0;
765}
766// Print
767void
768CbcLotsizeBranchingObject::print()
769{
770  int iColumn = variable_;
771  if (way_<0) {
772  { double olb,oub ;
773    olb = model_->solver()->getColLower()[iColumn] ;
774    oub = model_->solver()->getColUpper()[iColumn] ;
775    printf("branching down on var %d: [%g,%g] => [%g,%g]\n",
776           iColumn,olb,oub,down_[0],down_[1]) ; }
777  } else {
778  { double olb,oub ;
779    olb = model_->solver()->getColLower()[iColumn] ;
780    oub = model_->solver()->getColUpper()[iColumn] ;
781    printf("branching up on var %d: [%g,%g] => [%g,%g]\n",
782           iColumn,olb,oub,up_[0],up_[1]) ; }
783  }
784}
785
786/** Compare the \c this with \c brObj. \c this and \c brObj must be os the
787    same type and must have the same original object, but they may have
788    different feasible regions.
789    Return the appropriate CbcRangeCompare value (first argument being the
790    sub/superset if that's the case). In case of overlap (and if \c
791    replaceIfOverlap is true) replace the current branching object with one
792    whose feasible region is the overlap.
793*/
794CbcRangeCompare
795CbcLotsizeBranchingObject::compareBranchingObject
796(const CbcBranchingObject* brObj, const bool replaceIfOverlap)
797{
798  const CbcLotsizeBranchingObject* br =
799    dynamic_cast<const CbcLotsizeBranchingObject*>(brObj);
800  assert(br);
801  double* thisBd = way_ == -1 ? down_ : up_;
802  const double* otherBd = br->way_ == -1 ? br->down_ : br->up_;
803  return CbcCompareRanges(thisBd, otherBd, replaceIfOverlap);
804}
Note: See TracBrowser for help on using the repository browser.