source: trunk/Cbc/src/CbcFollowOn.cpp @ 1899

Last change on this file since 1899 was 1899, checked in by stefan, 5 years ago

fixup svn properties

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