source: branches/sandbox/Cbc/src/CbcBranchDynamic.cpp @ 1351

Last change on this file since 1351 was 1351, checked in by EdwinStraver, 10 years ago

Combined CbcBranchDynamic?.cpp with CbcDynamicPseudoCostBranchingObject?
Combined CbcBranchCut? with CbcCutBranchingObject?
Combined CbcLotsize? with CbcBranchLotsize?.cpp

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.6 KB
Line 
1/* $Id: CbcBranchDynamic.cpp 1351 2009-12-04 16:26:41Z EdwinStraver $ */
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//#define CBC_DEBUG
13//#define TRACE_ONE 19
14#include "OsiSolverInterface.hpp"
15#include "OsiSolverBranch.hpp"
16#include "CbcModel.hpp"
17#include "CbcMessage.hpp"
18#include "CbcBranchDynamic.hpp"
19#include "CoinSort.hpp"
20#include "CoinError.hpp"
21#ifdef COIN_DEVELOP
22typedef struct {
23    double sumUp_;
24    double upEst_; // or change in obj in update
25    double sumDown_;
26    double downEst_; // or movement in value in update
27    int sequence_;
28    int numberUp_;
29    int numberUpInf_;
30    int numberDown_;
31    int numberDownInf_;
32    char where_;
33    char status_;
34} History;
35History * history = NULL;
36int numberHistory = 0;
37int maxHistory = 0;
38bool getHistoryStatistics_ = true;
39static void increaseHistory()
40{
41    if (numberHistory == maxHistory) {
42        maxHistory = 100 + (3 * maxHistory) / 2;
43        History * temp = new History [maxHistory];
44        memcpy(temp, history, numberHistory*sizeof(History));
45        delete [] history;
46        history = temp;
47    }
48}
49static bool addRecord(History newOne)
50{
51    //if (!getHistoryStatistics_)
52    return false;
53    bool fromCompare = false;
54    int i;
55    for ( i = numberHistory - 1; i >= 0; i--) {
56        if (newOne.sequence_ != history[i].sequence_)
57            continue;
58        if (newOne.where_ != history[i].where_)
59            continue;
60        if (newOne.numberUp_ != history[i].numberUp_)
61            continue;
62        if (newOne.sumUp_ != history[i].sumUp_)
63            continue;
64        if (newOne.numberUpInf_ != history[i].numberUpInf_)
65            continue;
66        if (newOne.upEst_ != history[i].upEst_)
67            continue;
68        if (newOne.numberDown_ != history[i].numberDown_)
69            continue;
70        if (newOne.sumDown_ != history[i].sumDown_)
71            continue;
72        if (newOne.numberDownInf_ != history[i].numberDownInf_)
73            continue;
74        if (newOne.downEst_ != history[i].downEst_)
75            continue;
76        // If B knock out previous B
77        if (newOne.where_ == 'C') {
78            fromCompare = true;
79            if (newOne.status_ == 'B') {
80                int j;
81                for (j = i - 1; j >= 0; j--) {
82                    if (history[j].where_ == 'C') {
83                        if (history[j].status_ == 'I') {
84                            break;
85                        } else if (history[j].status_ == 'B') {
86                            history[j].status_ = ' ';
87                            break;
88                        }
89                    }
90                }
91            }
92            break;
93        }
94    }
95    if (i == -1 || fromCompare) {
96        //add
97        increaseHistory();
98        history[numberHistory++] = newOne;
99        return true;
100    } else {
101        return false;
102    }
103}
104#endif
105
106
107// Default Constructor
108CbcBranchDynamicDecision::CbcBranchDynamicDecision()
109        : CbcBranchDecision()
110{
111    bestCriterion_ = 0.0;
112    bestChangeUp_ = 0.0;
113    bestNumberUp_ = 0;
114    bestChangeDown_ = 0.0;
115    bestNumberDown_ = 0;
116    bestObject_ = NULL;
117}
118
119// Copy constructor
120CbcBranchDynamicDecision::CbcBranchDynamicDecision (
121    const CbcBranchDynamicDecision & rhs)
122        : CbcBranchDecision()
123{
124    bestCriterion_ = rhs.bestCriterion_;
125    bestChangeUp_ = rhs.bestChangeUp_;
126    bestNumberUp_ = rhs.bestNumberUp_;
127    bestChangeDown_ = rhs.bestChangeDown_;
128    bestNumberDown_ = rhs.bestNumberDown_;
129    bestObject_ = rhs.bestObject_;
130}
131
132CbcBranchDynamicDecision::~CbcBranchDynamicDecision()
133{
134}
135
136// Clone
137CbcBranchDecision *
138CbcBranchDynamicDecision::clone() const
139{
140    return new CbcBranchDynamicDecision(*this);
141}
142
143// Initialize i.e. before start of choosing at a node
144void
145CbcBranchDynamicDecision::initialize(CbcModel * /*model*/)
146{
147    bestCriterion_ = 0.0;
148    bestChangeUp_ = 0.0;
149    bestNumberUp_ = 0;
150    bestChangeDown_ = 0.0;
151    bestNumberDown_ = 0;
152    bestObject_ = NULL;
153#ifdef COIN_DEVELOP
154    History hist;
155    hist.where_ = 'C';
156    hist.status_ = 'I';
157    hist.sequence_ = 55555;
158    hist.numberUp_ = 0;
159    hist.numberUpInf_ = 0;
160    hist.sumUp_ = 0.0;
161    hist.upEst_ = 0.0;
162    hist.numberDown_ = 0;
163    hist.numberDownInf_ = 0;
164    hist.sumDown_ = 0.0;
165    hist.downEst_ = 0.0;
166    addRecord(hist);
167#endif
168}
169
170/* Saves a clone of current branching object.  Can be used to update
171      information on object causing branch - after branch */
172void
173CbcBranchDynamicDecision::saveBranchingObject(OsiBranchingObject * object)
174{
175    OsiBranchingObject * obj = object->clone();
176#ifndef NDEBUG
177    CbcBranchingObject * obj2 =
178        dynamic_cast<CbcBranchingObject *>(obj);
179    assert (obj2);
180#if COIN_DEVELOP>1
181    CbcDynamicPseudoCostBranchingObject * branchingObject =
182        dynamic_cast<CbcDynamicPseudoCostBranchingObject *>(obj);
183    if (!branchingObject)
184        printf("no dynamic branching object Dynamic Decision\n");
185#endif
186#else
187    CbcBranchingObject * obj2 =
188        static_cast<CbcBranchingObject *>(obj);
189#endif
190    //object_=branchingObject;
191    object_ = obj2;
192}
193/* Pass in information on branch just done.
194   assumes object can get information from solver */
195void
196CbcBranchDynamicDecision::updateInformation(OsiSolverInterface * solver,
197        const CbcNode * node)
198{
199    assert (object_);
200    const CbcModel * model = object_->model();
201    double originalValue = node->objectiveValue();
202    int originalUnsatisfied = node->numberUnsatisfied();
203    double objectiveValue = solver->getObjValue() * model->getObjSense();
204    int unsatisfied = 0;
205    int i;
206    int numberIntegers = model->numberIntegers();;
207    const double * solution = solver->getColSolution();
208    //const double * lower = solver->getColLower();
209    //const double * upper = solver->getColUpper();
210    CbcDynamicPseudoCostBranchingObject * branchingObject =
211        dynamic_cast<CbcDynamicPseudoCostBranchingObject *>(object_);
212    if (!branchingObject) {
213        delete object_;
214        object_ = NULL;
215        return;
216    }
217    CbcSimpleIntegerDynamicPseudoCost *  object = branchingObject->object();
218    double change = CoinMax(0.0, objectiveValue - originalValue);
219    // probably should also ignore if stopped
220    int iStatus;
221    if (solver->isProvenOptimal())
222        iStatus = 0; // optimal
223    else if (solver->isIterationLimitReached()
224             && !solver->isDualObjectiveLimitReached())
225        iStatus = 2; // unknown
226    else
227        iStatus = 1; // infeasible
228
229    bool feasible = iStatus != 1;
230    if (feasible) {
231        double integerTolerance =
232            model->getDblParam(CbcModel::CbcIntegerTolerance);
233        const int * integerVariable = model->integerVariable();
234        for (i = 0; i < numberIntegers; i++) {
235            int j = integerVariable[i];
236            double value = solution[j];
237            double nearest = floor(value + 0.5);
238            if (fabs(value - nearest) > integerTolerance)
239                unsatisfied++;
240        }
241    }
242    int way = object_->way();
243    double value = object_->value();
244    //#define TYPE2 1
245    //#define TYPERATIO 0.9
246    if (way < 0) {
247        // down
248        if (feasible) {
249            double movement = value - floor(value);
250            movement = CoinMax(movement, MINIMUM_MOVEMENT);
251            //printf("(down change %g value down %g ",change,movement);
252            object->incrementNumberTimesDown();
253            object->addToSumDownChange(1.0e-30 + movement);
254            object->addToSumDownDecrease(originalUnsatisfied - unsatisfied);
255#if TYPE2==0
256            object->addToSumDownCost(change / (1.0e-30 + movement));
257            object->setDownDynamicPseudoCost(object->sumDownCost() /
258                                             static_cast<double> (object->numberTimesDown()));
259#elif TYPE2==1
260            object->addToSumDownCost(change);
261            object->setDownDynamicPseudoCost(object->sumDownCost() / object->sumDownChange());
262#elif TYPE2==2
263            object->addToSumDownCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement));
264            object->setDownDynamicPseudoCost(object->sumDownCost()*(TYPERATIO / object->sumDownChange() + (1.0 - TYPERATIO) / (double) object->numberTimesDown()));
265#endif
266        } else {
267            //printf("(down infeasible value down %g ",change,movement);
268            object->incrementNumberTimesDown();
269            object->incrementNumberTimesDownInfeasible();
270#if INFEAS==2
271            double distanceToCutoff = 0.0;
272            double objectiveValue = model->getCurrentMinimizationObjValue();
273            distanceToCutoff =  model->getCutoff()  - originalValue;
274            if (distanceToCutoff < 1.0e20)
275                change = distanceToCutoff * 2.0;
276            else
277                change = object->downDynamicPseudoCost() * movement * 10.0;
278            change = CoinMax(1.0e-12 * (1.0 + fabs(originalValue)), change);
279            object->addToSumDownChange(1.0e-30 + movement);
280            object->addToSumDownDecrease(originalUnsatisfied - unsatisfied);
281#if TYPE2==0
282            object->addToSumDownCost(change / (1.0e-30 + movement));
283            object->setDownDynamicPseudoCost(object->sumDownCost() / (double) object->numberTimesDown());
284#elif TYPE2==1
285            object->addToSumDownCost(change);
286            object->setDownDynamicPseudoCost(object->sumDownCost() / object->sumDownChange());
287#elif TYPE2==2
288            object->addToSumDownCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement));
289            object->setDownDynamicPseudoCost(object->sumDownCost()*(TYPERATIO / object->sumDownChange() + (1.0 - TYPERATIO) / (double) object->numberTimesDown()));
290#endif
291#endif
292        }
293    } else {
294        // up
295        if (feasible) {
296            double movement = ceil(value) - value;
297            movement = CoinMax(movement, MINIMUM_MOVEMENT);
298            //printf("(up change %g value down %g ",change,movement);
299            object->incrementNumberTimesUp();
300            object->addToSumUpChange(1.0e-30 + movement);
301            object->addToSumUpDecrease(unsatisfied - originalUnsatisfied);
302#if TYPE2==0
303            object->addToSumUpCost(change / (1.0e-30 + movement));
304            object->setUpDynamicPseudoCost(object->sumUpCost() /
305                                           static_cast<double> (object->numberTimesUp()));
306#elif TYPE2==1
307            object->addToSumUpCost(change);
308            object->setUpDynamicPseudoCost(object->sumUpCost() / object->sumUpChange());
309#elif TYPE2==2
310            object->addToSumUpCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement));
311            object->setUpDynamicPseudoCost(object->sumUpCost()*(TYPERATIO / object->sumUpChange() + (1.0 - TYPERATIO) / (double) object->numberTimesUp()));
312#endif
313        } else {
314            //printf("(up infeasible value down %g ",change,movement);
315            object->incrementNumberTimesUp();
316            object->incrementNumberTimesUpInfeasible();
317#if INFEAS==2
318            double distanceToCutoff = 0.0;
319            double objectiveValue = model->getCurrentMinimizationObjValue();
320            distanceToCutoff =  model->getCutoff()  - originalValue;
321            if (distanceToCutoff < 1.0e20)
322                change = distanceToCutoff * 2.0;
323            else
324                change = object->upDynamicPseudoCost() * movement * 10.0;
325            change = CoinMax(1.0e-12 * (1.0 + fabs(originalValue)), change);
326            object->addToSumUpChange(1.0e-30 + movement);
327            object->addToSumUpDecrease(unsatisfied - originalUnsatisfied);
328#if TYPE2==0
329            object->addToSumUpCost(change / (1.0e-30 + movement));
330            object->setUpDynamicPseudoCost(object->sumUpCost() / (double) object->numberTimesUp());
331#elif TYPE2==1
332            object->addToSumUpCost(change);
333            object->setUpDynamicPseudoCost(object->sumUpCost() / object->sumUpChange());
334#elif TYPE2==2
335            object->addToSumUpCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement));
336            object->setUpDynamicPseudoCost(object->sumUpCost()*(TYPERATIO / object->sumUpChange() + (1.0 - TYPERATIO) / (double) object->numberTimesUp()));
337#endif
338#endif
339        }
340    }
341    //object->print(1,0.5);
342    delete object_;
343    object_ = NULL;
344}
345
346/*
347  Simple dynamic decision algorithm. Compare based on infeasibility (numInfUp,
348  numInfDown) until a solution is found by search, then switch to change in
349  objective (changeUp, changeDown). Note that bestSoFar is remembered in
350  bestObject_, so the parameter bestSoFar is unused.
351*/
352
353int
354CbcBranchDynamicDecision::betterBranch(CbcBranchingObject * thisOne,
355                                       CbcBranchingObject * /*bestSoFar*/,
356                                       double changeUp, int numInfUp,
357                                       double changeDown, int numInfDown)
358{
359    CbcModel * model = thisOne->model();
360    int stateOfSearch = model->stateOfSearch() % 10;
361    int betterWay = 0;
362    double value = 0.0;
363    if (!bestObject_) {
364        bestCriterion_ = -1.0e30;
365        bestNumberUp_ = COIN_INT_MAX;
366        bestNumberDown_ = COIN_INT_MAX;
367    }
368    // maybe branch up more if no solution or not many nodes done?
369    if (stateOfSearch <= 2) {
370        //#define TRY_STUFF 1
371#ifdef TRY_STUFF
372        // before solution - choose smallest number
373        // could add in depth as well
374        int bestNumber = CoinMin(bestNumberUp_, bestNumberDown_);
375        if (numInfUp < numInfDown) {
376            if (numInfUp < bestNumber) {
377                betterWay = 1;
378            } else if (numInfUp == bestNumber) {
379                if (changeUp < bestChangeUp_)
380                    betterWay = 1;
381            }
382        } else if (numInfUp > numInfDown) {
383            if (numInfDown < bestNumber) {
384                betterWay = -1;
385            } else if (numInfDown == bestNumber) {
386                if (changeDown < bestChangeDown_)
387                    betterWay = -1;
388            }
389        } else {
390            // up and down have same number
391            bool better = false;
392            if (numInfUp < bestNumber) {
393                better = true;
394            } else if (numInfUp == bestNumber) {
395                if (CoinMin(changeUp, changeDown) < CoinMin(bestChangeUp_, bestChangeDown_) - 1.0e-5)
396                    better = true;;
397            }
398            if (better) {
399                // see which way
400                if (changeUp <= changeDown)
401                    betterWay = 1;
402                else
403                    betterWay = -1;
404            }
405        }
406        if (betterWay) {
407            value = CoinMin(numInfUp, numInfDown);
408        }
409#else
410        // use pseudo shadow prices modified by locks
411        // test testosi
412#if 1
413        double objectiveValue = model->getCurrentMinimizationObjValue();
414        double distanceToCutoff =  model->getCutoff()  - objectiveValue;
415        if (distanceToCutoff < 1.0e20)
416            distanceToCutoff *= 10.0;
417        else
418            distanceToCutoff = 1.0e2 + fabs(objectiveValue);
419        distanceToCutoff = CoinMax(distanceToCutoff, 1.0e-12 * (1.0 + fabs(objectiveValue)));
420        double continuousObjective = model->getContinuousObjective();
421        double distanceToCutoffC =  model->getCutoff()  - continuousObjective;
422        if (distanceToCutoffC > 1.0e20)
423            distanceToCutoffC = 1.0e2 + fabs(objectiveValue);
424        distanceToCutoffC = CoinMax(distanceToCutoffC, 1.0e-12 * (1.0 + fabs(objectiveValue)));
425        int numberInfC = model->getContinuousInfeasibilities();
426        double perInf = distanceToCutoffC / static_cast<double> (numberInfC);
427        assert (perInf > 0.0);
428        //int numberIntegers = model->numberIntegers();
429        changeDown += perInf * numInfDown;
430        changeUp += perInf * numInfUp;
431#if 0
432        if (numInfDown == 1) {
433            if (numInfUp == 1) {
434                changeUp += 1.0e6;
435                changeDown += 1.0e6;
436            } else if (changeDown <= 1.5*changeUp) {
437                changeUp += 1.0e6;
438            }
439        } else if (numInfUp == 1 && changeUp <= 1.5*changeDown) {
440            changeDown += 1.0e6;
441        }
442#endif
443#endif
444        double minValue = CoinMin(changeDown, changeUp);
445        double maxValue = CoinMax(changeDown, changeUp);
446        value = WEIGHT_BEFORE * minValue + (1.0 - WEIGHT_BEFORE) * maxValue;
447        if (value > bestCriterion_ + 1.0e-8) {
448            if (changeUp <= 1.5*changeDown) {
449                betterWay = 1;
450            } else {
451                betterWay = -1;
452            }
453        }
454#endif
455    } else {
456#define TRY_STUFF 2
457#if TRY_STUFF > 1
458        // Get current number of infeasibilities, cutoff and current objective
459        CbcNode * node = model->currentNode();
460        int numberUnsatisfied = node->numberUnsatisfied();
461        double cutoff = model->getCutoff();
462        double objectiveValue = node->objectiveValue();
463#endif
464        // got a solution
465        double minValue = CoinMin(changeDown, changeUp);
466        double maxValue = CoinMax(changeDown, changeUp);
467        // Reduce
468#ifdef TRY_STUFF
469        //maxValue = CoinMin(maxValue,minValue*4.0);
470#else
471        //maxValue = CoinMin(maxValue,minValue*2.0);
472#endif
473#ifndef WEIGHT_PRODUCT
474        value = WEIGHT_AFTER * minValue + (1.0 - WEIGHT_AFTER) * maxValue;
475#else
476        double minProductWeight = model->getDblParam(CbcModel::CbcSmallChange);
477        value = CoinMax(minValue, minProductWeight) * CoinMax(maxValue, minProductWeight);
478        //value += minProductWeight*minValue;
479#endif
480        double useValue = value;
481        double useBest = bestCriterion_;
482#if TRY_STUFF>1
483        int thisNumber = CoinMin(numInfUp, numInfDown);
484        int bestNumber = CoinMin(bestNumberUp_, bestNumberDown_);
485        double distance = cutoff - objectiveValue;
486        assert (distance >= 0.0);
487        if (useValue + 0.1*distance > useBest && useValue*1.1 > useBest &&
488                useBest + 0.1*distance > useValue && useBest*1.1 > useValue) {
489            // not much in it - look at unsatisfied
490            if (thisNumber < numberUnsatisfied || bestNumber < numberUnsatisfied) {
491                double perInteger = distance / (static_cast<double> (numberUnsatisfied));
492                useValue += thisNumber * perInteger;
493                useBest += bestNumber * perInteger;
494            }
495        }
496#endif
497        if (useValue > useBest + 1.0e-8) {
498            if (changeUp <= 1.5*changeDown) {
499                betterWay = 1;
500            } else {
501                betterWay = -1;
502            }
503        }
504    }
505#ifdef COIN_DEVELOP
506    History hist;
507    {
508        CbcDynamicPseudoCostBranchingObject * branchingObject =
509            dynamic_cast<CbcDynamicPseudoCostBranchingObject *>(thisOne);
510        if (branchingObject) {
511            CbcSimpleIntegerDynamicPseudoCost *  object = branchingObject->object();
512            assert (object);
513            hist.where_ = 'C';
514            hist.status_ = ' ';
515            hist.sequence_ = object->columnNumber();
516            hist.numberUp_ = object->numberTimesUp();
517            hist.numberUpInf_ = numInfUp;
518            hist.sumUp_ = object->sumUpCost();
519            hist.upEst_ = changeUp;
520            hist.numberDown_ = object->numberTimesDown();
521            hist.numberDownInf_ = numInfDown;
522            hist.sumDown_ = object->sumDownCost();
523            hist.downEst_ = changeDown;
524        }
525    }
526#endif
527    if (betterWay) {
528#ifdef COIN_DEVELOP
529        hist.status_ = 'B';
530#endif
531        // maybe change better way
532        CbcDynamicPseudoCostBranchingObject * branchingObject =
533            dynamic_cast<CbcDynamicPseudoCostBranchingObject *>(thisOne);
534        if (branchingObject) {
535            CbcSimpleIntegerDynamicPseudoCost *  object = branchingObject->object();
536            double separator = object->upDownSeparator();
537            if (separator > 0.0) {
538                const double * solution = thisOne->model()->testSolution();
539                double valueVariable = solution[object->columnNumber()];
540                betterWay = (valueVariable - floor(valueVariable) >= separator) ? 1 : -1;
541            }
542        }
543        bestCriterion_ = value;
544        bestChangeUp_ = changeUp;
545        bestNumberUp_ = numInfUp;
546        bestChangeDown_ = changeDown;
547        bestNumberDown_ = numInfDown;
548        bestObject_ = thisOne;
549        // See if user is overriding way
550        if (thisOne->object() && thisOne->object()->preferredWay())
551            betterWay = thisOne->object()->preferredWay();
552    }
553#ifdef COIN_DEVELOP
554    addRecord(hist);
555#endif
556    return betterWay;
557}
558/* Sets or gets best criterion so far */
559void
560CbcBranchDynamicDecision::setBestCriterion(double value)
561{
562    bestCriterion_ = value;
563}
564double
565CbcBranchDynamicDecision::getBestCriterion() const
566{
567    return bestCriterion_;
568}
569#ifdef COIN_DEVELOP
570void printHistory(const char * file)
571{
572    if (!numberHistory)
573        return;
574    FILE * fp = fopen(file, "w");
575    assert(fp);
576    int numberIntegers = 0;
577    int i;
578    for (i = 0; i < numberHistory; i++) {
579        if (history[i].where_ != 'C' || history[i].status_ != 'I')
580            numberIntegers = CoinMax(numberIntegers, history[i].sequence_);
581    }
582    numberIntegers++;
583    for (int iC = 0; iC < numberIntegers; iC++) {
584        int n = 0;
585        for (i = 0; i < numberHistory; i++) {
586            if (history[i].sequence_ == iC) {
587                if (!n)
588                    fprintf(fp, "XXX %d\n", iC);
589                n++;
590                fprintf(fp, "%c%c up %8d %8d %12.5f %12.5f down  %8d %8d %12.5f %12.5f\n",
591                        history[i].where_,
592                        history[i].status_,
593                        history[i].numberUp_,
594                        history[i].numberUpInf_,
595                        history[i].sumUp_,
596                        history[i].upEst_,
597                        history[i].numberDown_,
598                        history[i].numberDownInf_,
599                        history[i].sumDown_,
600                        history[i].downEst_);
601            }
602        }
603    }
604    fclose(fp);
605}
606#endif
607
608// Default Constructor
609CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject()
610        : CbcIntegerBranchingObject()
611{
612    changeInGuessed_ = 1.0e-5;
613    object_ = NULL;
614}
615
616// Useful constructor
617CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject (CbcModel * model,
618        int variable,
619        int way , double value,
620        CbcSimpleIntegerDynamicPseudoCost * object)
621        : CbcIntegerBranchingObject(model, variable, way, value)
622{
623    changeInGuessed_ = 1.0e-5;
624    object_ = object;
625}
626// Does part of work for constructor
627void
628CbcDynamicPseudoCostBranchingObject::fillPart (int variable,
629        int way , double value,
630        CbcSimpleIntegerDynamicPseudoCost * object)
631{
632    CbcIntegerBranchingObject::fillPart(variable, way, value);
633    changeInGuessed_ = 1.0e-5;
634    object_ = object;
635}
636// Useful constructor for fixing
637CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject (CbcModel * model,
638        int variable, int way,
639        double lowerValue,
640        double /*upperValue*/)
641        : CbcIntegerBranchingObject(model, variable, way, lowerValue)
642{
643    changeInGuessed_ = 1.0e100;
644    object_ = NULL;
645}
646
647
648// Copy constructor
649CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject (
650    const CbcDynamicPseudoCostBranchingObject & rhs)
651        : CbcIntegerBranchingObject(rhs)
652{
653    changeInGuessed_ = rhs.changeInGuessed_;
654    object_ = rhs.object_;
655}
656
657// Assignment operator
658CbcDynamicPseudoCostBranchingObject &
659CbcDynamicPseudoCostBranchingObject::operator=( const CbcDynamicPseudoCostBranchingObject & rhs)
660{
661    if (this != &rhs) {
662        CbcIntegerBranchingObject::operator=(rhs);
663        changeInGuessed_ = rhs.changeInGuessed_;
664        object_ = rhs.object_;
665    }
666    return *this;
667}
668CbcBranchingObject *
669CbcDynamicPseudoCostBranchingObject::clone() const
670{
671    return (new CbcDynamicPseudoCostBranchingObject(*this));
672}
673
674// Destructor
675CbcDynamicPseudoCostBranchingObject::~CbcDynamicPseudoCostBranchingObject ()
676{
677}
678
679/*
680  Perform a branch by adjusting the bounds of the specified variable. Note
681  that each arm of the branch advances the object to the next arm by
682  advancing the value of way_.
683
684  Providing new values for the variable's lower and upper bounds for each
685  branching direction gives a little bit of additional flexibility and will
686  be easily extensible to multi-way branching.
687  Returns change in guessed objective on next branch
688*/
689double
690CbcDynamicPseudoCostBranchingObject::branch()
691{
692    CbcIntegerBranchingObject::branch();
693    return changeInGuessed_;
694}
695/* Some branchingObjects may claim to be able to skip
696   strong branching.  If so they have to fill in CbcStrongInfo.
697   The object mention in incoming CbcStrongInfo must match.
698   Returns nonzero if skip is wanted */
699int
700CbcDynamicPseudoCostBranchingObject::fillStrongInfo( CbcStrongInfo & info)
701{
702    assert (object_);
703    assert (info.possibleBranch == this);
704    info.upMovement = object_->upDynamicPseudoCost() * (ceil(value_) - value_);
705    info.downMovement = object_->downDynamicPseudoCost() * (value_ - floor(value_));
706    info.numIntInfeasUp  -= static_cast<int> (object_->sumUpDecrease() /
707                            (1.0e-12 + static_cast<double> (object_->numberTimesUp())));
708    info.numIntInfeasUp = CoinMax(info.numIntInfeasUp, 0);
709    info.numObjInfeasUp = 0;
710    info.finishedUp = false;
711    info.numItersUp = 0;
712    info.numIntInfeasDown  -= static_cast<int> (object_->sumDownDecrease() /
713                              (1.0e-12 + static_cast<double> (object_->numberTimesDown())));
714    info.numIntInfeasDown = CoinMax(info.numIntInfeasDown, 0);
715    info.numObjInfeasDown = 0;
716    info.finishedDown = false;
717    info.numItersDown = 0;
718    info.fix = 0;
719    if (object_->numberTimesUp() < object_->numberBeforeTrust() +
720            2*object_->numberTimesUpInfeasible() ||
721            object_->numberTimesDown() < object_->numberBeforeTrust() +
722            2*object_->numberTimesDownInfeasible()) {
723        return 0;
724    } else {
725        return 1;
726    }
727}
Note: See TracBrowser for help on using the repository browser.