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

Last change on this file since 1899 was 1899, checked in by stefan, 5 years ago

fixup svn properties

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