text: // $Id: CbcGeneralDepth.cpp 2467 2019-01-03 21:26:29Z unxusr $
  // Copyright (C) 2002, International Business Machines
  // Corporation and others.  All Rights Reserved.
  // This code is licensed under the terms of the Eclipse Public License (EPL).
  
  // Edwin 11/10/2009-- carved out of CbcBranchActual
  
  #if defined(_MSC_VER)
  // Turn off compiler warning about long names
  #pragma warning(disable : 4786)
  #endif
  #include <cassert>
  #include <cstdlib>
  #include <cmath>
  #include <cfloat>
  //#define CBC_DEBUG
  
  #include "CoinTypes.hpp"
  #include "OsiSolverInterface.hpp"
  #include "OsiSolverBranch.hpp"
  #include "CbcModel.hpp"
  #include "CbcMessage.hpp"
  #include "CbcGeneralDepth.hpp"
  #include "CbcBranchActual.hpp"
  #include "CbcHeuristicDive.hpp"
  #include "CoinSort.hpp"
  #include "CoinError.hpp"
  
  #ifdef COIN_HAS_CLP
  #include "OsiClpSolverInterface.hpp"
  #include "CoinWarmStartBasis.hpp"
  #include "ClpNode.hpp"
  #include "CbcBranchDynamic.hpp"
  // Default Constructor
  CbcGeneralDepth::CbcGeneralDepth()
    : CbcGeneral()
    , maximumDepth_(0)
    , maximumNodes_(0)
    , whichSolution_(-1)
    , numberNodes_(0)
    , nodeInfo_(NULL)
  {
  }
  
  // Useful constructor (which are integer indices)
  CbcGeneralDepth::CbcGeneralDepth(CbcModel *model, int maximumDepth)
    : CbcGeneral(model)
    , maximumDepth_(maximumDepth)
    , maximumNodes_(0)
    , whichSolution_(-1)
    , numberNodes_(0)
    , nodeInfo_(NULL)
  {
    assert(maximumDepth_ < 1000000);
    if (maximumDepth_ > 0)
      maximumNodes_ = (1 << maximumDepth_) + 1 + maximumDepth_;
    else if (maximumDepth_ < 0)
      maximumNodes_ = 1 + 1 - maximumDepth_;
    else
      maximumNodes_ = 0;
  #define MAX_NODES 100
    maximumNodes_ = CoinMin(maximumNodes_, 1 + maximumDepth_ + MAX_NODES);
    if (maximumNodes_) {
      nodeInfo_ = new ClpNodeStuff();
      nodeInfo_->maximumNodes_ = maximumNodes_;
      ClpNodeStuff *info = nodeInfo_;
      // for reduced costs and duals
      info->solverOptions_ |= 7;
      if (maximumDepth_ > 0) {
        info->nDepth_ = maximumDepth_;
      } else {
        info->nDepth_ = -maximumDepth_;
        info->solverOptions_ |= 32;
      }
      ClpNode **nodeInfo = new ClpNode *[maximumNodes_];
      for (int i = 0; i < maximumNodes_; i++)
        nodeInfo[i] = NULL;
      info->nodeInfo_ = nodeInfo;
    } else {
      nodeInfo_ = NULL;
    }
  }
  
  // Copy constructor
  CbcGeneralDepth::CbcGeneralDepth(const CbcGeneralDepth &rhs)
    : CbcGeneral(rhs)
  {
    maximumDepth_ = rhs.maximumDepth_;
    maximumNodes_ = rhs.maximumNodes_;
    whichSolution_ = -1;
    numberNodes_ = 0;
    if (maximumNodes_) {
      assert(rhs.nodeInfo_);
      nodeInfo_ = new ClpNodeStuff(*rhs.nodeInfo_);
      nodeInfo_->maximumNodes_ = maximumNodes_;
      ClpNodeStuff *info = nodeInfo_;
      if (maximumDepth_ > 0) {
        info->nDepth_ = maximumDepth_;
      } else {
        info->nDepth_ = -maximumDepth_;
        info->solverOptions_ |= 32;
      }
      if (!info->nodeInfo_) {
        ClpNode **nodeInfo = new ClpNode *[maximumNodes_];
        for (int i = 0; i < maximumNodes_; i++)
          nodeInfo[i] = NULL;
        info->nodeInfo_ = nodeInfo;
      }
    } else {
      nodeInfo_ = NULL;
    }
  }
  
  // Clone
  CbcObject *
  CbcGeneralDepth::clone() const
  {
    return new CbcGeneralDepth(*this);
  }
  
  // Assignment operator
  CbcGeneralDepth &
  CbcGeneralDepth::operator=(const CbcGeneralDepth &rhs)
  {
    if (this != &rhs) {
      CbcGeneral::operator=(rhs);
      delete nodeInfo_;
      maximumDepth_ = rhs.maximumDepth_;
      maximumNodes_ = rhs.maximumNodes_;
      whichSolution_ = -1;
      numberNodes_ = 0;
      if (maximumDepth_) {
        assert(rhs.nodeInfo_);
        nodeInfo_ = new ClpNodeStuff(*rhs.nodeInfo_);
        nodeInfo_->maximumNodes_ = maximumNodes_;
      } else {
        nodeInfo_ = NULL;
      }
    }
    return *this;
  }
  
  // Destructor
  CbcGeneralDepth::~CbcGeneralDepth()
  {
    delete nodeInfo_;
  }
  // Infeasibility - large is 0.5
  double
  CbcGeneralDepth::infeasibility(const OsiBranchingInformation * /*info*/,
    int & /*preferredWay*/) const
  {
    whichSolution_ = -1;
    // should use genuine OsiBranchingInformation usefulInfo = model_->usefulInformation();
    // for now assume only called when correct
    //if (usefulInfo.depth_>=4&&!model_->parentModel()
    //     &&(usefulInfo.depth_%2)==0) {
    if (true) {
      OsiSolverInterface *solver = model_->solver();
      OsiClpSolverInterface *clpSolver
        = dynamic_cast< OsiClpSolverInterface * >(solver);
      if (clpSolver) {
        if ((model_->moreSpecialOptions() & 33554432) == 0) {
          ClpNodeStuff *info = nodeInfo_;
          info->integerTolerance_ = model_->getIntegerTolerance();
          info->integerIncrement_ = model_->getCutoffIncrement();
          info->numberBeforeTrust_ = model_->numberBeforeTrust();
          info->stateOfSearch_ = model_->stateOfSearch();
          // Compute "small" change in branch
          int nBranches = model_->getIntParam(CbcModel::CbcNumberBranches);
          if (nBranches) {
            double average = model_->getDblParam(CbcModel::CbcSumChange) / static_cast< double >(nBranches);
            info->smallChange_ = CoinMax(average * 1.0e-5, model_->getDblParam(CbcModel::CbcSmallestChange));
            info->smallChange_ = CoinMax(info->smallChange_, 1.0e-8);
          } else {
            info->smallChange_ = 1.0e-8;
          }
          int numberIntegers = model_->numberIntegers();
          double *down = new double[numberIntegers];
          double *up = new double[numberIntegers];
          int *priority = new int[numberIntegers];
          int *numberDown = new int[numberIntegers];
          int *numberUp = new int[numberIntegers];
          int *numberDownInfeasible = new int[numberIntegers];
          int *numberUpInfeasible = new int[numberIntegers];
          model_->fillPseudoCosts(down, up, priority, numberDown, numberUp,
            numberDownInfeasible, numberUpInfeasible);
          info->fillPseudoCosts(down, up, priority, numberDown, numberUp,
            numberDownInfeasible,
            numberUpInfeasible, numberIntegers);
          info->presolveType_ = 1;
          delete[] down;
          delete[] up;
          delete[] numberDown;
          delete[] numberUp;
          delete[] numberDownInfeasible;
          delete[] numberUpInfeasible;
          bool takeHint;
          OsiHintStrength strength;
          solver->getHintParam(OsiDoReducePrint, takeHint, strength);
          ClpSimplex *simplex = clpSolver->getModelPtr();
          int saveLevel = simplex->logLevel();
          if (strength != OsiHintIgnore && takeHint && saveLevel == 1)
            simplex->setLogLevel(0);
          clpSolver->setBasis();
          whichSolution_ = simplex->fathomMany(info);
          //printf("FAT %d nodes, %d iterations\n",
          //info->numberNodesExplored_,info->numberIterations_);
          //printf("CbcBranch %d rows, %d columns\n",clpSolver->getNumRows(),
          //     clpSolver->getNumCols());
          model_->incrementExtra(info->numberNodesExplored_,
            info->numberIterations_);
          // update pseudo costs
          double smallest = 1.0e50;
          double largest = -1.0;
          OsiObject **objects = model_->objects();
  #ifndef NDEBUG
          const int *integerVariable = model_->integerVariable();
  #endif
          for (int i = 0; i < numberIntegers; i++) {
  #ifndef NDEBUG
            CbcSimpleIntegerDynamicPseudoCost *obj = dynamic_cast< CbcSimpleIntegerDynamicPseudoCost * >(objects[i]);
            assert(obj && obj->columnNumber() == integerVariable[i]);
  #else
            CbcSimpleIntegerDynamicPseudoCost *obj = static_cast< CbcSimpleIntegerDynamicPseudoCost * >(objects[i]);
  #endif
            if (info->numberUp_[i] > 0) {
              if (info->downPseudo_[i] > largest)
                largest = info->downPseudo_[i];
              if (info->downPseudo_[i] < smallest)
                smallest = info->downPseudo_[i];
              if (info->upPseudo_[i] > largest)
                largest = info->upPseudo_[i];
              if (info->upPseudo_[i] < smallest)
                smallest = info->upPseudo_[i];
              obj->updateAfterMini(info->numberDown_[i],
                info->numberDownInfeasible_[i],
                info->downPseudo_[i],
                info->numberUp_[i],
                info->numberUpInfeasible_[i],
                info->upPseudo_[i]);
            }
          }
          //printf("range of costs %g to %g\n",smallest,largest);
          simplex->setLogLevel(saveLevel);
          numberNodes_ = info->nNodes_;
        } else {
          // Try diving
          // See if any diving heuristics set to do dive+save
          CbcHeuristicDive *dive = NULL;
          for (int i = 0; i < model_->numberHeuristics(); i++) {
            CbcHeuristicDive *possible = dynamic_cast< CbcHeuristicDive * >(model_->heuristic(i));
            if (possible && possible->maxSimplexIterations() == COIN_INT_MAX) {
              // if more than one then rotate later?
              //if (possible->canHeuristicRun()) {
              dive = possible;
              break;
            }
          }
          assert(dive); // otherwise moreSpecial should have been turned off
          CbcSubProblem **nodes = NULL;
          int branchState = dive->fathom(model_, numberNodes_, nodes);
          if (branchState) {
            printf("new solution\n");
            whichSolution_ = numberNodes_ - 1;
          } else {
            whichSolution_ = -1;
          }
  #if 0
  	    if (0) {
  	      for (int iNode=0;iNode<numberNodes;iNode++) {
  		//tree_->push(nodes[iNode]) ;
  	      }
  	      assert (node->nodeInfo());
  	      if (node->nodeInfo()->numberBranchesLeft()) {
  		tree_->push(node) ;
  	      } else {
  		node->setActive(false);
  	      }
  	    }
  #endif
          //delete [] nodes;
          model_->setTemporaryPointer(reinterpret_cast< void * >(nodes));
          // end try diving
        }
        int numberDo = numberNodes_;
        if (numberDo > 0 || whichSolution_ >= 0) {
          return 0.5;
        } else {
          // no solution
          return COIN_DBL_MAX; // say infeasible
        }
      } else {
        return -1.0;
      }
    } else {
      return -1.0;
    }
  }
  
  // This looks at solution and sets bounds to contain solution
  void CbcGeneralDepth::feasibleRegion()
  {
    // Other stuff should have done this
  }
  // Redoes data when sequence numbers change
  void CbcGeneralDepth::redoSequenceEtc(CbcModel * /*model*/,
    int /*numberColumns*/,
    const int * /*originalColumns*/)
  {
  }
  
  //#define CHECK_PATH
  #ifdef CHECK_PATH
  extern const double *debuggerSolution_Z;
  extern int numberColumns_Z;
  extern int gotGoodNode_Z;
  #endif
  CbcBranchingObject *
  CbcGeneralDepth::createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int /*way*/)
  {
    int numberDo = numberNodes_;
    if (whichSolution_ >= 0 && (model_->moreSpecialOptions() & 33554432) == 0)
      numberDo--;
    assert(numberDo > 0);
    // create object
    CbcGeneralBranchingObject *branch = new CbcGeneralBranchingObject(model_);
    // skip solution
    branch->numberSubProblems_ = numberDo;
    // If parentBranch_ back in then will have to be 2*
    branch->numberSubLeft_ = numberDo;
    branch->setNumberBranches(numberDo);
    CbcSubProblem *sub = new CbcSubProblem[numberDo];
    int iProb = 0;
    branch->subProblems_ = sub;
    branch->numberRows_ = model_->solver()->getNumRows();
    int iNode;
    //OsiSolverInterface * solver = model_->solver();
    OsiClpSolverInterface *clpSolver
      = dynamic_cast< OsiClpSolverInterface * >(solver);
    assert(clpSolver);
    ClpSimplex *simplex = clpSolver->getModelPtr();
    int numberColumns = simplex->numberColumns();
    if ((model_->moreSpecialOptions() & 33554432) == 0) {
      double *lowerBefore = CoinCopyOfArray(simplex->getColLower(),
        numberColumns);
      double *upperBefore = CoinCopyOfArray(simplex->getColUpper(),
        numberColumns);
      ClpNodeStuff *info = nodeInfo_;
      double *weight = new double[numberNodes_];
      int *whichNode = new int[numberNodes_];
      // Sort
      for (iNode = 0; iNode < numberNodes_; iNode++) {
        if (iNode != whichSolution_) {
          double objectiveValue = info->nodeInfo_[iNode]->objectiveValue();
          double sumInfeasibilities = info->nodeInfo_[iNode]->sumInfeasibilities();
          int numberInfeasibilities = info->nodeInfo_[iNode]->numberInfeasibilities();
          double thisWeight = 0.0;
  #if 1
          // just closest
          thisWeight = 1.0e9 * numberInfeasibilities;
          thisWeight += sumInfeasibilities;
          thisWeight += 1.0e-7 * objectiveValue;
          // Try estimate
          thisWeight = info->nodeInfo_[iNode]->estimatedSolution();
  #else
          thisWeight = 1.0e-3 * numberInfeasibilities;
          thisWeight += 1.0e-5 * sumInfeasibilities;
          thisWeight += objectiveValue;
  #endif
          whichNode[iProb] = iNode;
          weight[iProb++] = thisWeight;
        }
      }
      assert(iProb == numberDo);
      CoinSort_2(weight, weight + numberDo, whichNode);
      for (iProb = 0; iProb < numberDo; iProb++) {
        iNode = whichNode[iProb];
        ClpNode *node = info->nodeInfo_[iNode];
        // move bounds
        node->applyNode(simplex, 3);
        // create subproblem
        sub[iProb] = CbcSubProblem(clpSolver, lowerBefore, upperBefore,
          node->statusArray(), node->depth());
        sub[iProb].objectiveValue_ = node->objectiveValue();
        sub[iProb].sumInfeasibilities_ = node->sumInfeasibilities();
        sub[iProb].numberInfeasibilities_ = node->numberInfeasibilities();
  #ifdef CHECK_PATH
        if (simplex->numberColumns() == numberColumns_Z) {
          bool onOptimal = true;
          const double *columnLower = simplex->columnLower();
          const double *columnUpper = simplex->columnUpper();
          for (int i = 0; i < numberColumns_Z; i++) {
            if (iNode == gotGoodNode_Z)
              printf("good %d %d %g %g\n", iNode, i, columnLower[i], columnUpper[i]);
            if (columnUpper[i] < debuggerSolution_Z[i] || columnLower[i] > debuggerSolution_Z[i] && simplex->isInteger(i)) {
              onOptimal = false;
              break;
            }
          }
          if (onOptimal) {
            printf("adding to node %x as %d - objs\n", this, iProb);
            for (int j = 0; j <= iProb; j++)
              printf("%d %g\n", j, sub[j].objectiveValue_);
          }
        }
  #endif
      }
      delete[] weight;
      delete[] whichNode;
      const double *lower = solver->getColLower();
      const double *upper = solver->getColUpper();
      // restore bounds
      for (int j = 0; j < numberColumns; j++) {
        if (lowerBefore[j] != lower[j])
          solver->setColLower(j, lowerBefore[j]);
        if (upperBefore[j] != upper[j])
          solver->setColUpper(j, upperBefore[j]);
      }
      delete[] upperBefore;
      delete[] lowerBefore;
    } else {
      // from diving
      CbcSubProblem **nodes = reinterpret_cast< CbcSubProblem ** >(model_->temporaryPointer());
      assert(nodes);
      int adjustDepth = info->depth_;
      assert(numberDo);
      numberNodes_ = 0;
      for (iProb = 0; iProb < numberDo; iProb++) {
        if ((nodes[iProb]->problemStatus_ & 2) == 0) {
          // create subproblem (and swap way and/or make inactive)
          sub[numberNodes_].takeOver(*nodes[iProb], true);
          // but adjust depth
          sub[numberNodes_].depth_ += adjustDepth;
          numberNodes_++;
        }
        delete nodes[iProb];
      }
      branch->numberSubProblems_ = numberNodes_;
      branch->numberSubLeft_ = numberNodes_;
      branch->setNumberBranches(numberNodes_);
      if (!numberNodes_) {
        // infeasible
        delete branch;
        branch = NULL;
      }
      delete[] nodes;
    }
    return branch;
  }
  
  // Default Constructor
  CbcGeneralBranchingObject::CbcGeneralBranchingObject()
    : CbcBranchingObject()
    , subProblems_(NULL)
    , node_(NULL)
    , numberSubProblems_(0)
    , numberSubLeft_(0)
    , whichNode_(-1)
    , numberRows_(0)
  {
    //  printf("CbcGeneral %x default constructor\n",this);
  }
  
  // Useful constructor
  CbcGeneralBranchingObject::CbcGeneralBranchingObject(CbcModel *model)
    : CbcBranchingObject(model, -1, -1, 0.5)
    , subProblems_(NULL)
    , node_(NULL)
    , numberSubProblems_(0)
    , numberSubLeft_(0)
    , whichNode_(-1)
    , numberRows_(0)
  {
    //printf("CbcGeneral %x useful constructor\n",this);
  }
  
  // Copy constructor
  CbcGeneralBranchingObject::CbcGeneralBranchingObject(const CbcGeneralBranchingObject &rhs)
    : CbcBranchingObject(rhs)
    , subProblems_(NULL)
    , node_(rhs.node_)
    , numberSubProblems_(rhs.numberSubProblems_)
    , numberSubLeft_(rhs.numberSubLeft_)
    , whichNode_(rhs.whichNode_)
    , numberRows_(rhs.numberRows_)
  {
    abort();
    if (numberSubProblems_) {
      subProblems_ = new CbcSubProblem[numberSubProblems_];
      for (int i = 0; i < numberSubProblems_; i++)
        subProblems_[i] = rhs.subProblems_[i];
    }
  }
  
  // Assignment operator
  CbcGeneralBranchingObject &
  CbcGeneralBranchingObject::operator=(const CbcGeneralBranchingObject &rhs)
  {
    if (this != &rhs) {
      abort();
      CbcBranchingObject::operator=(rhs);
      delete[] subProblems_;
      numberSubProblems_ = rhs.numberSubProblems_;
      numberSubLeft_ = rhs.numberSubLeft_;
      whichNode_ = rhs.whichNode_;
      numberRows_ = rhs.numberRows_;
      if (numberSubProblems_) {
        subProblems_ = new CbcSubProblem[numberSubProblems_];
        for (int i = 0; i < numberSubProblems_; i++)
          subProblems_[i] = rhs.subProblems_[i];
      } else {
        subProblems_ = NULL;
      }
      node_ = rhs.node_;
    }
    return *this;
  }
  CbcBranchingObject *
  CbcGeneralBranchingObject::clone() const
  {
    return (new CbcGeneralBranchingObject(*this));
  }
  
  // Destructor
  CbcGeneralBranchingObject::~CbcGeneralBranchingObject()
  {
    //printf("CbcGeneral %x destructor\n",this);
    delete[] subProblems_;
  }
  bool doingDoneBranch = false;
  double
  CbcGeneralBranchingObject::branch()
  {
    double cutoff = model_->getCutoff();
    //printf("GenB %x whichNode %d numberLeft %d which %d\n",
    // this,whichNode_,numberBranchesLeft(),branchIndex());
    if (whichNode_ < 0) {
      assert(node_);
      bool applied = false;
      while (numberBranchesLeft()) {
        int which = branchIndex();
        decrementNumberBranchesLeft();
        CbcSubProblem *thisProb = subProblems_ + which;
        if (thisProb->objectiveValue_ < cutoff) {
          //printf("branch %x (sub %x) which now %d\n",this,
          //     subProblems_,which);
          OsiSolverInterface *solver = model_->solver();
          thisProb->apply(solver);
          OsiClpSolverInterface *clpSolver
            = dynamic_cast< OsiClpSolverInterface * >(solver);
          assert(clpSolver);
          // Move status to basis
          clpSolver->setWarmStart(NULL);
          //ClpSimplex * simplex = clpSolver->getModelPtr();
          node_->setObjectiveValue(thisProb->objectiveValue_);
          node_->setSumInfeasibilities(thisProb->sumInfeasibilities_);
          node_->setNumberUnsatisfied(thisProb->numberInfeasibilities_);
          applied = true;
          doingDoneBranch = true;
          break;
        } else if (numberBranchesLeft()) {
          node_->nodeInfo()->branchedOn();
        }
      }
      if (!applied) {
        // no good one
        node_->setObjectiveValue(cutoff + 1.0e20);
        node_->setSumInfeasibilities(1.0);
        node_->setNumberUnsatisfied(1);
        assert(whichNode_ < 0);
      }
    } else {
      decrementNumberBranchesLeft();
      CbcSubProblem *thisProb = subProblems_ + whichNode_;
      assert(thisProb->objectiveValue_ < cutoff);
      OsiSolverInterface *solver = model_->solver();
      thisProb->apply(solver);
      //OsiClpSolverInterface * clpSolver
      //= dynamic_cast<OsiClpSolverInterface *> (solver);
      //assert (clpSolver);
      // Move status to basis
      //clpSolver->setWarmStart(NULL);
    }
    return 0.0;
  }
  /* Double checks in case node can change its mind!
     Can change objective etc */
  void CbcGeneralBranchingObject::checkIsCutoff(double cutoff)
  {
    assert(node_);
    int first = branchIndex();
    int last = first + numberBranchesLeft();
    for (int which = first; which < last; which++) {
      CbcSubProblem *thisProb = subProblems_ + which;
      if (thisProb->objectiveValue_ < cutoff) {
        node_->setObjectiveValue(thisProb->objectiveValue_);
        node_->setSumInfeasibilities(thisProb->sumInfeasibilities_);
        node_->setNumberUnsatisfied(thisProb->numberInfeasibilities_);
        break;
      }
    }
  }
  // Print what would happen
  void CbcGeneralBranchingObject::print()
  {
    //printf("CbcGeneralObject has %d subproblems\n",numberSubProblems_);
  }
  // Fill in current objective etc
  void CbcGeneralBranchingObject::state(double &objectiveValue,
    double &sumInfeasibilities,
    int &numberUnsatisfied, int which) const
  {
    assert(which >= 0 && which < numberSubProblems_);
    const CbcSubProblem *thisProb = subProblems_ + which;
    objectiveValue = thisProb->objectiveValue_;
    sumInfeasibilities = thisProb->sumInfeasibilities_;
    numberUnsatisfied = thisProb->numberInfeasibilities_;
  }
  /** Compare the original object of \c this with the original object of \c
      brObj. Assumes that there is an ordering of the original objects.
      This method should be invoked only if \c this and brObj are of the same
      type.
      Return negative/0/positive depending on whether \c this is
      smaller/same/larger than the argument.
  */
  int CbcGeneralBranchingObject::compareOriginalObject(const CbcBranchingObject * /*brObj*/) const
  {
    throw("must implement");
  }
  
  /** Compare the \c this with \c brObj. \c this and \c brObj must be os the
      same type and must have the same original object, but they may have
      different feasible regions.
      Return the appropriate CbcRangeCompare value (first argument being the
      sub/superset if that's the case). In case of overlap (and if \c
      replaceIfOverlap is true) replace the current branching object with one
      whose feasible region is the overlap.
  */
  CbcRangeCompare
  CbcGeneralBranchingObject::compareBranchingObject(const CbcBranchingObject * /*brObj*/, const bool /*replaceIfOverlap*/)
  {
    throw("must implement");
  }
  
  // Default Constructor
  CbcOneGeneralBranchingObject::CbcOneGeneralBranchingObject()
    : CbcBranchingObject()
    , object_(NULL)
    , whichOne_(-1)
  {
    //printf("CbcOneGeneral %x default constructor\n",this);
  }
  
  // Useful constructor
  CbcOneGeneralBranchingObject::CbcOneGeneralBranchingObject(CbcModel *model,
    CbcGeneralBranchingObject *object,
    int whichOne)
    : CbcBranchingObject(model, -1, -1, 0.5)
    , object_(object)
    , whichOne_(whichOne)
  {
    //printf("CbcOneGeneral %x useful constructor object %x %d left\n",this,
    //	 object_,object_->numberSubLeft_);
    numberBranches_ = 1;
  }
  
  // Copy constructor
  CbcOneGeneralBranchingObject::CbcOneGeneralBranchingObject(const CbcOneGeneralBranchingObject &rhs)
    : CbcBranchingObject(rhs)
    , object_(rhs.object_)
    , whichOne_(rhs.whichOne_)
  {
  }
  
  // Assignment operator
  CbcOneGeneralBranchingObject &
  CbcOneGeneralBranchingObject::operator=(const CbcOneGeneralBranchingObject &rhs)
  {
    if (this != &rhs) {
      CbcBranchingObject::operator=(rhs);
      object_ = rhs.object_;
      whichOne_ = rhs.whichOne_;
    }
    return *this;
  }
  CbcBranchingObject *
  CbcOneGeneralBranchingObject::clone() const
  {
    return (new CbcOneGeneralBranchingObject(*this));
  }
  
  // Destructor
  CbcOneGeneralBranchingObject::~CbcOneGeneralBranchingObject()
  {
    //printf("CbcOneGeneral %x destructor object %x %d left\n",this,
    // object_,object_->numberSubLeft_);
    assert(object_->numberSubLeft_ > 0 && object_->numberSubLeft_ < 1000000);
    if (!object_->decrementNumberLeft()) {
      // printf("CbcGeneral %x yy destructor\n",object_);
      delete object_;
    }
  }
  double
  CbcOneGeneralBranchingObject::branch()
  {
    assert(numberBranchesLeft());
    decrementNumberBranchesLeft();
    assert(!numberBranchesLeft());
    object_->setWhichNode(whichOne_);
    object_->branch();
    return 0.0;
  }
  /* Double checks in case node can change its mind!
     Can change objective etc */
  void CbcOneGeneralBranchingObject::checkIsCutoff(double /*cutoff*/)
  {
    assert(numberBranchesLeft());
  }
  // Print what would happen
  void CbcOneGeneralBranchingObject::print()
  {
    //printf("CbcOneGeneralObject has 1 subproblem\n");
  }
  /** Compare the original object of \c this with the original object of \c
      brObj. Assumes that there is an ordering of the original objects.
      This method should be invoked only if \c this and brObj are of the same
      type.
      Return negative/0/positive depending on whether \c this is
      smaller/same/larger than the argument.
  */
  int CbcOneGeneralBranchingObject::compareOriginalObject(const CbcBranchingObject * /*brObj*/) const
  {
    throw("must implement");
  }
  
  /** Compare the \c this with \c brObj. \c this and \c brObj must be os the
      same type and must have the same original object, but they may have
      different feasible regions.
      Return the appropriate CbcRangeCompare value (first argument being the
      sub/superset if that's the case). In case of overlap (and if \c
      replaceIfOverlap is true) replace the current branching object with one
      whose feasible region is the overlap.
  */
  CbcRangeCompare
  CbcOneGeneralBranchingObject::compareBranchingObject(const CbcBranchingObject * /*brObj*/, const bool /*replaceIfOverlap*/)
  {
    throw("must implement");
  }
  #endif
  
  /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
  */
  