source: trunk/CbcBranchLotsize.cpp @ 74

Last change on this file since 74 was 74, checked in by forrest, 16 years ago

adding something to say if object a column

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