source: trunk/Cbc/src/CbcSimpleInteger.cpp @ 1424

Last change on this file since 1424 was 1393, checked in by lou, 10 years ago

Mark #if 0 with JJF_ZERO and #if 1 with JJF_ONE as a historical reference
point.

File size: 22.1 KB
Line 
1// Edwin 11/9/2009-- carved out of CbcBranchActual
2#if defined(_MSC_VER)
3// Turn off compiler warning about long names
4#  pragma warning(disable:4786)
5#endif
6#include <cassert>
7#include <cstdlib>
8#include <cmath>
9#include <cfloat>
10//#define CBC_DEBUG
11
12#include "CoinTypes.hpp"
13#include "OsiSolverInterface.hpp"
14#include "OsiSolverBranch.hpp"
15#include "CbcModel.hpp"
16#include "CbcMessage.hpp"
17#include "CbcSimpleInteger.hpp"
18#include "CbcBranchActual.hpp"
19#include "CoinSort.hpp"
20#include "CoinError.hpp"
21
22
23//##############################################################################
24
25/** Default Constructor
26
27  Equivalent to an unspecified binary variable.
28*/
29CbcSimpleInteger::CbcSimpleInteger ()
30        : CbcObject(),
31        originalLower_(0.0),
32        originalUpper_(1.0),
33        breakEven_(0.5),
34        columnNumber_(-1),
35        preferredWay_(0)
36{
37}
38
39/** Useful constructor
40
41  Loads actual upper & lower bounds for the specified variable.
42*/
43CbcSimpleInteger::CbcSimpleInteger ( CbcModel * model, int iColumn, double breakEven)
44        : CbcObject(model)
45{
46    columnNumber_ = iColumn ;
47    originalLower_ = model->solver()->getColLower()[columnNumber_] ;
48    originalUpper_ = model->solver()->getColUpper()[columnNumber_] ;
49    breakEven_ = breakEven;
50    assert (breakEven_ > 0.0 && breakEven_ < 1.0);
51    preferredWay_ = 0;
52}
53
54
55// Copy constructor
56CbcSimpleInteger::CbcSimpleInteger ( const CbcSimpleInteger & rhs)
57        : CbcObject(rhs)
58
59{
60    columnNumber_ = rhs.columnNumber_;
61    originalLower_ = rhs.originalLower_;
62    originalUpper_ = rhs.originalUpper_;
63    breakEven_ = rhs.breakEven_;
64    preferredWay_ = rhs.preferredWay_;
65}
66
67// Clone
68CbcObject *
69CbcSimpleInteger::clone() const
70{
71    return new CbcSimpleInteger(*this);
72}
73
74// Assignment operator
75CbcSimpleInteger &
76CbcSimpleInteger::operator=( const CbcSimpleInteger & rhs)
77{
78    if (this != &rhs) {
79        CbcObject::operator=(rhs);
80        columnNumber_ = rhs.columnNumber_;
81        originalLower_ = rhs.originalLower_;
82        originalUpper_ = rhs.originalUpper_;
83        breakEven_ = rhs.breakEven_;
84        preferredWay_ = rhs.preferredWay_;
85    }
86    return *this;
87}
88
89// Destructor
90CbcSimpleInteger::~CbcSimpleInteger ()
91{
92}
93// Construct an OsiSimpleInteger object
94OsiSimpleInteger *
95CbcSimpleInteger::osiObject() const
96{
97    OsiSimpleInteger * obj = new OsiSimpleInteger(columnNumber_,
98            originalLower_, originalUpper_);
99    obj->setPriority(priority());
100    return obj;
101}
102double
103CbcSimpleInteger::infeasibility(const OsiBranchingInformation * info,
104                                int &preferredWay) const
105{
106    double value = info->solution_[columnNumber_];
107    value = CoinMax(value, info->lower_[columnNumber_]);
108    value = CoinMin(value, info->upper_[columnNumber_]);
109    double nearest = floor(value + (1.0 - breakEven_));
110    assert (breakEven_ > 0.0 && breakEven_ < 1.0);
111    if (nearest > value)
112        preferredWay = 1;
113    else
114        preferredWay = -1;
115    if (preferredWay_)
116        preferredWay = preferredWay_;
117    double weight = fabs(value - nearest);
118    // normalize so weight is 0.5 at break even
119    if (nearest < value)
120        weight = (0.5 / breakEven_) * weight;
121    else
122        weight = (0.5 / (1.0 - breakEven_)) * weight;
123    if (fabs(value - nearest) <= info->integerTolerance_)
124        return 0.0;
125    else
126        return weight;
127}
128double
129CbcSimpleInteger::feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const
130{
131    double value = info->solution_[columnNumber_];
132#ifdef COIN_DEVELOP
133    if (fabs(value - floor(value + 0.5)) > 1.0e-5)
134        printf("value for %d away from integer %g\n", columnNumber_, value);
135#endif
136    double newValue = CoinMax(value, info->lower_[columnNumber_]);
137    newValue = CoinMin(newValue, info->upper_[columnNumber_]);
138    newValue = floor(newValue + 0.5);
139    solver->setColLower(columnNumber_, newValue);
140    solver->setColUpper(columnNumber_, newValue);
141    return fabs(value - newValue);
142}
143
144/* Create an OsiSolverBranch object
145
146This returns NULL if branch not represented by bound changes
147*/
148OsiSolverBranch *
149CbcSimpleInteger::solverBranch(OsiSolverInterface * /*solver*/,
150                               const OsiBranchingInformation * info) const
151{
152    double value = info->solution_[columnNumber_];
153    value = CoinMax(value, info->lower_[columnNumber_]);
154    value = CoinMin(value, info->upper_[columnNumber_]);
155    assert (info->upper_[columnNumber_] > info->lower_[columnNumber_]);
156#ifndef NDEBUG
157    double nearest = floor(value + 0.5);
158    assert (fabs(value - nearest) > info->integerTolerance_);
159#endif
160    OsiSolverBranch * branch = new OsiSolverBranch();
161    branch->addBranch(columnNumber_, value);
162    return branch;
163}
164// Creates a branching object
165CbcBranchingObject *
166CbcSimpleInteger::createCbcBranch(OsiSolverInterface * /*solver*/,
167                                  const OsiBranchingInformation * info, int way)
168{
169    CbcIntegerBranchingObject * branch = new CbcIntegerBranchingObject(model_, 0, -1, 0.5);
170    fillCreateBranch(branch, info, way);
171    return branch;
172}
173// Fills in a created branching object
174void
175CbcSimpleInteger::fillCreateBranch(CbcIntegerBranchingObject * branch, const OsiBranchingInformation * info, int way)
176{
177    branch->setOriginalObject(this);
178    double value = info->solution_[columnNumber_];
179    value = CoinMax(value, info->lower_[columnNumber_]);
180    value = CoinMin(value, info->upper_[columnNumber_]);
181    assert (info->upper_[columnNumber_] > info->lower_[columnNumber_]);
182    if (!info->hotstartSolution_ && priority_ != -999) {
183#ifndef NDEBUG
184        double nearest = floor(value + 0.5);
185        assert (fabs(value - nearest) > info->integerTolerance_);
186#endif
187    } else if (info->hotstartSolution_) {
188        double targetValue = info->hotstartSolution_[columnNumber_];
189        if (way > 0)
190            value = targetValue - 0.1;
191        else
192            value = targetValue + 0.1;
193    } else {
194        if (value <= info->lower_[columnNumber_])
195            value += 0.1;
196        else if (value >= info->upper_[columnNumber_])
197            value -= 0.1;
198    }
199    assert (value >= info->lower_[columnNumber_] &&
200            value <= info->upper_[columnNumber_]);
201    branch->fillPart(columnNumber_, way, value);
202}
203/* Column number if single column object -1 otherwise,
204   so returns >= 0
205   Used by heuristics
206*/
207int
208CbcSimpleInteger::columnNumber() const
209{
210    return columnNumber_;
211}
212/* Reset variable bounds to their original values.
213
214    Bounds may be tightened, so it may be good to be able to set this info in object.
215*/
216void
217CbcSimpleInteger::resetBounds(const OsiSolverInterface * solver)
218{
219    originalLower_ = solver->getColLower()[columnNumber_] ;
220    originalUpper_ = solver->getColUpper()[columnNumber_] ;
221}
222
223/*  Change column numbers after preprocessing
224 */
225void
226CbcSimpleInteger::resetSequenceEtc(int /*numberColumns*/,
227                                   const int * originalColumns)
228{
229    //assert (numberColumns>0);
230    int iColumn;
231#ifdef JJF_ZERO
232    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
233        if (columnNumber_ == originalColumns[iColumn])
234            break;
235    }
236    assert (iColumn < numberColumns);
237#else
238    iColumn = originalColumns[columnNumber_];
239    assert (iColumn >= 0);
240#endif
241    columnNumber_ = iColumn;
242}
243// This looks at solution and sets bounds to contain solution
244/** More precisely: it first forces the variable within the existing
245    bounds, and then tightens the bounds to fix the variable at the
246    nearest integer value.
247*/
248void
249CbcSimpleInteger::feasibleRegion()
250{
251    abort();
252}
253
254//##############################################################################
255
256// Default Constructor
257CbcIntegerBranchingObject::CbcIntegerBranchingObject()
258        : CbcBranchingObject()
259{
260    down_[0] = 0.0;
261    down_[1] = 0.0;
262    up_[0] = 0.0;
263    up_[1] = 0.0;
264#ifdef FUNNY_BRANCHING
265    variables_ = NULL;
266    newBounds_ = NULL;
267    numberExtraChangedBounds_ = 0;
268#endif
269}
270// Useful constructor
271CbcIntegerBranchingObject::CbcIntegerBranchingObject (CbcModel * model,
272        int variable, int way , double value)
273        : CbcBranchingObject(model, variable, way, value)
274{
275    int iColumn = variable;
276    assert (model_->solver()->getNumCols() > 0);
277    down_[0] = model_->solver()->getColLower()[iColumn];
278    down_[1] = floor(value_);
279    up_[0] = ceil(value_);
280    up_[1] = model->getColUpper()[iColumn];
281#ifdef FUNNY_BRANCHING
282    variables_ = NULL;
283    newBounds_ = NULL;
284    numberExtraChangedBounds_ = 0;
285#endif
286}
287// Does part of constructor
288void
289CbcIntegerBranchingObject::fillPart (int variable,
290                                     int way , double value)
291{
292    //originalObject_=NULL;
293    branchIndex_ = 0;
294    value_ = value;
295    numberBranches_ = 2;
296    //model_= model;
297    //originalCbcObject_=NULL;
298    variable_ = variable;
299    way_ = way;
300    int iColumn = variable;
301    down_[0] = model_->solver()->getColLower()[iColumn];
302    down_[1] = floor(value_);
303    up_[0] = ceil(value_);
304    up_[1] = model_->getColUpper()[iColumn];
305}
306// Useful constructor for fixing
307CbcIntegerBranchingObject::CbcIntegerBranchingObject (CbcModel * model,
308        int variable, int way,
309        double lowerValue,
310        double upperValue)
311        : CbcBranchingObject(model, variable, way, lowerValue)
312{
313    setNumberBranchesLeft(1);
314    down_[0] = lowerValue;
315    down_[1] = upperValue;
316    up_[0] = lowerValue;
317    up_[1] = upperValue;
318#ifdef FUNNY_BRANCHING
319    variables_ = NULL;
320    newBounds_ = NULL;
321    numberExtraChangedBounds_ = 0;
322#endif
323}
324
325
326// Copy constructor
327CbcIntegerBranchingObject::CbcIntegerBranchingObject ( const CbcIntegerBranchingObject & rhs) : CbcBranchingObject(rhs)
328{
329    down_[0] = rhs.down_[0];
330    down_[1] = rhs.down_[1];
331    up_[0] = rhs.up_[0];
332    up_[1] = rhs.up_[1];
333#ifdef FUNNY_BRANCHING
334    numberExtraChangedBounds_ = rhs.numberExtraChangedBounds_;
335    int size = numberExtraChangedBounds_ * (sizeof(double) + sizeof(int));
336    char * temp = new char [size];
337    newBounds_ = (double *) temp;
338    variables_ = (int *) (newBounds_ + numberExtraChangedBounds_);
339
340    int i ;
341    for (i = 0; i < numberExtraChangedBounds_; i++) {
342        variables_[i] = rhs.variables_[i];
343        newBounds_[i] = rhs.newBounds_[i];
344    }
345#endif
346}
347
348// Assignment operator
349CbcIntegerBranchingObject &
350CbcIntegerBranchingObject::operator=( const CbcIntegerBranchingObject & rhs)
351{
352    if (this != &rhs) {
353        CbcBranchingObject::operator=(rhs);
354        down_[0] = rhs.down_[0];
355        down_[1] = rhs.down_[1];
356        up_[0] = rhs.up_[0];
357        up_[1] = rhs.up_[1];
358#ifdef FUNNY_BRANCHING
359        delete [] newBounds_;
360        numberExtraChangedBounds_ = rhs.numberExtraChangedBounds_;
361        int size = numberExtraChangedBounds_ * (sizeof(double) + sizeof(int));
362        char * temp = new char [size];
363        newBounds_ = (double *) temp;
364        variables_ = (int *) (newBounds_ + numberExtraChangedBounds_);
365
366        int i ;
367        for (i = 0; i < numberExtraChangedBounds_; i++) {
368            variables_[i] = rhs.variables_[i];
369            newBounds_[i] = rhs.newBounds_[i];
370        }
371#endif
372    }
373    return *this;
374}
375CbcBranchingObject *
376CbcIntegerBranchingObject::clone() const
377{
378    return (new CbcIntegerBranchingObject(*this));
379}
380
381
382// Destructor
383CbcIntegerBranchingObject::~CbcIntegerBranchingObject ()
384{
385    // for debugging threads
386    way_ = -23456789;
387#ifdef FUNNY_BRANCHING
388    delete [] newBounds_;
389#endif
390}
391
392/*
393  Perform a branch by adjusting the bounds of the specified variable. Note
394  that each arm of the branch advances the object to the next arm by
395  advancing the value of way_.
396
397  Providing new values for the variable's lower and upper bounds for each
398  branching direction gives a little bit of additional flexibility and will
399  be easily extensible to multi-way branching.
400  Returns change in guessed objective on next branch
401*/
402double
403CbcIntegerBranchingObject::branch()
404{
405    // for debugging threads
406    if (way_ < -1 || way_ > 100000) {
407        printf("way %d, left %d, iCol %d, variable %d\n",
408               way_, numberBranchesLeft(),
409               originalCbcObject_->columnNumber(), variable_);
410        assert (way_ != -23456789);
411    }
412    decrementNumberBranchesLeft();
413    if (down_[1] == -COIN_DBL_MAX)
414        return 0.0;
415    int iColumn = originalCbcObject_->columnNumber();
416    assert (variable_ == iColumn);
417    double olb, oub ;
418    olb = model_->solver()->getColLower()[iColumn] ;
419    oub = model_->solver()->getColUpper()[iColumn] ;
420    //#define TIGHTEN_BOUNDS
421#ifndef TIGHTEN_BOUNDS
422#ifdef COIN_DEVELOP
423    if (olb != down_[0] || oub != up_[1]) {
424        if (way_ > 0)
425            printf("branching up on var %d: [%g,%g] => [%g,%g] - other [%g,%g]\n",
426                   iColumn, olb, oub, up_[0], up_[1], down_[0], down_[1]) ;
427        else
428            printf("branching down on var %d: [%g,%g] => [%g,%g] - other [%g,%g]\n",
429                   iColumn, olb, oub, down_[0], down_[1], up_[0], up_[1]) ;
430    }
431#endif
432#endif
433    if (way_ < 0) {
434#ifdef CBC_DEBUG
435        { double olb, oub ;
436            olb = model_->solver()->getColLower()[iColumn] ;
437            oub = model_->solver()->getColUpper()[iColumn] ;
438            printf("branching down on var %d: [%g,%g] => [%g,%g]\n",
439                   iColumn, olb, oub, down_[0], down_[1]) ;
440        }
441#endif
442#ifndef TIGHTEN_BOUNDS
443        model_->solver()->setColLower(iColumn, down_[0]);
444#else
445        model_->solver()->setColLower(iColumn, CoinMax(down_[0], olb));
446#endif
447        model_->solver()->setColUpper(iColumn, down_[1]);
448        //#define CBC_PRINT2
449#ifdef CBC_PRINT2
450        printf("%d branching down has bounds %g %g", iColumn, down_[0], down_[1]);
451#endif
452#ifdef FUNNY_BRANCHING
453        // branch - do extra bounds
454        for (int i = 0; i < numberExtraChangedBounds_; i++) {
455            int variable = variables_[i];
456            if ((variable&0x40000000) != 0) {
457                // for going down
458                int k = variable & 0x3fffffff;
459                assert (k != iColumn);
460                if ((variable&0x80000000) == 0) {
461                    // lower bound changing
462#ifdef CBC_PRINT2
463                    printf(" extra for %d changes lower from %g to %g",
464                           k, model_->solver()->getColLower()[k], newBounds_[i]);
465#endif
466                    model_->solver()->setColLower(k, newBounds_[i]);
467                } else {
468                    // upper bound changing
469#ifdef CBC_PRINT2
470                    printf(" extra for %d changes upper from %g to %g",
471                           k, model_->solver()->getColUpper()[k], newBounds_[i]);
472#endif
473                    model_->solver()->setColUpper(k, newBounds_[i]);
474                }
475            }
476        }
477#endif
478#ifdef CBC_PRINT2
479        printf("\n");
480#endif
481        way_ = 1;
482    } else {
483#ifdef CBC_DEBUG
484        { double olb, oub ;
485            olb = model_->solver()->getColLower()[iColumn] ;
486            oub = model_->solver()->getColUpper()[iColumn] ;
487            printf("branching up on var %d: [%g,%g] => [%g,%g]\n",
488                   iColumn, olb, oub, up_[0], up_[1]) ;
489        }
490#endif
491        model_->solver()->setColLower(iColumn, up_[0]);
492#ifndef TIGHTEN_BOUNDS
493        model_->solver()->setColUpper(iColumn, up_[1]);
494#else
495        model_->solver()->setColUpper(iColumn, CoinMin(up_[1], oub));
496#endif
497#ifdef CBC_PRINT2
498        printf("%d branching up has bounds %g %g", iColumn, up_[0], up_[1]);
499#endif
500#ifdef FUNNY_BRANCHING
501        // branch - do extra bounds
502        for (int i = 0; i < numberExtraChangedBounds_; i++) {
503            int variable = variables_[i];
504            if ((variable&0x40000000) == 0) {
505                // for going up
506                int k = variable & 0x3fffffff;
507                assert (k != iColumn);
508                if ((variable&0x80000000) == 0) {
509                    // lower bound changing
510#ifdef CBC_PRINT2
511                    printf(" extra for %d changes lower from %g to %g",
512                           k, model_->solver()->getColLower()[k], newBounds_[i]);
513#endif
514                    model_->solver()->setColLower(k, newBounds_[i]);
515                } else {
516                    // upper bound changing
517#ifdef CBC_PRINT2
518                    printf(" extra for %d changes upper from %g to %g",
519                           k, model_->solver()->getColUpper()[k], newBounds_[i]);
520#endif
521                    model_->solver()->setColUpper(k, newBounds_[i]);
522                }
523            }
524        }
525#endif
526#ifdef CBC_PRINT2
527        printf("\n");
528#endif
529        way_ = -1;        // Swap direction
530    }
531    double nlb = model_->solver()->getColLower()[iColumn];
532    double nub = model_->solver()->getColUpper()[iColumn];
533    if (nlb < olb) {
534#ifndef NDEBUG
535        printf("bad lb change for column %d from %g to %g\n", iColumn, olb, nlb);
536#endif
537        model_->solver()->setColLower(iColumn, CoinMin(olb, nub));
538        nlb = olb;
539    }
540    if (nub > oub) {
541#ifndef NDEBUG
542        printf("bad ub change for column %d from %g to %g\n", iColumn, oub, nub);
543#endif
544        model_->solver()->setColUpper(iColumn, CoinMax(oub, nlb));
545    }
546#ifndef NDEBUG
547    if (nlb < olb + 1.0e-8 && nub > oub - 1.0e-8 && false)
548        printf("bad null change for column %d - bounds %g,%g\n", iColumn, olb, oub);
549#endif
550    return 0.0;
551}
552/* Update bounds in solver as in 'branch' and update given bounds.
553   branchState is -1 for 'down' +1 for 'up' */
554void
555CbcIntegerBranchingObject::fix(OsiSolverInterface * /*solver*/,
556                               double * lower, double * upper,
557                               int branchState) const
558{
559    int iColumn = originalCbcObject_->columnNumber();
560    assert (variable_ == iColumn);
561    if (branchState < 0) {
562        model_->solver()->setColLower(iColumn, down_[0]);
563        lower[iColumn] = down_[0];
564        model_->solver()->setColUpper(iColumn, down_[1]);
565        upper[iColumn] = down_[1];
566    } else {
567        model_->solver()->setColLower(iColumn, up_[0]);
568        lower[iColumn] = up_[0];
569        model_->solver()->setColUpper(iColumn, up_[1]);
570        upper[iColumn] = up_[1];
571    }
572}
573#ifdef FUNNY_BRANCHING
574// Deactivate bounds for branching
575void
576CbcIntegerBranchingObject::deactivate()
577{
578    down_[1] = -COIN_DBL_MAX;
579}
580int
581CbcIntegerBranchingObject::applyExtraBounds(int iColumn, double lower, double upper, int way)
582{
583    // branch - do bounds
584
585    int i;
586    int found = 0;
587    if (variable_ == iColumn) {
588        printf("odd applyExtra %d\n", iColumn);
589        if (way < 0) {
590            down_[0] = CoinMax(lower, down_[0]);
591            down_[1] = CoinMin(upper, down_[1]);
592            assert (down_[0] <= down_[1]);
593        } else {
594            up_[0] = CoinMax(lower, up_[0]);
595            up_[1] = CoinMin(upper, up_[1]);
596            assert (up_[0] <= up_[1]);
597        }
598        return 0;
599    }
600    int check = (way < 0) ? 0x40000000 : 0;
601    double newLower = lower;
602    double newUpper = upper;
603    for (i = 0; i < numberExtraChangedBounds_; i++) {
604        int variable = variables_[i];
605        if ((variable&0x40000000) == check) {
606            int k = variable & 0x3fffffff;
607            if (k == iColumn) {
608                if ((variable&0x80000000) == 0) {
609                    // lower bound changing
610                    found |= 1;
611                    newBounds_[i] = CoinMax(lower, newBounds_[i]);
612                    newLower = newBounds_[i];
613                } else {
614                    // upper bound changing
615                    found |= 2;
616                    newBounds_[i] = CoinMin(upper, newBounds_[i]);
617                    newUpper = newBounds_[i];
618                }
619            }
620        }
621    }
622    int nAdd = 0;
623    if ((found&2) == 0) {
624        // need to add new upper
625        nAdd++;
626    }
627    if ((found&1) == 0) {
628        // need to add new lower
629        nAdd++;
630    }
631    if (nAdd) {
632        int size = (numberExtraChangedBounds_ + nAdd) * (sizeof(double) + sizeof(int));
633        char * temp = new char [size];
634        double * newBounds = (double *) temp;
635        int * variables = (int *) (newBounds + numberExtraChangedBounds_ + nAdd);
636
637        int i ;
638        for (i = 0; i < numberExtraChangedBounds_; i++) {
639            variables[i] = variables_[i];
640            newBounds[i] = newBounds_[i];
641        }
642        delete [] newBounds_;
643        newBounds_ = newBounds;
644        variables_ = variables;
645        if ((found&2) == 0) {
646            // need to add new upper
647            int variable = iColumn | 0x80000000;
648            variables_[numberExtraChangedBounds_] = variable;
649            newBounds_[numberExtraChangedBounds_++] = newUpper;
650        }
651        if ((found&1) == 0) {
652            // need to add new lower
653            int variable = iColumn;
654            variables_[numberExtraChangedBounds_] = variable;
655            newBounds_[numberExtraChangedBounds_++] = newLower;
656        }
657    }
658
659    return (newUpper >= newLower) ? 0 : 1;
660}
661#endif
662// Print what would happen
663void
664CbcIntegerBranchingObject::print()
665{
666    int iColumn = originalCbcObject_->columnNumber();
667    assert (variable_ == iColumn);
668    if (way_ < 0) {
669        {
670            double olb, oub ;
671            olb = model_->solver()->getColLower()[iColumn] ;
672            oub = model_->solver()->getColUpper()[iColumn] ;
673            printf("CbcInteger would branch down on var %d (int var %d): [%g,%g] => [%g,%g]\n",
674                   iColumn, variable_, olb, oub, down_[0], down_[1]) ;
675        }
676    } else {
677        {
678            double olb, oub ;
679            olb = model_->solver()->getColLower()[iColumn] ;
680            oub = model_->solver()->getColUpper()[iColumn] ;
681            printf("CbcInteger would branch up on var %d (int var %d): [%g,%g] => [%g,%g]\n",
682                   iColumn, variable_, olb, oub, up_[0], up_[1]) ;
683        }
684    }
685}
686
687/** Compare the \c this with \c brObj. \c this and \c brObj must be os the
688    same type and must have the same original object, but they may have
689    different feasible regions.
690    Return the appropriate CbcRangeCompare value (first argument being the
691    sub/superset if that's the case). In case of overlap (and if \c
692    replaceIfOverlap is true) replace the current branching object with one
693    whose feasible region is the overlap.
694   */
695CbcRangeCompare
696CbcIntegerBranchingObject::compareBranchingObject
697(const CbcBranchingObject* brObj, const bool replaceIfOverlap)
698{
699    const CbcIntegerBranchingObject* br =
700        dynamic_cast<const CbcIntegerBranchingObject*>(brObj);
701    assert(br);
702    double* thisBd = way_ < 0 ? down_ : up_;
703    const double* otherBd = br->way_ < 0 ? br->down_ : br->up_;
704    return CbcCompareRanges(thisBd, otherBd, replaceIfOverlap);
705}
Note: See TracBrowser for help on using the repository browser.