source: trunk/Cbc/src/CbcFollowOn.cpp

Last change on this file was 2467, checked in by unxusr, 5 months ago

spaces after angles

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.7 KB
Line 
1// $Id: CbcFollowOn.cpp 2467 2019-01-03 21:26:29Z tkr $
2// Copyright (C) 2002, 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// Edwin 11/10/2009-- carved out of CbcBranchActual
7
8#if defined(_MSC_VER)
9// Turn off compiler warning about long names
10#pragma warning(disable : 4786)
11#endif
12#include <cassert>
13#include <cstdlib>
14#include <cmath>
15#include <cfloat>
16//#define CBC_DEBUG
17
18#include "CoinTypes.hpp"
19#include "OsiSolverInterface.hpp"
20#include "OsiSolverBranch.hpp"
21#include "CbcModel.hpp"
22#include "CbcMessage.hpp"
23#include "CbcFollowOn.hpp"
24#include "CbcBranchActual.hpp"
25#include "CbcBranchCut.hpp"
26#include "CoinSort.hpp"
27#include "CoinError.hpp"
28
29//##############################################################################
30
31// Default Constructor
32CbcFollowOn::CbcFollowOn()
33  : CbcObject()
34  , rhs_(NULL)
35{
36}
37
38// Useful constructor
39CbcFollowOn::CbcFollowOn(CbcModel *model)
40  : CbcObject(model)
41{
42  assert(model);
43  OsiSolverInterface *solver = model_->solver();
44  matrix_ = *solver->getMatrixByCol();
45  matrix_.removeGaps();
46  matrix_.setExtraGap(0.0);
47  matrixByRow_ = *solver->getMatrixByRow();
48  int numberRows = matrix_.getNumRows();
49
50  rhs_ = new int[numberRows];
51  int i;
52  const double *rowLower = solver->getRowLower();
53  const double *rowUpper = solver->getRowUpper();
54  // Row copy
55  const double *elementByRow = matrixByRow_.getElements();
56  const int *column = matrixByRow_.getIndices();
57  const CoinBigIndex *rowStart = matrixByRow_.getVectorStarts();
58  const int *rowLength = matrixByRow_.getVectorLengths();
59  for (i = 0; i < numberRows; i++) {
60    rhs_[i] = 0;
61    double value = rowLower[i];
62    if (value == rowUpper[i]) {
63      if (floor(value) == value && value >= 1.0 && value < 10.0) {
64        // check elements
65        bool good = true;
66        for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
67          int iColumn = column[j];
68          if (!solver->isBinary(iColumn))
69            good = false;
70          double elValue = elementByRow[j];
71          if (floor(elValue) != elValue || value < 1.0)
72            good = false;
73        }
74        if (good)
75          rhs_[i] = static_cast< int >(value);
76      }
77    }
78  }
79}
80
81// Copy constructor
82CbcFollowOn::CbcFollowOn(const CbcFollowOn &rhs)
83  : CbcObject(rhs)
84  , matrix_(rhs.matrix_)
85  , matrixByRow_(rhs.matrixByRow_)
86{
87  int numberRows = matrix_.getNumRows();
88  rhs_ = CoinCopyOfArray(rhs.rhs_, numberRows);
89}
90
91// Clone
92CbcObject *
93CbcFollowOn::clone() const
94{
95  return new CbcFollowOn(*this);
96}
97
98// Assignment operator
99CbcFollowOn &
100CbcFollowOn::operator=(const CbcFollowOn &rhs)
101{
102  if (this != &rhs) {
103    CbcObject::operator=(rhs);
104    delete[] rhs_;
105    matrix_ = rhs.matrix_;
106    matrixByRow_ = rhs.matrixByRow_;
107    int numberRows = matrix_.getNumRows();
108    rhs_ = CoinCopyOfArray(rhs.rhs_, numberRows);
109  }
110  return *this;
111}
112
113// Destructor
114CbcFollowOn::~CbcFollowOn()
115{
116  delete[] rhs_;
117}
118// As some computation is needed in more than one place - returns row
119int CbcFollowOn::gutsOfFollowOn(int &otherRow, int &preferredWay) const
120{
121  int whichRow = -1;
122  otherRow = -1;
123  int numberRows = matrix_.getNumRows();
124
125  int i;
126  // For sorting
127  int *sort = new int[numberRows];
128  int *isort = new int[numberRows];
129  // Column copy
130  //const double * element = matrix_.getElements();
131  const int *row = matrix_.getIndices();
132  const CoinBigIndex *columnStart = matrix_.getVectorStarts();
133  const int *columnLength = matrix_.getVectorLengths();
134  // Row copy
135  const double *elementByRow = matrixByRow_.getElements();
136  const int *column = matrixByRow_.getIndices();
137  const CoinBigIndex *rowStart = matrixByRow_.getVectorStarts();
138  const int *rowLength = matrixByRow_.getVectorLengths();
139  OsiSolverInterface *solver = model_->solver();
140  const double *columnLower = solver->getColLower();
141  const double *columnUpper = solver->getColUpper();
142  const double *solution = solver->getColSolution();
143  double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);
144  int nSort = 0;
145  for (i = 0; i < numberRows; i++) {
146    if (rhs_[i]) {
147      // check elements
148      double smallest = 1.0e10;
149      double largest = 0.0;
150      int rhsValue = rhs_[i];
151      int number1 = 0;
152      int numberUnsatisfied = 0;
153      for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
154        int iColumn = column[j];
155        double value = elementByRow[j];
156        double solValue = solution[iColumn];
157        if (columnLower[iColumn] != columnUpper[iColumn]) {
158          smallest = CoinMin(smallest, value);
159          largest = CoinMax(largest, value);
160          if (value == 1.0)
161            number1++;
162          if (solValue < 1.0 - integerTolerance && solValue > integerTolerance)
163            numberUnsatisfied++;
164        } else {
165          rhsValue -= static_cast< int >(value * floor(solValue + 0.5));
166        }
167      }
168      if (numberUnsatisfied > 1) {
169        if (smallest < largest) {
170          // probably no good but check a few things
171          assert(largest <= rhsValue);
172          if (number1 == 1 && largest == rhsValue)
173            printf("could fix\n");
174        } else if (largest == rhsValue) {
175          sort[nSort] = i;
176          isort[nSort++] = -numberUnsatisfied;
177        }
178      }
179    }
180  }
181  if (nSort > 1) {
182    CoinSort_2(isort, isort + nSort, sort);
183    CoinZeroN(isort, numberRows);
184    double *other = new double[numberRows];
185    CoinZeroN(other, numberRows);
186    int *which = new int[numberRows];
187    //#define COUNT
188#ifndef COUNT
189    bool beforeSolution = model_->getSolutionCount() == 0;
190#endif
191    for (int k = 0; k < nSort - 1; k++) {
192      i = sort[k];
193      int numberUnsatisfied = 0;
194      int n = 0;
195      CoinBigIndex j;
196      for (j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
197        int iColumn = column[j];
198        if (columnLower[iColumn] != columnUpper[iColumn]) {
199          double solValue = solution[iColumn] - columnLower[iColumn];
200          if (solValue < 1.0 - integerTolerance && solValue > integerTolerance) {
201            numberUnsatisfied++;
202            for (CoinBigIndex jj = columnStart[iColumn]; jj < columnStart[iColumn] + columnLength[iColumn]; jj++) {
203              int iRow = row[jj];
204              if (rhs_[iRow]) {
205                other[iRow] += solValue;
206                if (isort[iRow]) {
207                  isort[iRow]++;
208                } else {
209                  isort[iRow] = 1;
210                  which[n++] = iRow;
211                }
212              }
213            }
214          }
215        }
216      }
217      double total = 0.0;
218      // Take out row
219      double sumThis = other[i];
220      other[i] = 0.0;
221      assert(numberUnsatisfied == isort[i]);
222      // find one nearest half if solution, one if before solution
223      int iBest = -1;
224      double dtarget = 0.5 * total;
225#ifdef COUNT
226      int target = (numberUnsatisfied + 1) >> 1;
227      int best = numberUnsatisfied;
228#else
229      double best;
230      if (beforeSolution)
231        best = dtarget;
232      else
233        best = 1.0e30;
234#endif
235      for (j = 0; j < n; j++) {
236        int iRow = which[j];
237        double dvalue = other[iRow];
238        other[iRow] = 0.0;
239#ifdef COUNT
240        int value = isort[iRow];
241#endif
242        isort[iRow] = 0;
243        if (fabs(dvalue) < 1.0e-8 || fabs(sumThis - dvalue) < 1.0e-8)
244          continue;
245        if (dvalue < integerTolerance || dvalue > 1.0 - integerTolerance)
246          continue;
247#ifdef COUNT
248        if (abs(value - target) < best && value != numberUnsatisfied) {
249          best = abs(value - target);
250          iBest = iRow;
251          if (dvalue < dtarget)
252            preferredWay = 1;
253          else
254            preferredWay = -1;
255        }
256#else
257        if (beforeSolution) {
258          if (fabs(dvalue - dtarget) > best) {
259            best = fabs(dvalue - dtarget);
260            iBest = iRow;
261            if (dvalue < dtarget)
262              preferredWay = 1;
263            else
264              preferredWay = -1;
265          }
266        } else {
267          if (fabs(dvalue - dtarget) < best) {
268            best = fabs(dvalue - dtarget);
269            iBest = iRow;
270            if (dvalue < dtarget)
271              preferredWay = 1;
272            else
273              preferredWay = -1;
274          }
275        }
276#endif
277      }
278      if (iBest >= 0) {
279        whichRow = i;
280        otherRow = iBest;
281        break;
282      }
283    }
284    delete[] which;
285    delete[] other;
286  }
287  delete[] sort;
288  delete[] isort;
289  return whichRow;
290}
291double
292CbcFollowOn::infeasibility(const OsiBranchingInformation * /*info*/,
293  int &preferredWay) const
294{
295  int otherRow = 0;
296  int whichRow = gutsOfFollowOn(otherRow, preferredWay);
297  if (whichRow < 0)
298    return 0.0;
299  else
300    return 2.0 * model_->getDblParam(CbcModel::CbcIntegerTolerance);
301}
302
303// This looks at solution and sets bounds to contain solution
304void CbcFollowOn::feasibleRegion()
305{
306}
307
308CbcBranchingObject *
309CbcFollowOn::createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation * /*info*/, int way)
310{
311  int otherRow = 0;
312  int preferredWay;
313  int whichRow = gutsOfFollowOn(otherRow, preferredWay);
314  assert(way == preferredWay);
315  assert(whichRow >= 0);
316  int numberColumns = matrix_.getNumCols();
317
318  // Column copy
319  //const double * element = matrix_.getElements();
320  const int *row = matrix_.getIndices();
321  const CoinBigIndex *columnStart = matrix_.getVectorStarts();
322  const int *columnLength = matrix_.getVectorLengths();
323  // Row copy
324  //const double * elementByRow = matrixByRow_.getElements();
325  const int *column = matrixByRow_.getIndices();
326  const CoinBigIndex *rowStart = matrixByRow_.getVectorStarts();
327  const int *rowLength = matrixByRow_.getVectorLengths();
328  //OsiSolverInterface * solver = model_->solver();
329  const double *columnLower = solver->getColLower();
330  const double *columnUpper = solver->getColUpper();
331  //const double * solution = solver->getColSolution();
332  int nUp = 0;
333  int nDown = 0;
334  int *upList = new int[numberColumns];
335  int *downList = new int[numberColumns];
336  CoinBigIndex j;
337  for (j = rowStart[whichRow]; j < rowStart[whichRow] + rowLength[whichRow]; j++) {
338    int iColumn = column[j];
339    if (columnLower[iColumn] != columnUpper[iColumn]) {
340      bool up = true;
341      for (CoinBigIndex jj = columnStart[iColumn]; jj < columnStart[iColumn] + columnLength[iColumn]; jj++) {
342        int iRow = row[jj];
343        if (iRow == otherRow) {
344          up = false;
345          break;
346        }
347      }
348      if (up)
349        upList[nUp++] = iColumn;
350      else
351        downList[nDown++] = iColumn;
352    }
353  }
354  //printf("way %d\n",way);
355  // create object
356  //printf("would fix %d down and %d up\n",nDown,nUp);
357  CbcBranchingObject *branch
358    = new CbcFixingBranchingObject(model_, way,
359      nDown, downList, nUp, upList);
360  delete[] upList;
361  delete[] downList;
362  return branch;
363}
364
365//##############################################################################
366
367// Default Constructor
368CbcFixingBranchingObject::CbcFixingBranchingObject()
369  : CbcBranchingObject()
370{
371  numberDown_ = 0;
372  numberUp_ = 0;
373  downList_ = NULL;
374  upList_ = NULL;
375}
376
377// Useful constructor
378CbcFixingBranchingObject::CbcFixingBranchingObject(CbcModel *model,
379  int way,
380  int numberOnDownSide, const int *down,
381  int numberOnUpSide, const int *up)
382  : CbcBranchingObject(model, 0, way, 0.5)
383{
384  numberDown_ = numberOnDownSide;
385  numberUp_ = numberOnUpSide;
386  downList_ = CoinCopyOfArray(down, numberDown_);
387  upList_ = CoinCopyOfArray(up, numberUp_);
388}
389
390// Copy constructor
391CbcFixingBranchingObject::CbcFixingBranchingObject(const CbcFixingBranchingObject &rhs)
392  : CbcBranchingObject(rhs)
393{
394  numberDown_ = rhs.numberDown_;
395  numberUp_ = rhs.numberUp_;
396  downList_ = CoinCopyOfArray(rhs.downList_, numberDown_);
397  upList_ = CoinCopyOfArray(rhs.upList_, numberUp_);
398}
399
400// Assignment operator
401CbcFixingBranchingObject &
402CbcFixingBranchingObject::operator=(const CbcFixingBranchingObject &rhs)
403{
404  if (this != &rhs) {
405    CbcBranchingObject::operator=(rhs);
406    delete[] downList_;
407    delete[] upList_;
408    numberDown_ = rhs.numberDown_;
409    numberUp_ = rhs.numberUp_;
410    downList_ = CoinCopyOfArray(rhs.downList_, numberDown_);
411    upList_ = CoinCopyOfArray(rhs.upList_, numberUp_);
412  }
413  return *this;
414}
415CbcBranchingObject *
416CbcFixingBranchingObject::clone() const
417{
418  return (new CbcFixingBranchingObject(*this));
419}
420
421// Destructor
422CbcFixingBranchingObject::~CbcFixingBranchingObject()
423{
424  delete[] downList_;
425  delete[] upList_;
426}
427double
428CbcFixingBranchingObject::branch()
429{
430  decrementNumberBranchesLeft();
431  OsiSolverInterface *solver = model_->solver();
432  const double *columnLower = solver->getColLower();
433  int i;
434  // *** for way - up means fix all those in up section
435  if (way_ < 0) {
436#ifdef FULL_PRINT
437    printf("Down Fix ");
438#endif
439    //printf("Down Fix %d\n",numberDown_);
440    for (i = 0; i < numberDown_; i++) {
441      int iColumn = downList_[i];
442      model_->solver()->setColUpper(iColumn, columnLower[iColumn]);
443#ifdef FULL_PRINT
444      printf("Setting bound on %d to lower bound\n", iColumn);
445#endif
446    }
447    way_ = 1; // Swap direction
448  } else {
449#ifdef FULL_PRINT
450    printf("Up Fix ");
451#endif
452    //printf("Up Fix %d\n",numberUp_);
453    for (i = 0; i < numberUp_; i++) {
454      int iColumn = upList_[i];
455      model_->solver()->setColUpper(iColumn, columnLower[iColumn]);
456#ifdef FULL_PRINT
457      printf("Setting bound on %d to lower bound\n", iColumn);
458#endif
459    }
460    way_ = -1; // Swap direction
461  }
462#ifdef FULL_PRINT
463  printf("\n");
464#endif
465  return 0.0;
466}
467void CbcFixingBranchingObject::print()
468{
469  int i;
470  // *** for way - up means fix all those in up section
471  if (way_ < 0) {
472    printf("Down Fix ");
473    for (i = 0; i < numberDown_; i++) {
474      int iColumn = downList_[i];
475      printf("%d ", iColumn);
476    }
477  } else {
478    printf("Up Fix ");
479    for (i = 0; i < numberUp_; i++) {
480      int iColumn = upList_[i];
481      printf("%d ", iColumn);
482    }
483  }
484  printf("\n");
485}
486
487/** Compare the original object of \c this with the original object of \c
488    brObj. Assumes that there is an ordering of the original objects.
489    This method should be invoked only if \c this and brObj are of the same
490    type.
491    Return negative/0/positive depending on whether \c this is
492    smaller/same/larger than the argument.
493*/
494int CbcFixingBranchingObject::compareOriginalObject(const CbcBranchingObject * /*brObj*/) const
495{
496  throw("must implement");
497}
498
499/** Compare the \c this with \c brObj. \c this and \c brObj must be os the
500    same type and must have the same original object, but they may have
501    different feasible regions.
502    Return the appropriate CbcRangeCompare value (first argument being the
503    sub/superset if that's the case). In case of overlap (and if \c
504    replaceIfOverlap is true) replace the current branching object with one
505    whose feasible region is the overlap.
506   */
507CbcRangeCompare
508CbcFixingBranchingObject::compareBranchingObject(const CbcBranchingObject * /*brObj*/, const bool /*replaceIfOverlap*/)
509{
510#ifdef JJF_ZERO //ndef NDEBUG
511  const CbcFixingBranchingObject *br = dynamic_cast< const CbcFixingBranchingObject * >(brObj);
512  assert(br);
513#endif
514  // If two FixingBranchingObject's have the same base object then it's pretty
515  // much guaranteed
516  throw("must implement");
517}
518
519//##############################################################################
520
521//##############################################################################
522
523// Default Constructor
524CbcIdiotBranch::CbcIdiotBranch()
525  : CbcObject()
526{
527  id_ = 1000000000 + CutBranchingObj;
528}
529
530// Useful constructor
531CbcIdiotBranch::CbcIdiotBranch(CbcModel *model)
532  : CbcObject(model)
533{
534  assert(model);
535  id_ = 1000000000 + CutBranchingObj;
536}
537
538// Copy constructor
539CbcIdiotBranch::CbcIdiotBranch(const CbcIdiotBranch &rhs)
540  : CbcObject(rhs)
541  , randomNumberGenerator_(rhs.randomNumberGenerator_)
542  , savedRandomNumberGenerator_(rhs.savedRandomNumberGenerator_)
543{
544}
545
546// Clone
547CbcObject *
548CbcIdiotBranch::clone() const
549{
550  return new CbcIdiotBranch(*this);
551}
552
553// Assignment operator
554CbcIdiotBranch &
555CbcIdiotBranch::operator=(const CbcIdiotBranch &rhs)
556{
557  if (this != &rhs) {
558    CbcObject::operator=(rhs);
559    randomNumberGenerator_ = rhs.randomNumberGenerator_;
560    savedRandomNumberGenerator_ = rhs.savedRandomNumberGenerator_;
561  }
562  return *this;
563}
564
565// Destructor
566CbcIdiotBranch::~CbcIdiotBranch()
567{
568}
569double
570CbcIdiotBranch::infeasibility(const OsiBranchingInformation *info,
571  int &preferredWay) const
572{
573  randomNumberGenerator_ = savedRandomNumberGenerator_;
574  double rhs = buildCut(info, 0, preferredWay).ub();
575  double fraction = rhs - floor(rhs);
576  if (fraction > 0.5)
577    fraction = 1.0 - fraction;
578  return fraction;
579}
580
581// This looks at solution and sets bounds to contain solution
582void CbcIdiotBranch::feasibleRegion()
583{
584}
585
586CbcBranchingObject *
587CbcIdiotBranch::createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way)
588{
589  // down and up
590  randomNumberGenerator_ = savedRandomNumberGenerator_;
591  int preferredWay;
592  OsiRowCut downCut = buildCut(info, 0, preferredWay);
593  double rhs = downCut.ub();
594  assert(rhs == downCut.lb());
595  OsiRowCut upCut = downCut;
596  downCut.setUb(floor(rhs));
597  downCut.setLb(-COIN_DBL_MAX);
598  upCut.setLb(ceil(rhs));
599  upCut.setUb(COIN_DBL_MAX);
600  CbcBranchingObject *branch
601    = new CbcCutBranchingObject(model_, downCut, upCut, true);
602  return branch;
603}
604// Initialize for branching
605void CbcIdiotBranch::initializeForBranching(CbcModel *)
606{
607  savedRandomNumberGenerator_ = randomNumberGenerator_;
608}
609// Build "cut"
610OsiRowCut
611CbcIdiotBranch::buildCut(const OsiBranchingInformation *info, int /*type*/, int &preferredWay) const
612{
613  int numberIntegers = model_->numberIntegers();
614  const int *integerVariable = model_->integerVariable();
615  int *which = new int[numberIntegers];
616  double *away = new double[numberIntegers];
617  const double *solution = info->solution_;
618  const double *lower = info->lower_;
619  const double *upper = info->upper_;
620  double integerTolerance = model_->getIntegerTolerance();
621  //int nMax=CoinMin(4,numberIntegers/2);
622  int n = 0;
623  for (int i = 0; i < numberIntegers; i++) {
624    int iColumn = integerVariable[i];
625    double value = solution[iColumn];
626    value = CoinMax(value, lower[iColumn]);
627    value = CoinMin(value, upper[iColumn]);
628    //#define JUST_SMALL
629#ifndef JUST_SMALL
630    double nearest = floor(value + 0.5);
631    if (fabs(value - nearest) > integerTolerance) {
632      double random = 0.0; //0.25*randomNumberGenerator_.randomDouble();
633      away[n] = -fabs(value - nearest) * (1.0 + random);
634      which[n++] = iColumn;
635    }
636#else
637    double distanceDown = value - floor(value);
638    if (distanceDown > 10.0 * integerTolerance && distanceDown < 0.1) {
639      double random = 0.0; //0.25*randomNumberGenerator_.randomDouble();
640      away[n] = distanceDown * (1.0 + random);
641      which[n++] = iColumn;
642    }
643#endif
644  }
645  CoinSort_2(away, away + n, which);
646  OsiRowCut possibleCut;
647  possibleCut.setUb(0.0);
648  if (n > 1) {
649    int nUse = 0;
650    double useRhs = 0.0;
651    double best = 0.0;
652    double rhs = 0.0;
653    double scaleFactor = 1.0;
654    /* should be able to be clever to find best cut
655       maybe don't do if away >0.45
656       maybe don't be random
657       maybe do complete enumeration on biggest k (where sum of k >= 1.0)
658       maybe allow +-1
659     */
660    for (int i = 0; i < n; i++) {
661      int iColumn = which[i];
662      double value = solution[iColumn];
663      value = CoinMax(value, lower[iColumn]);
664      value = CoinMin(value, upper[iColumn]);
665#define PLUS_MINUS
666#ifndef PLUS_MINUS
667      away[i] = 1.0;
668      rhs += value;
669#else
670      if (value - floor(value) <= 0.5) {
671        away[i] = 1.0;
672        rhs += value;
673      } else {
674        away[i] = -1.0;
675        rhs -= value;
676      }
677#endif
678      double nearest = floor(rhs + 0.5);
679      double distance = fabs(rhs - nearest);
680      // scale back
681      distance *= scaleFactor;
682      scaleFactor *= 0.95;
683      if (distance > best) {
684        nUse = i + 1;
685        best = distance;
686        useRhs = rhs;
687      }
688    }
689    // create cut
690    if (nUse > 1) {
691      possibleCut.setRow(nUse, which, away);
692      possibleCut.setLb(useRhs);
693      possibleCut.setUb(useRhs);
694    }
695  }
696  delete[] which;
697  delete[] away;
698  return possibleCut;
699}
700#if 0
701//##############################################################################
702
703// Default Constructor
704CbcBoundingBranchingObject::CbcBoundingBranchingObject()
705        : CbcBranchingObject()
706{
707  branchCut_.setUb(0.0);
708}
709
710// Useful constructor
711CbcBoundingBranchingObject::CbcBoundingBranchingObject (CbcModel * model,
712                                                        int way , const OsiRowCut * cut)
713        : CbcBranchingObject(model, 0, way, 0.5)
714{
715  branchCut_ = *cut;
716}
717
718// Copy constructor
719CbcBoundingBranchingObject::CbcBoundingBranchingObject ( const CbcBoundingBranchingObject & rhs) : CbcBranchingObject(rhs)
720{
721  branchCut_ = rhs.branchCut_;
722}
723
724// Assignment operator
725CbcBoundingBranchingObject &
726CbcBoundingBranchingObject::operator=( const CbcBoundingBranchingObject & rhs)
727{
728    if (this != &rhs) {
729        CbcBranchingObject::operator=(rhs);
730        branchCut_ = rhs.branchCut_;
731    }
732    return *this;
733}
734CbcBranchingObject *
735CbcBoundingBranchingObject::clone() const
736{
737    return (new CbcBoundingBranchingObject(*this));
738}
739
740
741// Destructor
742CbcBoundingBranchingObject::~CbcBoundingBranchingObject ()
743{
744}
745double
746CbcBoundingBranchingObject::branch()
747{
748    decrementNumberBranchesLeft();
749    OsiSolverInterface * solver = model_->solver();
750    const double * columnLower = solver->getColLower();
751    int i;
752    // *** for way - up means bound all those in up section
753    if (way_ < 0) {
754#ifdef FULL_PRINT
755        printf("Down Bound ");
756#endif
757        //printf("Down Bound %d\n",numberDown_);
758        for (i = 0; i < numberDown_; i++) {
759            int iColumn = downList_[i];
760            model_->solver()->setColUpper(iColumn, columnLower[iColumn]);
761#ifdef FULL_PRINT
762            printf("Setting bound on %d to lower bound\n", iColumn);
763#endif
764        }
765        way_ = 1;         // Swap direction
766    } else {
767#ifdef FULL_PRINT
768        printf("Up Bound ");
769#endif
770        //printf("Up Bound %d\n",numberUp_);
771        for (i = 0; i < numberUp_; i++) {
772            int iColumn = upList_[i];
773            model_->solver()->setColUpper(iColumn, columnLower[iColumn]);
774#ifdef FULL_PRINT
775            printf("Setting bound on %d to lower bound\n", iColumn);
776#endif
777        }
778        way_ = -1;        // Swap direction
779    }
780#ifdef FULL_PRINT
781    printf("\n");
782#endif
783    return 0.0;
784}
785void
786CbcBoundingBranchingObject::print()
787{
788  OsiRowCut cut = branchCut_;
789  if (way_ < 0) {
790    printf("Down Fix ");
791    cut.setUb(floor(branchCut_.ub()));
792    cut.setLb(-COIN_DBL_MAX);
793  } else {
794    printf("Up Fix ");
795    cut.setLb(ceil(branchCut_.lb()));
796    cut.setUb(COIN_DBL_MAX);
797  }
798  printf("\n");
799  cut.print();
800}
801
802/** Compare the original object of \c this with the original object of \c
803    brObj. Assumes that there is an ordering of the original objects.
804    This method should be invoked only if \c this and brObj are of the same
805    type.
806    Return negative/0/positive depending on whether \c this is
807    smaller/same/larger than the argument.
808*/
809int
810CbcBoundingBranchingObject::compareOriginalObject
811(const CbcBranchingObject* /*brObj*/) const
812{
813    throw("must implement");
814}
815
816/** Compare the \c this with \c brObj. \c this and \c brObj must be os the
817    same type and must have the same original object, but they may have
818    different feasible regions.
819    Return the appropriate CbcRangeCompare value (first argument being the
820    sub/superset if that's the case). In case of overlap (and if \c
821    replaceIfOverlap is true) replace the current branching object with one
822    whose feasible region is the overlap.
823   */
824CbcRangeCompare
825CbcBoundingBranchingObject::compareBranchingObject
826(const CbcBranchingObject* /*brObj*/, const bool /*replaceIfOverlap*/)
827{
828#ifdef JJF_ZERO //ndef NDEBUG
829    const CbcBoundingBranchingObject* br =
830        dynamic_cast<const CbcBoundingBranchingObject*>(brObj);
831    assert(br);
832#endif
833    // If two BoundingBranchingObject's have the same base object then it's pretty
834    // much guaranteed
835    throw("must implement");
836}
837
838//##############################################################################
839
840#endif
841
842/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
843*/
Note: See TracBrowser for help on using the repository browser.