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

Last change on this file since 1362 was 1362, checked in by EdwinStraver, 11 years ago

added Lou's comments

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.9 KB
Line 
1/* $Id: CbcBranchDynamic.cpp 1362 2009-12-04 22:15:52Z 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 */
195/*
196  The expectation is that this method will be called after the branch has been
197  imposed on the constraint system and resolve() has executed.
198
199  Note that the CbcBranchDecision is a property of the CbcModel. Note also that
200  this method is reaching right through the CbcBranchingObject to update
201  information in the underlying CbcObject. That's why we delete the
202  branchingObject at the end of the method --- the next time we're called,
203  the CbcObject will be different.
204*/
205void
206CbcBranchDynamicDecision::updateInformation(OsiSolverInterface * solver,
207        const CbcNode * node)
208{
209    assert (object_);
210    const CbcModel * model = object_->model();
211    double originalValue = node->objectiveValue();
212    int originalUnsatisfied = node->numberUnsatisfied();
213    double objectiveValue = solver->getObjValue() * model->getObjSense();
214    int unsatisfied = 0;
215    int i;
216    int numberIntegers = model->numberIntegers();;
217    const double * solution = solver->getColSolution();
218    //const double * lower = solver->getColLower();
219    //const double * upper = solver->getColUpper();
220        /*
221         Gain access to the associated CbcBranchingObject and its underlying
222         CbcObject.
223
224         Seems like we'd want to distinguish between no branching object and a
225         branching object of the wrong type. Just deleting an object of the wrong
226         type hides many sins.
227
228         Hmmm ... if we're using the OSI side of the hierarchy, is this indicated by a
229         null object_? Nah, then we have an assert failure off the top.
230        */
231
232    CbcDynamicPseudoCostBranchingObject * branchingObject =
233        dynamic_cast<CbcDynamicPseudoCostBranchingObject *>(object_);
234    if (!branchingObject) {
235        delete object_;
236        object_ = NULL;
237        return;
238    }
239    CbcSimpleIntegerDynamicPseudoCost *  object = branchingObject->object();
240    /*
241        change is the change in objective due to the branch we've just imposed. It's
242        possible we may have gone infeasible.
243        */
244        double change = CoinMax(0.0, objectiveValue - originalValue);
245    // probably should also ignore if stopped
246    int iStatus;
247    if (solver->isProvenOptimal())
248        iStatus = 0; // optimal
249    else if (solver->isIterationLimitReached()
250             && !solver->isDualObjectiveLimitReached())
251        iStatus = 2; // unknown
252    else
253        iStatus = 1; // infeasible
254        /*
255          If we're feasible according to the solver, evaluate integer feasibility.
256        */
257    bool feasible = iStatus != 1;
258    if (feasible) {
259        double integerTolerance =
260            model->getDblParam(CbcModel::CbcIntegerTolerance);
261        const int * integerVariable = model->integerVariable();
262        for (i = 0; i < numberIntegers; i++) {
263            int j = integerVariable[i];
264            double value = solution[j];
265            double nearest = floor(value + 0.5);
266            if (fabs(value - nearest) > integerTolerance)
267                unsatisfied++;
268        }
269    }
270        /*
271          Finally, update the object. Defaults (080104) are TYPE2 = 0, INFEAS = 1.
272
273          Pseudocosts are at heart the average of actual costs for a branch. We just
274          need to update the information used to calculate that average.
275        */
276    int way = object_->way();
277    double value = object_->value();
278    //#define TYPE2 1
279    //#define TYPERATIO 0.9
280    if (way < 0) {
281        // down
282        if (feasible) {
283            double movement = value - floor(value);
284            movement = CoinMax(movement, MINIMUM_MOVEMENT);
285            //printf("(down change %g value down %g ",change,movement);
286            object->incrementNumberTimesDown();
287            object->addToSumDownChange(1.0e-30 + movement);
288            object->addToSumDownDecrease(originalUnsatisfied - unsatisfied);
289#if TYPE2==0
290            object->addToSumDownCost(change / (1.0e-30 + movement));
291            object->setDownDynamicPseudoCost(object->sumDownCost() /
292                                             static_cast<double> (object->numberTimesDown()));
293#elif TYPE2==1
294            object->addToSumDownCost(change);
295            object->setDownDynamicPseudoCost(object->sumDownCost() / object->sumDownChange());
296#elif TYPE2==2
297            object->addToSumDownCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement));
298            object->setDownDynamicPseudoCost(object->sumDownCost()*(TYPERATIO / object->sumDownChange() + (1.0 - TYPERATIO) / (double) object->numberTimesDown()));
299#endif
300        } else {
301            //printf("(down infeasible value down %g ",change,movement);
302            object->incrementNumberTimesDown();
303            object->incrementNumberTimesDownInfeasible();
304#if INFEAS==2
305            double distanceToCutoff = 0.0;
306            double objectiveValue = model->getCurrentMinimizationObjValue();
307            distanceToCutoff =  model->getCutoff()  - originalValue;
308            if (distanceToCutoff < 1.0e20)
309                change = distanceToCutoff * 2.0;
310            else
311                change = object->downDynamicPseudoCost() * movement * 10.0;
312            change = CoinMax(1.0e-12 * (1.0 + fabs(originalValue)), change);
313            object->addToSumDownChange(1.0e-30 + movement);
314            object->addToSumDownDecrease(originalUnsatisfied - unsatisfied);
315#if TYPE2==0
316            object->addToSumDownCost(change / (1.0e-30 + movement));
317            object->setDownDynamicPseudoCost(object->sumDownCost() / (double) object->numberTimesDown());
318#elif TYPE2==1
319            object->addToSumDownCost(change);
320            object->setDownDynamicPseudoCost(object->sumDownCost() / object->sumDownChange());
321#elif TYPE2==2
322            object->addToSumDownCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement));
323            object->setDownDynamicPseudoCost(object->sumDownCost()*(TYPERATIO / object->sumDownChange() + (1.0 - TYPERATIO) / (double) object->numberTimesDown()));
324#endif
325#endif
326        }
327    } else {
328        // up
329        if (feasible) {
330            double movement = ceil(value) - value;
331            movement = CoinMax(movement, MINIMUM_MOVEMENT);
332            //printf("(up change %g value down %g ",change,movement);
333            object->incrementNumberTimesUp();
334            object->addToSumUpChange(1.0e-30 + movement);
335            object->addToSumUpDecrease(unsatisfied - originalUnsatisfied);
336#if TYPE2==0
337            object->addToSumUpCost(change / (1.0e-30 + movement));
338            object->setUpDynamicPseudoCost(object->sumUpCost() /
339                                           static_cast<double> (object->numberTimesUp()));
340#elif TYPE2==1
341            object->addToSumUpCost(change);
342            object->setUpDynamicPseudoCost(object->sumUpCost() / object->sumUpChange());
343#elif TYPE2==2
344            object->addToSumUpCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement));
345            object->setUpDynamicPseudoCost(object->sumUpCost()*(TYPERATIO / object->sumUpChange() + (1.0 - TYPERATIO) / (double) object->numberTimesUp()));
346#endif
347        } else {
348            //printf("(up infeasible value down %g ",change,movement);
349            object->incrementNumberTimesUp();
350            object->incrementNumberTimesUpInfeasible();
351#if INFEAS==2
352            double distanceToCutoff = 0.0;
353            double objectiveValue = model->getCurrentMinimizationObjValue();
354            distanceToCutoff =  model->getCutoff()  - originalValue;
355            if (distanceToCutoff < 1.0e20)
356                change = distanceToCutoff * 2.0;
357            else
358                change = object->upDynamicPseudoCost() * movement * 10.0;
359            change = CoinMax(1.0e-12 * (1.0 + fabs(originalValue)), change);
360            object->addToSumUpChange(1.0e-30 + movement);
361            object->addToSumUpDecrease(unsatisfied - originalUnsatisfied);
362#if TYPE2==0
363            object->addToSumUpCost(change / (1.0e-30 + movement));
364            object->setUpDynamicPseudoCost(object->sumUpCost() / (double) object->numberTimesUp());
365#elif TYPE2==1
366            object->addToSumUpCost(change);
367            object->setUpDynamicPseudoCost(object->sumUpCost() / object->sumUpChange());
368#elif TYPE2==2
369            object->addToSumUpCost(change*TYPERATIO + (1.0 - TYPERATIO)*change / (1.0e-30 + movement));
370            object->setUpDynamicPseudoCost(object->sumUpCost()*(TYPERATIO / object->sumUpChange() + (1.0 - TYPERATIO) / (double) object->numberTimesUp()));
371#endif
372#endif
373        }
374    }
375    //object->print(1,0.5);
376    delete object_;
377    object_ = NULL;
378}
379
380/*
381  Simple dynamic decision algorithm. Compare based on infeasibility (numInfUp,
382  numInfDown) until a solution is found by search, then switch to change in
383  objective (changeUp, changeDown). Note that bestSoFar is remembered in
384  bestObject_, so the parameter bestSoFar is unused.
385*/
386
387int
388CbcBranchDynamicDecision::betterBranch(CbcBranchingObject * thisOne,
389                                       CbcBranchingObject * /*bestSoFar*/,
390                                       double changeUp, int numInfUp,
391                                       double changeDown, int numInfDown)
392{
393    CbcModel * model = thisOne->model();
394    int stateOfSearch = model->stateOfSearch() % 10;
395    int betterWay = 0;
396    double value = 0.0;
397    if (!bestObject_) {
398        bestCriterion_ = -1.0e30;
399        bestNumberUp_ = COIN_INT_MAX;
400        bestNumberDown_ = COIN_INT_MAX;
401    }
402    // maybe branch up more if no solution or not many nodes done?
403    if (stateOfSearch <= 2) {
404        //#define TRY_STUFF 1
405#ifdef TRY_STUFF
406        // before solution - choose smallest number
407        // could add in depth as well
408        int bestNumber = CoinMin(bestNumberUp_, bestNumberDown_);
409        if (numInfUp < numInfDown) {
410            if (numInfUp < bestNumber) {
411                betterWay = 1;
412            } else if (numInfUp == bestNumber) {
413                if (changeUp < bestChangeUp_)
414                    betterWay = 1;
415            }
416        } else if (numInfUp > numInfDown) {
417            if (numInfDown < bestNumber) {
418                betterWay = -1;
419            } else if (numInfDown == bestNumber) {
420                if (changeDown < bestChangeDown_)
421                    betterWay = -1;
422            }
423        } else {
424            // up and down have same number
425            bool better = false;
426            if (numInfUp < bestNumber) {
427                better = true;
428            } else if (numInfUp == bestNumber) {
429                if (CoinMin(changeUp, changeDown) < CoinMin(bestChangeUp_, bestChangeDown_) - 1.0e-5)
430                    better = true;;
431            }
432            if (better) {
433                // see which way
434                if (changeUp <= changeDown)
435                    betterWay = 1;
436                else
437                    betterWay = -1;
438            }
439        }
440        if (betterWay) {
441            value = CoinMin(numInfUp, numInfDown);
442        }
443#else
444        // use pseudo shadow prices modified by locks
445        // test testosi
446#if 1
447        double objectiveValue = model->getCurrentMinimizationObjValue();
448        double distanceToCutoff =  model->getCutoff()  - objectiveValue;
449        if (distanceToCutoff < 1.0e20)
450            distanceToCutoff *= 10.0;
451        else
452            distanceToCutoff = 1.0e2 + fabs(objectiveValue);
453        distanceToCutoff = CoinMax(distanceToCutoff, 1.0e-12 * (1.0 + fabs(objectiveValue)));
454        double continuousObjective = model->getContinuousObjective();
455        double distanceToCutoffC =  model->getCutoff()  - continuousObjective;
456        if (distanceToCutoffC > 1.0e20)
457            distanceToCutoffC = 1.0e2 + fabs(objectiveValue);
458        distanceToCutoffC = CoinMax(distanceToCutoffC, 1.0e-12 * (1.0 + fabs(objectiveValue)));
459        int numberInfC = model->getContinuousInfeasibilities();
460        double perInf = distanceToCutoffC / static_cast<double> (numberInfC);
461        assert (perInf > 0.0);
462        //int numberIntegers = model->numberIntegers();
463        changeDown += perInf * numInfDown;
464        changeUp += perInf * numInfUp;
465#if 0
466        if (numInfDown == 1) {
467            if (numInfUp == 1) {
468                changeUp += 1.0e6;
469                changeDown += 1.0e6;
470            } else if (changeDown <= 1.5*changeUp) {
471                changeUp += 1.0e6;
472            }
473        } else if (numInfUp == 1 && changeUp <= 1.5*changeDown) {
474            changeDown += 1.0e6;
475        }
476#endif
477#endif
478        double minValue = CoinMin(changeDown, changeUp);
479        double maxValue = CoinMax(changeDown, changeUp);
480        value = WEIGHT_BEFORE * minValue + (1.0 - WEIGHT_BEFORE) * maxValue;
481        if (value > bestCriterion_ + 1.0e-8) {
482            if (changeUp <= 1.5*changeDown) {
483                betterWay = 1;
484            } else {
485                betterWay = -1;
486            }
487        }
488#endif
489    } else {
490#define TRY_STUFF 2
491#if TRY_STUFF > 1
492        // Get current number of infeasibilities, cutoff and current objective
493        CbcNode * node = model->currentNode();
494        int numberUnsatisfied = node->numberUnsatisfied();
495        double cutoff = model->getCutoff();
496        double objectiveValue = node->objectiveValue();
497#endif
498        // got a solution
499        double minValue = CoinMin(changeDown, changeUp);
500        double maxValue = CoinMax(changeDown, changeUp);
501        // Reduce
502#ifdef TRY_STUFF
503        //maxValue = CoinMin(maxValue,minValue*4.0);
504#else
505        //maxValue = CoinMin(maxValue,minValue*2.0);
506#endif
507#ifndef WEIGHT_PRODUCT
508        value = WEIGHT_AFTER * minValue + (1.0 - WEIGHT_AFTER) * maxValue;
509#else
510        double minProductWeight = model->getDblParam(CbcModel::CbcSmallChange);
511        value = CoinMax(minValue, minProductWeight) * CoinMax(maxValue, minProductWeight);
512        //value += minProductWeight*minValue;
513#endif
514        double useValue = value;
515        double useBest = bestCriterion_;
516#if TRY_STUFF>1
517        int thisNumber = CoinMin(numInfUp, numInfDown);
518        int bestNumber = CoinMin(bestNumberUp_, bestNumberDown_);
519        double distance = cutoff - objectiveValue;
520        assert (distance >= 0.0);
521        if (useValue + 0.1*distance > useBest && useValue*1.1 > useBest &&
522                useBest + 0.1*distance > useValue && useBest*1.1 > useValue) {
523            // not much in it - look at unsatisfied
524            if (thisNumber < numberUnsatisfied || bestNumber < numberUnsatisfied) {
525                double perInteger = distance / (static_cast<double> (numberUnsatisfied));
526                useValue += thisNumber * perInteger;
527                useBest += bestNumber * perInteger;
528            }
529        }
530#endif
531        if (useValue > useBest + 1.0e-8) {
532            if (changeUp <= 1.5*changeDown) {
533                betterWay = 1;
534            } else {
535                betterWay = -1;
536            }
537        }
538    }
539#ifdef COIN_DEVELOP
540    History hist;
541    {
542        CbcDynamicPseudoCostBranchingObject * branchingObject =
543            dynamic_cast<CbcDynamicPseudoCostBranchingObject *>(thisOne);
544        if (branchingObject) {
545            CbcSimpleIntegerDynamicPseudoCost *  object = branchingObject->object();
546            assert (object);
547            hist.where_ = 'C';
548            hist.status_ = ' ';
549            hist.sequence_ = object->columnNumber();
550            hist.numberUp_ = object->numberTimesUp();
551            hist.numberUpInf_ = numInfUp;
552            hist.sumUp_ = object->sumUpCost();
553            hist.upEst_ = changeUp;
554            hist.numberDown_ = object->numberTimesDown();
555            hist.numberDownInf_ = numInfDown;
556            hist.sumDown_ = object->sumDownCost();
557            hist.downEst_ = changeDown;
558        }
559    }
560#endif
561    if (betterWay) {
562#ifdef COIN_DEVELOP
563        hist.status_ = 'B';
564#endif
565        // maybe change better way
566        CbcDynamicPseudoCostBranchingObject * branchingObject =
567            dynamic_cast<CbcDynamicPseudoCostBranchingObject *>(thisOne);
568        if (branchingObject) {
569            CbcSimpleIntegerDynamicPseudoCost *  object = branchingObject->object();
570            double separator = object->upDownSeparator();
571            if (separator > 0.0) {
572                const double * solution = thisOne->model()->testSolution();
573                double valueVariable = solution[object->columnNumber()];
574                betterWay = (valueVariable - floor(valueVariable) >= separator) ? 1 : -1;
575            }
576        }
577        bestCriterion_ = value;
578        bestChangeUp_ = changeUp;
579        bestNumberUp_ = numInfUp;
580        bestChangeDown_ = changeDown;
581        bestNumberDown_ = numInfDown;
582        bestObject_ = thisOne;
583        // See if user is overriding way
584        if (thisOne->object() && thisOne->object()->preferredWay())
585            betterWay = thisOne->object()->preferredWay();
586    }
587#ifdef COIN_DEVELOP
588    addRecord(hist);
589#endif
590    return betterWay;
591}
592/* Sets or gets best criterion so far */
593void
594CbcBranchDynamicDecision::setBestCriterion(double value)
595{
596    bestCriterion_ = value;
597}
598double
599CbcBranchDynamicDecision::getBestCriterion() const
600{
601    return bestCriterion_;
602}
603#ifdef COIN_DEVELOP
604void printHistory(const char * file)
605{
606    if (!numberHistory)
607        return;
608    FILE * fp = fopen(file, "w");
609    assert(fp);
610    int numberIntegers = 0;
611    int i;
612    for (i = 0; i < numberHistory; i++) {
613        if (history[i].where_ != 'C' || history[i].status_ != 'I')
614            numberIntegers = CoinMax(numberIntegers, history[i].sequence_);
615    }
616    numberIntegers++;
617    for (int iC = 0; iC < numberIntegers; iC++) {
618        int n = 0;
619        for (i = 0; i < numberHistory; i++) {
620            if (history[i].sequence_ == iC) {
621                if (!n)
622                    fprintf(fp, "XXX %d\n", iC);
623                n++;
624                fprintf(fp, "%c%c up %8d %8d %12.5f %12.5f down  %8d %8d %12.5f %12.5f\n",
625                        history[i].where_,
626                        history[i].status_,
627                        history[i].numberUp_,
628                        history[i].numberUpInf_,
629                        history[i].sumUp_,
630                        history[i].upEst_,
631                        history[i].numberDown_,
632                        history[i].numberDownInf_,
633                        history[i].sumDown_,
634                        history[i].downEst_);
635            }
636        }
637    }
638    fclose(fp);
639}
640#endif
641
642// Default Constructor
643CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject()
644        : CbcIntegerBranchingObject()
645{
646    changeInGuessed_ = 1.0e-5;
647    object_ = NULL;
648}
649
650// Useful constructor
651CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject (CbcModel * model,
652        int variable,
653        int way , double value,
654        CbcSimpleIntegerDynamicPseudoCost * object)
655        : CbcIntegerBranchingObject(model, variable, way, value)
656{
657    changeInGuessed_ = 1.0e-5;
658    object_ = object;
659}
660// Does part of work for constructor
661void
662CbcDynamicPseudoCostBranchingObject::fillPart (int variable,
663        int way , double value,
664        CbcSimpleIntegerDynamicPseudoCost * object)
665{
666    CbcIntegerBranchingObject::fillPart(variable, way, value);
667    changeInGuessed_ = 1.0e-5;
668    object_ = object;
669}
670// Useful constructor for fixing
671CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject (CbcModel * model,
672        int variable, int way,
673        double lowerValue,
674        double /*upperValue*/)
675        : CbcIntegerBranchingObject(model, variable, way, lowerValue)
676{
677    changeInGuessed_ = 1.0e100;
678    object_ = NULL;
679}
680
681
682// Copy constructor
683CbcDynamicPseudoCostBranchingObject::CbcDynamicPseudoCostBranchingObject (
684    const CbcDynamicPseudoCostBranchingObject & rhs)
685        : CbcIntegerBranchingObject(rhs)
686{
687    changeInGuessed_ = rhs.changeInGuessed_;
688    object_ = rhs.object_;
689}
690
691// Assignment operator
692CbcDynamicPseudoCostBranchingObject &
693CbcDynamicPseudoCostBranchingObject::operator=( const CbcDynamicPseudoCostBranchingObject & rhs)
694{
695    if (this != &rhs) {
696        CbcIntegerBranchingObject::operator=(rhs);
697        changeInGuessed_ = rhs.changeInGuessed_;
698        object_ = rhs.object_;
699    }
700    return *this;
701}
702CbcBranchingObject *
703CbcDynamicPseudoCostBranchingObject::clone() const
704{
705    return (new CbcDynamicPseudoCostBranchingObject(*this));
706}
707
708// Destructor
709CbcDynamicPseudoCostBranchingObject::~CbcDynamicPseudoCostBranchingObject ()
710{
711}
712
713/*
714  Perform a branch by adjusting the bounds of the specified variable. Note
715  that each arm of the branch advances the object to the next arm by
716  advancing the value of way_.
717
718  Providing new values for the variable's lower and upper bounds for each
719  branching direction gives a little bit of additional flexibility and will
720  be easily extensible to multi-way branching.
721  Returns change in guessed objective on next branch
722*/
723double
724CbcDynamicPseudoCostBranchingObject::branch()
725{
726    CbcIntegerBranchingObject::branch();
727    return changeInGuessed_;
728}
729/* Some branchingObjects may claim to be able to skip
730   strong branching.  If so they have to fill in CbcStrongInfo.
731   The object mention in incoming CbcStrongInfo must match.
732   Returns nonzero if skip is wanted */
733int
734CbcDynamicPseudoCostBranchingObject::fillStrongInfo( CbcStrongInfo & info)
735{
736    assert (object_);
737    assert (info.possibleBranch == this);
738    info.upMovement = object_->upDynamicPseudoCost() * (ceil(value_) - value_);
739    info.downMovement = object_->downDynamicPseudoCost() * (value_ - floor(value_));
740    info.numIntInfeasUp  -= static_cast<int> (object_->sumUpDecrease() /
741                            (1.0e-12 + static_cast<double> (object_->numberTimesUp())));
742    info.numIntInfeasUp = CoinMax(info.numIntInfeasUp, 0);
743    info.numObjInfeasUp = 0;
744    info.finishedUp = false;
745    info.numItersUp = 0;
746    info.numIntInfeasDown  -= static_cast<int> (object_->sumDownDecrease() /
747                              (1.0e-12 + static_cast<double> (object_->numberTimesDown())));
748    info.numIntInfeasDown = CoinMax(info.numIntInfeasDown, 0);
749    info.numObjInfeasDown = 0;
750    info.finishedDown = false;
751    info.numItersDown = 0;
752    info.fix = 0;
753    if (object_->numberTimesUp() < object_->numberBeforeTrust() +
754            2*object_->numberTimesUpInfeasible() ||
755            object_->numberTimesDown() < object_->numberBeforeTrust() +
756            2*object_->numberTimesDownInfeasible()) {
757        return 0;
758    } else {
759        return 1;
760    }
761}
Note: See TracBrowser for help on using the repository browser.