source: trunk/Cbc/src/CbcGeneralDepth.cpp

Last change on this file was 2467, checked in by unxusr, 11 months ago

spaces after angles

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