source: trunk/Cbc/src/CbcGeneralDepth.cpp @ 1573

Last change on this file since 1573 was 1573, checked in by lou, 8 years ago

Change to EPL license notice.

File size: 24.2 KB
Line 
1// $Id$
2// Copyright (C) 2002, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6// Edwin 11/10/2009-- carved out of CbcBranchActual
7
8#if defined(_MSC_VER)
9// Turn off compiler warning about long names
10#  pragma warning(disable:4786)
11#endif
12#include <cassert>
13#include <cstdlib>
14#include <cmath>
15#include <cfloat>
16//#define CBC_DEBUG
17
18#include "CoinTypes.hpp"
19#include "OsiSolverInterface.hpp"
20#include "OsiSolverBranch.hpp"
21#include "CbcModel.hpp"
22#include "CbcMessage.hpp"
23#include "CbcGeneralDepth.hpp"
24#include "CbcBranchActual.hpp"
25#include "CoinSort.hpp"
26#include "CoinError.hpp"
27
28#ifdef COIN_HAS_CLP
29#include "OsiClpSolverInterface.hpp"
30#include "CoinWarmStartBasis.hpp"
31#include "ClpNode.hpp"
32#include "CbcBranchDynamic.hpp"
33// Default Constructor
34CbcGeneralDepth::CbcGeneralDepth ()
35        : CbcGeneral(),
36        maximumDepth_(0),
37        maximumNodes_(0),
38        whichSolution_(-1),
39        numberNodes_(0),
40        nodeInfo_(NULL)
41{
42}
43
44// Useful constructor (which are integer indices)
45CbcGeneralDepth::CbcGeneralDepth (CbcModel * model, int maximumDepth)
46        : CbcGeneral(model),
47        maximumDepth_(maximumDepth),
48        maximumNodes_(0),
49        whichSolution_(-1),
50        numberNodes_(0),
51        nodeInfo_(NULL)
52{
53    assert(maximumDepth_ < 1000000);
54    if (maximumDepth_ > 0)
55        maximumNodes_ = (1 << maximumDepth_) + 1 + maximumDepth_;
56    else if (maximumDepth_ < 0)
57        maximumNodes_ = 1 + 1 - maximumDepth_;
58    else
59        maximumNodes_ = 0;
60#define MAX_NODES 100
61    maximumNodes_ = CoinMin(maximumNodes_, 1 + maximumDepth_ + MAX_NODES);
62    if (maximumNodes_) {
63        nodeInfo_ = new ClpNodeStuff();
64        nodeInfo_->maximumNodes_ = maximumNodes_;
65        ClpNodeStuff * info = nodeInfo_;
66        // for reduced costs and duals
67        info->solverOptions_ |= 7;
68        if (maximumDepth_ > 0) {
69            info->nDepth_ = maximumDepth_;
70        } else {
71            info->nDepth_ = - maximumDepth_;
72            info->solverOptions_ |= 32;
73        }
74        ClpNode ** nodeInfo = new ClpNode * [maximumNodes_];
75        for (int i = 0; i < maximumNodes_; i++)
76            nodeInfo[i] = NULL;
77        info->nodeInfo_ = nodeInfo;
78    } else {
79        nodeInfo_ = NULL;
80    }
81}
82
83// Copy constructor
84CbcGeneralDepth::CbcGeneralDepth ( const CbcGeneralDepth & rhs)
85        : CbcGeneral(rhs)
86{
87    maximumDepth_ = rhs.maximumDepth_;
88    maximumNodes_ = rhs.maximumNodes_;
89    whichSolution_ = -1;
90    numberNodes_ = 0;
91    if (maximumNodes_) {
92        assert (rhs.nodeInfo_);
93        nodeInfo_ = new ClpNodeStuff(*rhs.nodeInfo_);
94        nodeInfo_->maximumNodes_ = maximumNodes_;
95        ClpNodeStuff * info = nodeInfo_;
96        if (maximumDepth_ > 0) {
97            info->nDepth_ = maximumDepth_;
98        } else {
99            info->nDepth_ = - maximumDepth_;
100            info->solverOptions_ |= 32;
101        }
102        if (!info->nodeInfo_) {
103            ClpNode ** nodeInfo = new ClpNode * [maximumNodes_];
104            for (int i = 0; i < maximumNodes_; i++)
105                nodeInfo[i] = NULL;
106            info->nodeInfo_ = nodeInfo;
107        }
108    } else {
109        nodeInfo_ = NULL;
110    }
111}
112
113// Clone
114CbcObject *
115CbcGeneralDepth::clone() const
116{
117    return new CbcGeneralDepth(*this);
118}
119
120// Assignment operator
121CbcGeneralDepth &
122CbcGeneralDepth::operator=( const CbcGeneralDepth & rhs)
123{
124    if (this != &rhs) {
125        CbcGeneral::operator=(rhs);
126        delete nodeInfo_;
127        maximumDepth_ = rhs.maximumDepth_;
128        maximumNodes_ = rhs.maximumNodes_;
129        whichSolution_ = -1;
130        numberNodes_ = 0;
131        if (maximumDepth_) {
132            assert (rhs.nodeInfo_);
133            nodeInfo_ = new ClpNodeStuff(*rhs.nodeInfo_);
134            nodeInfo_->maximumNodes_ = maximumNodes_;
135        } else {
136            nodeInfo_ = NULL;
137        }
138    }
139    return *this;
140}
141
142// Destructor
143CbcGeneralDepth::~CbcGeneralDepth ()
144{
145    delete nodeInfo_;
146}
147// Infeasibility - large is 0.5
148double
149CbcGeneralDepth::infeasibility(const OsiBranchingInformation * /*info*/,
150                               int &/*preferredWay*/) const
151{
152    whichSolution_ = -1;
153    // should use genuine OsiBranchingInformation usefulInfo = model_->usefulInformation();
154    // for now assume only called when correct
155    //if (usefulInfo.depth_>=4&&!model_->parentModel()
156    //     &&(usefulInfo.depth_%2)==0) {
157    if (true) {
158        OsiSolverInterface * solver = model_->solver();
159        OsiClpSolverInterface * clpSolver
160        = dynamic_cast<OsiClpSolverInterface *> (solver);
161        if (clpSolver) {
162            ClpNodeStuff * info = nodeInfo_;
163            info->integerTolerance_ = model_->getIntegerTolerance();
164            info->integerIncrement_ = model_->getCutoffIncrement();
165            info->numberBeforeTrust_ = model_->numberBeforeTrust();
166            info->stateOfSearch_ = model_->stateOfSearch();
167            // Compute "small" change in branch
168            int nBranches = model_->getIntParam(CbcModel::CbcNumberBranches);
169            if (nBranches) {
170                double average = model_->getDblParam(CbcModel::CbcSumChange) / static_cast<double>(nBranches);
171                info->smallChange_ =
172                    CoinMax(average * 1.0e-5, model_->getDblParam(CbcModel::CbcSmallestChange));
173                info->smallChange_ = CoinMax(info->smallChange_, 1.0e-8);
174            } else {
175                info->smallChange_ = 1.0e-8;
176            }
177            int numberIntegers = model_->numberIntegers();
178            double * down = new double[numberIntegers];
179            double * up = new double[numberIntegers];
180            int * priority = new int[numberIntegers];
181            int * numberDown = new int[numberIntegers];
182            int * numberUp = new int[numberIntegers];
183            int * numberDownInfeasible = new int[numberIntegers];
184            int * numberUpInfeasible = new int[numberIntegers];
185            model_->fillPseudoCosts(down, up, priority, numberDown, numberUp,
186                                    numberDownInfeasible, numberUpInfeasible);
187            info->fillPseudoCosts(down, up, priority, numberDown, numberUp,
188                                  numberDownInfeasible,
189                                  numberUpInfeasible, numberIntegers);
190            info->presolveType_ = 1;
191            delete [] down;
192            delete [] up;
193            delete [] numberDown;
194            delete [] numberUp;
195            delete [] numberDownInfeasible;
196            delete [] numberUpInfeasible;
197            bool takeHint;
198            OsiHintStrength strength;
199            solver->getHintParam(OsiDoReducePrint, takeHint, strength);
200            ClpSimplex * simplex = clpSolver->getModelPtr();
201            int saveLevel = simplex->logLevel();
202            if (strength != OsiHintIgnore && takeHint && saveLevel == 1)
203                simplex->setLogLevel(0);
204            clpSolver->setBasis();
205            whichSolution_ = simplex->fathomMany(info);
206            //printf("FAT %d nodes, %d iterations\n",
207            //info->numberNodesExplored_,info->numberIterations_);
208            //printf("CbcBranch %d rows, %d columns\n",clpSolver->getNumRows(),
209            //     clpSolver->getNumCols());
210            model_->incrementExtra(info->numberNodesExplored_,
211                                   info->numberIterations_);
212            // update pseudo costs
213            double smallest = 1.0e50;
214            double largest = -1.0;
215            OsiObject ** objects = model_->objects();
216#ifndef NDEBUG
217            const int * integerVariable = model_->integerVariable();
218#endif
219            for (int i = 0; i < numberIntegers; i++) {
220#ifndef NDEBUG
221                CbcSimpleIntegerDynamicPseudoCost * obj =
222                    dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(objects[i]) ;
223                assert (obj && obj->columnNumber() == integerVariable[i]);
224#else
225                CbcSimpleIntegerDynamicPseudoCost * obj =
226                    static_cast <CbcSimpleIntegerDynamicPseudoCost *>(objects[i]) ;
227#endif
228                if (info->numberUp_[i] > 0) {
229                    if (info->downPseudo_[i] > largest)
230                        largest = info->downPseudo_[i];
231                    if (info->downPseudo_[i] < smallest)
232                        smallest = info->downPseudo_[i];
233                    if (info->upPseudo_[i] > largest)
234                        largest = info->upPseudo_[i];
235                    if (info->upPseudo_[i] < smallest)
236                        smallest = info->upPseudo_[i];
237                    obj->updateAfterMini(info->numberDown_[i],
238                                         info->numberDownInfeasible_[i],
239                                         info->downPseudo_[i],
240                                         info->numberUp_[i],
241                                         info->numberUpInfeasible_[i],
242                                         info->upPseudo_[i]);
243                }
244            }
245            //printf("range of costs %g to %g\n",smallest,largest);
246            simplex->setLogLevel(saveLevel);
247            numberNodes_ = info->nNodes_;
248            int numberDo = numberNodes_;
249            if (whichSolution_ >= 0)
250                numberDo--;
251            if (numberDo > 0) {
252                return 0.5;
253            } else {
254                // no solution
255                return COIN_DBL_MAX; // say infeasible
256            }
257        } else {
258            return -1.0;
259        }
260    } else {
261        return -1.0;
262    }
263}
264
265// This looks at solution and sets bounds to contain solution
266void
267CbcGeneralDepth::feasibleRegion()
268{
269    // Other stuff should have done this
270}
271// Redoes data when sequence numbers change
272void
273CbcGeneralDepth::redoSequenceEtc(CbcModel * /*model*/,
274                                 int /*numberColumns*/,
275                                 const int * /*originalColumns*/)
276{
277}
278
279//#define CHECK_PATH
280#ifdef CHECK_PATH
281extern const double * debuggerSolution_Z;
282extern int numberColumns_Z;
283extern int gotGoodNode_Z;
284#endif
285CbcBranchingObject *
286CbcGeneralDepth::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * /*info*/, int /*way*/)
287{
288    int numberDo = numberNodes_;
289    if (whichSolution_ >= 0)
290        numberDo--;
291    assert (numberDo > 0);
292    // create object
293    CbcGeneralBranchingObject * branch = new CbcGeneralBranchingObject(model_);
294    // skip solution
295    branch->numberSubProblems_ = numberDo;
296    // If parentBranch_ back in then will have to be 2*
297    branch->numberSubLeft_ = numberDo;
298    branch->setNumberBranches(numberDo);
299    CbcSubProblem * sub = new CbcSubProblem[numberDo];
300    int iProb = 0;
301    branch->subProblems_ = sub;
302    branch->numberRows_ = model_->solver()->getNumRows();
303    int iNode;
304    //OsiSolverInterface * solver = model_->solver();
305    OsiClpSolverInterface * clpSolver
306    = dynamic_cast<OsiClpSolverInterface *> (solver);
307    assert (clpSolver);
308    ClpSimplex * simplex = clpSolver->getModelPtr();
309    int numberColumns = simplex->numberColumns();
310    double * lowerBefore = CoinCopyOfArray(simplex->getColLower(),
311                                           numberColumns);
312    double * upperBefore = CoinCopyOfArray(simplex->getColUpper(),
313                                           numberColumns);
314    ClpNodeStuff * info = nodeInfo_;
315    double * weight = new double[numberNodes_];
316    int * whichNode = new int [numberNodes_];
317    // Sort
318    for (iNode = 0; iNode < numberNodes_; iNode++) {
319        if (iNode != whichSolution_) {
320            double objectiveValue = info->nodeInfo_[iNode]->objectiveValue();
321            double sumInfeasibilities = info->nodeInfo_[iNode]->sumInfeasibilities();
322            int numberInfeasibilities = info->nodeInfo_[iNode]->numberInfeasibilities();
323            double thisWeight = 0.0;
324#if 1
325            // just closest
326            thisWeight = 1.0e9 * numberInfeasibilities;
327            thisWeight += sumInfeasibilities;
328            thisWeight += 1.0e-7 * objectiveValue;
329            // Try estimate
330            thisWeight = info->nodeInfo_[iNode]->estimatedSolution();
331#else
332            thisWeight = 1.0e-3 * numberInfeasibilities;
333            thisWeight += 1.0e-5 * sumInfeasibilities;
334            thisWeight += objectiveValue;
335#endif
336            whichNode[iProb] = iNode;
337            weight[iProb++] = thisWeight;
338        }
339    }
340    assert (iProb == numberDo);
341    CoinSort_2(weight, weight + numberDo, whichNode);
342    for (iProb = 0; iProb < numberDo; iProb++) {
343        iNode = whichNode[iProb];
344        ClpNode * node = info->nodeInfo_[iNode];
345        // move bounds
346        node->applyNode(simplex, 3);
347        // create subproblem
348        sub[iProb] = CbcSubProblem(clpSolver, lowerBefore, upperBefore,
349                                   node->statusArray(), node->depth());
350        sub[iProb].objectiveValue_ = node->objectiveValue();
351        sub[iProb].sumInfeasibilities_ = node->sumInfeasibilities();
352        sub[iProb].numberInfeasibilities_ = node->numberInfeasibilities();
353#ifdef CHECK_PATH
354        if (simplex->numberColumns() == numberColumns_Z) {
355            bool onOptimal = true;
356            const double * columnLower = simplex->columnLower();
357            const double * columnUpper = simplex->columnUpper();
358            for (int i = 0; i < numberColumns_Z; i++) {
359                if (iNode == gotGoodNode_Z)
360                    printf("good %d %d %g %g\n", iNode, i, columnLower[i], columnUpper[i]);
361                if (columnUpper[i] < debuggerSolution_Z[i] || columnLower[i] > debuggerSolution_Z[i] && simplex->isInteger(i)) {
362                    onOptimal = false;
363                    break;
364                }
365            }
366            if (onOptimal) {
367                printf("adding to node %x as %d - objs\n", this, iProb);
368                for (int j = 0; j <= iProb; j++)
369                    printf("%d %g\n", j, sub[j].objectiveValue_);
370            }
371        }
372#endif
373    }
374    delete [] weight;
375    delete [] whichNode;
376    const double * lower = solver->getColLower();
377    const double * upper = solver->getColUpper();
378    // restore bounds
379    for ( int j = 0; j < numberColumns; j++) {
380        if (lowerBefore[j] != lower[j])
381            solver->setColLower(j, lowerBefore[j]);
382        if (upperBefore[j] != upper[j])
383            solver->setColUpper(j, upperBefore[j]);
384    }
385    delete [] upperBefore;
386    delete [] lowerBefore;
387    return branch;
388}
389
390// Default Constructor
391CbcGeneralBranchingObject::CbcGeneralBranchingObject()
392        : CbcBranchingObject(),
393        subProblems_(NULL),
394        node_(NULL),
395        numberSubProblems_(0),
396        numberSubLeft_(0),
397        whichNode_(-1),
398        numberRows_(0)
399{
400    //  printf("CbcGeneral %x default constructor\n",this);
401}
402
403// Useful constructor
404CbcGeneralBranchingObject::CbcGeneralBranchingObject (CbcModel * model)
405        : CbcBranchingObject(model, -1, -1, 0.5),
406        subProblems_(NULL),
407        node_(NULL),
408        numberSubProblems_(0),
409        numberSubLeft_(0),
410        whichNode_(-1),
411        numberRows_(0)
412{
413    //printf("CbcGeneral %x useful constructor\n",this);
414}
415
416// Copy constructor
417CbcGeneralBranchingObject::CbcGeneralBranchingObject ( const CbcGeneralBranchingObject & rhs)
418        : CbcBranchingObject(rhs),
419        subProblems_(NULL),
420        node_(rhs.node_),
421        numberSubProblems_(rhs.numberSubProblems_),
422        numberSubLeft_(rhs.numberSubLeft_),
423        whichNode_(rhs.whichNode_),
424        numberRows_(rhs.numberRows_)
425{
426    abort();
427    if (numberSubProblems_) {
428        subProblems_ = new CbcSubProblem[numberSubProblems_];
429        for (int i = 0; i < numberSubProblems_; i++)
430            subProblems_[i] = rhs.subProblems_[i];
431    }
432}
433
434// Assignment operator
435CbcGeneralBranchingObject &
436CbcGeneralBranchingObject::operator=( const CbcGeneralBranchingObject & rhs)
437{
438    if (this != &rhs) {
439        abort();
440        CbcBranchingObject::operator=(rhs);
441        delete [] subProblems_;
442        numberSubProblems_ = rhs.numberSubProblems_;
443        numberSubLeft_ = rhs.numberSubLeft_;
444        whichNode_ = rhs.whichNode_;
445        numberRows_ = rhs.numberRows_;
446        if (numberSubProblems_) {
447            subProblems_ = new CbcSubProblem[numberSubProblems_];
448            for (int i = 0; i < numberSubProblems_; i++)
449                subProblems_[i] = rhs.subProblems_[i];
450        } else {
451            subProblems_ = NULL;
452        }
453        node_ = rhs.node_;
454    }
455    return *this;
456}
457CbcBranchingObject *
458CbcGeneralBranchingObject::clone() const
459{
460    return (new CbcGeneralBranchingObject(*this));
461}
462
463
464// Destructor
465CbcGeneralBranchingObject::~CbcGeneralBranchingObject ()
466{
467    //printf("CbcGeneral %x destructor\n",this);
468    delete [] subProblems_;
469}
470bool doingDoneBranch = false;
471double
472CbcGeneralBranchingObject::branch()
473{
474    double cutoff = model_->getCutoff();
475    //printf("GenB %x whichNode %d numberLeft %d which %d\n",
476    // this,whichNode_,numberBranchesLeft(),branchIndex());
477    if (whichNode_ < 0) {
478        assert (node_);
479        bool applied = false;
480        while (numberBranchesLeft()) {
481            int which = branchIndex();
482            decrementNumberBranchesLeft();
483            CbcSubProblem * thisProb = subProblems_ + which;
484            if (thisProb->objectiveValue_ < cutoff) {
485                //printf("branch %x (sub %x) which now %d\n",this,
486                //     subProblems_,which);
487                OsiSolverInterface * solver = model_->solver();
488                thisProb->apply(solver);
489                OsiClpSolverInterface * clpSolver
490                = dynamic_cast<OsiClpSolverInterface *> (solver);
491                assert (clpSolver);
492                // Move status to basis
493                clpSolver->setWarmStart(NULL);
494                //ClpSimplex * simplex = clpSolver->getModelPtr();
495                node_->setObjectiveValue(thisProb->objectiveValue_);
496                node_->setSumInfeasibilities(thisProb->sumInfeasibilities_);
497                node_->setNumberUnsatisfied(thisProb->numberInfeasibilities_);
498                applied = true;
499                doingDoneBranch = true;
500                break;
501            } else if (numberBranchesLeft()) {
502                node_->nodeInfo()->branchedOn() ;
503            }
504        }
505        if (!applied) {
506            // no good one
507            node_->setObjectiveValue(cutoff + 1.0e20);
508            node_->setSumInfeasibilities(1.0);
509            node_->setNumberUnsatisfied(1);
510            assert (whichNode_ < 0);
511        }
512    } else {
513        decrementNumberBranchesLeft();
514        CbcSubProblem * thisProb = subProblems_ + whichNode_;
515        assert (thisProb->objectiveValue_ < cutoff);
516        OsiSolverInterface * solver = model_->solver();
517        thisProb->apply(solver);
518        //OsiClpSolverInterface * clpSolver
519        //= dynamic_cast<OsiClpSolverInterface *> (solver);
520        //assert (clpSolver);
521        // Move status to basis
522        //clpSolver->setWarmStart(NULL);
523    }
524    return 0.0;
525}
526/* Double checks in case node can change its mind!
527   Can change objective etc */
528void
529CbcGeneralBranchingObject::checkIsCutoff(double cutoff)
530{
531    assert (node_);
532    int first = branchIndex();
533    int last = first + numberBranchesLeft();
534    for (int which = first; which < last; which++) {
535        CbcSubProblem * thisProb = subProblems_ + which;
536        if (thisProb->objectiveValue_ < cutoff) {
537            node_->setObjectiveValue(thisProb->objectiveValue_);
538            node_->setSumInfeasibilities(thisProb->sumInfeasibilities_);
539            node_->setNumberUnsatisfied(thisProb->numberInfeasibilities_);
540            break;
541        }
542    }
543}
544// Print what would happen
545void
546CbcGeneralBranchingObject::print()
547{
548    //printf("CbcGeneralObject has %d subproblems\n",numberSubProblems_);
549}
550// Fill in current objective etc
551void
552CbcGeneralBranchingObject::state(double & objectiveValue,
553                                 double & sumInfeasibilities,
554                                 int & numberUnsatisfied, int which) const
555{
556    assert (which >= 0 && which < numberSubProblems_);
557    const CbcSubProblem * thisProb = subProblems_ + which;
558    objectiveValue = thisProb->objectiveValue_;
559    sumInfeasibilities = thisProb->sumInfeasibilities_;
560    numberUnsatisfied = thisProb->numberInfeasibilities_;
561}
562/** Compare the original object of \c this with the original object of \c
563    brObj. Assumes that there is an ordering of the original objects.
564    This method should be invoked only if \c this and brObj are of the same
565    type.
566    Return negative/0/positive depending on whether \c this is
567    smaller/same/larger than the argument.
568*/
569int
570CbcGeneralBranchingObject::compareOriginalObject
571(const CbcBranchingObject* /*brObj*/) const
572{
573    throw("must implement");
574}
575
576/** Compare the \c this with \c brObj. \c this and \c brObj must be os the
577    same type and must have the same original object, but they may have
578    different feasible regions.
579    Return the appropriate CbcRangeCompare value (first argument being the
580    sub/superset if that's the case). In case of overlap (and if \c
581    replaceIfOverlap is true) replace the current branching object with one
582    whose feasible region is the overlap.
583*/
584CbcRangeCompare
585CbcGeneralBranchingObject::compareBranchingObject
586(const CbcBranchingObject* /*brObj*/, const bool /*replaceIfOverlap*/)
587{
588    throw("must implement");
589}
590
591// Default Constructor
592CbcOneGeneralBranchingObject::CbcOneGeneralBranchingObject()
593        : CbcBranchingObject(),
594        object_(NULL),
595        whichOne_(-1)
596{
597    //printf("CbcOneGeneral %x default constructor\n",this);
598}
599
600// Useful constructor
601CbcOneGeneralBranchingObject::CbcOneGeneralBranchingObject (CbcModel * model,
602        CbcGeneralBranchingObject * object,
603        int whichOne)
604        : CbcBranchingObject(model, -1, -1, 0.5),
605        object_(object),
606        whichOne_(whichOne)
607{
608    //printf("CbcOneGeneral %x useful constructor object %x %d left\n",this,
609    //   object_,object_->numberSubLeft_);
610    numberBranches_ = 1;
611}
612
613// Copy constructor
614CbcOneGeneralBranchingObject::CbcOneGeneralBranchingObject ( const CbcOneGeneralBranchingObject & rhs)
615        : CbcBranchingObject(rhs),
616        object_(rhs.object_),
617        whichOne_(rhs.whichOne_)
618{
619}
620
621// Assignment operator
622CbcOneGeneralBranchingObject &
623CbcOneGeneralBranchingObject::operator=( const CbcOneGeneralBranchingObject & rhs)
624{
625    if (this != &rhs) {
626        CbcBranchingObject::operator=(rhs);
627        object_ = rhs.object_;
628        whichOne_ = rhs.whichOne_;
629    }
630    return *this;
631}
632CbcBranchingObject *
633CbcOneGeneralBranchingObject::clone() const
634{
635    return (new CbcOneGeneralBranchingObject(*this));
636}
637
638
639// Destructor
640CbcOneGeneralBranchingObject::~CbcOneGeneralBranchingObject ()
641{
642    //printf("CbcOneGeneral %x destructor object %x %d left\n",this,
643    // object_,object_->numberSubLeft_);
644    assert (object_->numberSubLeft_ > 0 &&
645            object_->numberSubLeft_ < 1000000);
646    if (!object_->decrementNumberLeft()) {
647        // printf("CbcGeneral %x yy destructor\n",object_);
648        delete object_;
649    }
650}
651double
652CbcOneGeneralBranchingObject::branch()
653{
654    assert (numberBranchesLeft());
655    decrementNumberBranchesLeft();
656    assert (!numberBranchesLeft());
657    object_->setWhichNode(whichOne_);
658    object_->branch();
659    return 0.0;
660}
661/* Double checks in case node can change its mind!
662   Can change objective etc */
663void
664CbcOneGeneralBranchingObject::checkIsCutoff(double /*cutoff*/)
665{
666    assert (numberBranchesLeft());
667}
668// Print what would happen
669void
670CbcOneGeneralBranchingObject::print()
671{
672    //printf("CbcOneGeneralObject has 1 subproblem\n");
673}
674/** Compare the original object of \c this with the original object of \c
675    brObj. Assumes that there is an ordering of the original objects.
676    This method should be invoked only if \c this and brObj are of the same
677    type.
678    Return negative/0/positive depending on whether \c this is
679    smaller/same/larger than the argument.
680*/
681int
682CbcOneGeneralBranchingObject::compareOriginalObject
683(const CbcBranchingObject* /*brObj*/) const
684{
685    throw("must implement");
686}
687
688/** Compare the \c this with \c brObj. \c this and \c brObj must be os the
689    same type and must have the same original object, but they may have
690    different feasible regions.
691    Return the appropriate CbcRangeCompare value (first argument being the
692    sub/superset if that's the case). In case of overlap (and if \c
693    replaceIfOverlap is true) replace the current branching object with one
694    whose feasible region is the overlap.
695*/
696CbcRangeCompare
697CbcOneGeneralBranchingObject::compareBranchingObject
698(const CbcBranchingObject* /*brObj*/, const bool /*replaceIfOverlap*/)
699{
700    throw("must implement");
701}
702#endif
703
Note: See TracBrowser for help on using the repository browser.