source: trunk/Cbc/src/CbcBranchLotsize.cpp @ 1433

Last change on this file since 1433 was 1432, checked in by bjarni, 10 years ago

Added extra return at end of each source file where needed, to remove possible linefeed conflicts (NightlyBuild? errors)

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