source: trunk/Cbc/src/CbcSimpleInteger.cpp

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

spaces after angles

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1// $Id: CbcSimpleInteger.cpp 2467 2019-01-03 21:26:29Z forrest $
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/9/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 "CbcSimpleInteger.hpp"
24#include "CbcSimpleIntegerDynamicPseudoCost.hpp"
25#include "CbcBranchActual.hpp"
26#include "CoinSort.hpp"
27#include "CoinError.hpp"
28
29//##############################################################################
30
31/** Default Constructor
32
33  Equivalent to an unspecified binary variable.
34*/
35CbcSimpleInteger::CbcSimpleInteger()
36  : CbcObject()
37  , originalLower_(0.0)
38  , originalUpper_(1.0)
39  , breakEven_(0.5)
40  , columnNumber_(-1)
41  , preferredWay_(0)
42{
43}
44
45/** Useful constructor
46
47  Loads actual upper & lower bounds for the specified variable.
48*/
49CbcSimpleInteger::CbcSimpleInteger(CbcModel *model, int iColumn, double breakEven)
50  : CbcObject(model)
51{
52  columnNumber_ = iColumn;
53  originalLower_ = model->solver()->getColLower()[columnNumber_];
54  originalUpper_ = model->solver()->getColUpper()[columnNumber_];
55  breakEven_ = breakEven;
56  assert(breakEven_ > 0.0 && breakEven_ < 1.0);
57  preferredWay_ = 0;
58}
59
60// Copy constructor
61CbcSimpleInteger::CbcSimpleInteger(const CbcSimpleInteger &rhs)
62  : CbcObject(rhs)
63
64{
65  columnNumber_ = rhs.columnNumber_;
66  originalLower_ = rhs.originalLower_;
67  originalUpper_ = rhs.originalUpper_;
68  breakEven_ = rhs.breakEven_;
69  preferredWay_ = rhs.preferredWay_;
70}
71
72// Clone
73CbcObject *
74CbcSimpleInteger::clone() const
75{
76  return new CbcSimpleInteger(*this);
77}
78
79// Assignment operator
80CbcSimpleInteger &
81CbcSimpleInteger::operator=(const CbcSimpleInteger &rhs)
82{
83  if (this != &rhs) {
84    CbcObject::operator=(rhs);
85    columnNumber_ = rhs.columnNumber_;
86    originalLower_ = rhs.originalLower_;
87    originalUpper_ = rhs.originalUpper_;
88    breakEven_ = rhs.breakEven_;
89    preferredWay_ = rhs.preferredWay_;
90  }
91  return *this;
92}
93
94// Destructor
95CbcSimpleInteger::~CbcSimpleInteger()
96{
97}
98// Construct an OsiSimpleInteger object
99OsiSimpleInteger *
100CbcSimpleInteger::osiObject() const
101{
102  OsiSimpleInteger *obj = new OsiSimpleInteger(columnNumber_,
103    originalLower_, originalUpper_);
104  obj->setPriority(priority());
105  return obj;
106}
107double
108CbcSimpleInteger::infeasibility(const OsiBranchingInformation *info,
109  int &preferredWay) const
110{
111  double value = info->solution_[columnNumber_];
112  value = CoinMax(value, info->lower_[columnNumber_]);
113  value = CoinMin(value, info->upper_[columnNumber_]);
114  double nearest = floor(value + (1.0 - breakEven_));
115  assert(breakEven_ > 0.0 && breakEven_ < 1.0);
116  if (nearest > value)
117    preferredWay = 1;
118  else
119    preferredWay = -1;
120  if (preferredWay_)
121    preferredWay = preferredWay_;
122  double weight = fabs(value - nearest);
123  // normalize so weight is 0.5 at break even
124  if (nearest < value)
125    weight = (0.5 / breakEven_) * weight;
126  else
127    weight = (0.5 / (1.0 - breakEven_)) * weight;
128  if (fabs(value - nearest) <= info->integerTolerance_)
129    return 0.0;
130  else
131    return weight;
132}
133double
134CbcSimpleInteger::feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const
135{
136  double value = info->solution_[columnNumber_];
137#ifdef COIN_DEVELOP
138  if (fabs(value - floor(value + 0.5)) > 1.0e-5)
139    printf("value for %d away from integer %g\n", columnNumber_, value);
140#endif
141  double newValue = CoinMax(value, info->lower_[columnNumber_]);
142  newValue = CoinMin(newValue, info->upper_[columnNumber_]);
143  newValue = floor(newValue + 0.5);
144  solver->setColLower(columnNumber_, newValue);
145  solver->setColUpper(columnNumber_, newValue);
146#ifdef SWITCH_VARIABLES
147  const CbcSwitchingBinary *sObject = dynamic_cast< const CbcSwitchingBinary * >(this);
148  if (sObject)
149    sObject->setAssociatedBounds(solver, 1);
150#endif
151  return fabs(value - newValue);
152}
153
154/* Create an OsiSolverBranch object
155
156This returns NULL if branch not represented by bound changes
157*/
158OsiSolverBranch *
159CbcSimpleInteger::solverBranch(OsiSolverInterface * /*solver*/,
160  const OsiBranchingInformation *info) const
161{
162  double value = info->solution_[columnNumber_];
163  value = CoinMax(value, info->lower_[columnNumber_]);
164  value = CoinMin(value, info->upper_[columnNumber_]);
165  assert(info->upper_[columnNumber_] > info->lower_[columnNumber_]);
166#ifndef NDEBUG
167  double nearest = floor(value + 0.5);
168  assert(fabs(value - nearest) > info->integerTolerance_);
169#endif
170  OsiSolverBranch *branch = new OsiSolverBranch();
171  branch->addBranch(columnNumber_, value);
172  return branch;
173}
174// Creates a branching object
175CbcBranchingObject *
176CbcSimpleInteger::createCbcBranch(OsiSolverInterface * /*solver*/,
177  const OsiBranchingInformation *info, int way)
178{
179  CbcIntegerBranchingObject *branch = new CbcIntegerBranchingObject(model_, 0, -1, 0.5);
180  fillCreateBranch(branch, info, way);
181  return branch;
182}
183// Fills in a created branching object
184void CbcSimpleInteger::fillCreateBranch(CbcIntegerBranchingObject *branch, const OsiBranchingInformation *info, int way)
185{
186  branch->setOriginalObject(this);
187  double value = info->solution_[columnNumber_];
188  value = CoinMax(value, info->lower_[columnNumber_]);
189  value = CoinMin(value, info->upper_[columnNumber_]);
190  assert(info->upper_[columnNumber_] > info->lower_[columnNumber_]);
191  if (!info->hotstartSolution_ && priority_ != -999) {
192#if 0 // out because of very strong branching ndef NDEBUG
193        double nearest = floor(value + 0.5);
194        assert (fabs(value - nearest) > info->integerTolerance_);
195#endif
196  } else if (info->hotstartSolution_) {
197    double targetValue = info->hotstartSolution_[columnNumber_];
198    if (way > 0)
199      value = targetValue - 0.1;
200    else
201      value = targetValue + 0.1;
202  } else {
203    if (value <= info->lower_[columnNumber_])
204      value += 0.1;
205    else if (value >= info->upper_[columnNumber_])
206      value -= 0.1;
207  }
208  assert(value >= info->lower_[columnNumber_] && value <= info->upper_[columnNumber_]);
209  branch->fillPart(columnNumber_, way, value);
210}
211/* Column number if single column object -1 otherwise,
212   so returns >= 0
213   Used by heuristics
214*/
215int CbcSimpleInteger::columnNumber() const
216{
217  return columnNumber_;
218}
219/* Reset variable bounds to their original values.
220
221    Bounds may be tightened, so it may be good to be able to set this info in object.
222*/
223void CbcSimpleInteger::resetBounds(const OsiSolverInterface *solver)
224{
225  originalLower_ = solver->getColLower()[columnNumber_];
226  originalUpper_ = solver->getColUpper()[columnNumber_];
227}
228
229/*  Change column numbers after preprocessing
230 */
231void CbcSimpleInteger::resetSequenceEtc(int /*numberColumns*/,
232  const int *originalColumns)
233{
234  //assert (numberColumns>0);
235  int iColumn;
236#ifdef JJF_ZERO
237  for (iColumn = 0; iColumn < numberColumns; iColumn++) {
238    if (columnNumber_ == originalColumns[iColumn])
239      break;
240  }
241  assert(iColumn < numberColumns);
242#else
243  iColumn = originalColumns[columnNumber_];
244  assert(iColumn >= 0);
245#endif
246  columnNumber_ = iColumn;
247}
248// This looks at solution and sets bounds to contain solution
249/** More precisely: it first forces the variable within the existing
250    bounds, and then tightens the bounds to fix the variable at the
251    nearest integer value.
252*/
253void CbcSimpleInteger::feasibleRegion()
254{
255  abort();
256}
257
258//##############################################################################
259
260// Default Constructor
261CbcIntegerBranchingObject::CbcIntegerBranchingObject()
262  : CbcBranchingObject()
263{
264  down_[0] = 0.0;
265  down_[1] = 0.0;
266  up_[0] = 0.0;
267  up_[1] = 0.0;
268#ifdef FUNNY_BRANCHING2
269  variables_ = NULL;
270  newBounds_ = NULL;
271  numberExtraChangedBounds_ = 0;
272#endif
273}
274// Useful constructor
275CbcIntegerBranchingObject::CbcIntegerBranchingObject(CbcModel *model,
276  int variable, int way, double value)
277  : CbcBranchingObject(model, variable, way, value)
278{
279  int iColumn = variable;
280  assert(model_->solver()->getNumCols() > 0);
281  down_[0] = model_->solver()->getColLower()[iColumn];
282  down_[1] = floor(value_);
283  up_[0] = ceil(value_);
284  up_[1] = model->getColUpper()[iColumn];
285#ifdef FUNNY_BRANCHING2
286  variables_ = NULL;
287  newBounds_ = NULL;
288  numberExtraChangedBounds_ = 0;
289#endif
290}
291// Does part of constructor
292void CbcIntegerBranchingObject::fillPart(int variable,
293  int way, double value)
294{
295  //originalObject_=NULL;
296  branchIndex_ = 0;
297  value_ = value;
298  numberBranches_ = 2;
299  //model_= model;
300  //originalCbcObject_=NULL;
301  variable_ = variable;
302  way_ = way;
303  int iColumn = variable;
304  down_[0] = model_->solver()->getColLower()[iColumn];
305  down_[1] = floor(value_);
306  up_[0] = ceil(value_);
307  up_[1] = model_->getColUpper()[iColumn];
308  // fix extreme cases
309  if (up_[0] == 1.0)
310    down_[1] = 0.0;
311  if (down_[1] == 0.0)
312    up_[0] = 1.0;
313}
314// Useful constructor for fixing
315CbcIntegerBranchingObject::CbcIntegerBranchingObject(CbcModel *model,
316  int variable, int way,
317  double lowerValue,
318  double upperValue)
319  : CbcBranchingObject(model, variable, way, lowerValue)
320{
321  setNumberBranchesLeft(1);
322  down_[0] = lowerValue;
323  down_[1] = upperValue;
324  up_[0] = lowerValue;
325  up_[1] = upperValue;
326#ifdef FUNNY_BRANCHING2
327  variables_ = NULL;
328  newBounds_ = NULL;
329  numberExtraChangedBounds_ = 0;
330#endif
331}
332
333// Copy constructor
334CbcIntegerBranchingObject::CbcIntegerBranchingObject(const CbcIntegerBranchingObject &rhs)
335  : CbcBranchingObject(rhs)
336{
337  down_[0] = rhs.down_[0];
338  down_[1] = rhs.down_[1];
339  up_[0] = rhs.up_[0];
340  up_[1] = rhs.up_[1];
341#ifdef FUNNY_BRANCHING2
342  numberExtraChangedBounds_ = rhs.numberExtraChangedBounds_;
343  int size = numberExtraChangedBounds_ * (sizeof(double) + sizeof(int));
344  char *temp = new char[size];
345  newBounds_ = (double *)temp;
346  variables_ = (int *)(newBounds_ + numberExtraChangedBounds_);
347
348  int i;
349  for (i = 0; i < numberExtraChangedBounds_; i++) {
350    variables_[i] = rhs.variables_[i];
351    newBounds_[i] = rhs.newBounds_[i];
352  }
353#endif
354}
355
356// Assignment operator
357CbcIntegerBranchingObject &
358CbcIntegerBranchingObject::operator=(const CbcIntegerBranchingObject &rhs)
359{
360  if (this != &rhs) {
361    CbcBranchingObject::operator=(rhs);
362    down_[0] = rhs.down_[0];
363    down_[1] = rhs.down_[1];
364    up_[0] = rhs.up_[0];
365    up_[1] = rhs.up_[1];
366#ifdef FUNNY_BRANCHING2
367    delete[] newBounds_;
368    numberExtraChangedBounds_ = rhs.numberExtraChangedBounds_;
369    int size = numberExtraChangedBounds_ * (sizeof(double) + sizeof(int));
370    char *temp = new char[size];
371    newBounds_ = (double *)temp;
372    variables_ = (int *)(newBounds_ + numberExtraChangedBounds_);
373
374    int i;
375    for (i = 0; i < numberExtraChangedBounds_; i++) {
376      variables_[i] = rhs.variables_[i];
377      newBounds_[i] = rhs.newBounds_[i];
378    }
379#endif
380  }
381  return *this;
382}
383CbcBranchingObject *
384CbcIntegerBranchingObject::clone() const
385{
386  return (new CbcIntegerBranchingObject(*this));
387}
388
389// Destructor
390CbcIntegerBranchingObject::~CbcIntegerBranchingObject()
391{
392  // for debugging threads
393  way_ = -23456789;
394#ifdef FUNNY_BRANCHING2
395  delete[] newBounds_;
396#endif
397}
398
399/*
400  Perform a branch by adjusting the bounds of the specified variable. Note
401  that each arm of the branch advances the object to the next arm by
402  advancing the value of way_.
403
404  Providing new values for the variable's lower and upper bounds for each
405  branching direction gives a little bit of additional flexibility and will
406  be easily extensible to multi-way branching.
407  Returns change in guessed objective on next branch
408*/
409double
410CbcIntegerBranchingObject::branch()
411{
412  // for debugging threads
413  if (way_ < -1 || way_ > 100000) {
414    printf("way %d, left %d, iCol %d, variable %d\n",
415      way_, numberBranchesLeft(),
416      originalCbcObject_->columnNumber(), variable_);
417    assert(way_ != -23456789);
418  }
419  decrementNumberBranchesLeft();
420  if (down_[1] == -COIN_DBL_MAX)
421    return 0.0;
422  int iColumn = originalCbcObject_->columnNumber();
423  assert(variable_ == iColumn);
424  double olb, oub;
425  olb = model_->solver()->getColLower()[iColumn];
426  oub = model_->solver()->getColUpper()[iColumn];
427  //#define CBCSIMPLE_TIGHTEN_BOUNDS
428#ifndef CBCSIMPLE_TIGHTEN_BOUNDS
429#ifdef COIN_DEVELOP
430  if (olb != down_[0] || oub != up_[1]) {
431    if (way_ > 0)
432      printf("branching up on var %d: [%g,%g] => [%g,%g] - other [%g,%g]\n",
433        iColumn, olb, oub, up_[0], up_[1], down_[0], down_[1]);
434    else
435      printf("branching down on var %d: [%g,%g] => [%g,%g] - other [%g,%g]\n",
436        iColumn, olb, oub, down_[0], down_[1], up_[0], up_[1]);
437  }
438#endif
439#endif
440  if (way_ < 0) {
441#ifdef CBC_DEBUG
442    {
443      double olb, oub;
444      olb = model_->solver()->getColLower()[iColumn];
445      oub = model_->solver()->getColUpper()[iColumn];
446      printf("branching down on var %d: [%g,%g] => [%g,%g]\n",
447        iColumn, olb, oub, down_[0], down_[1]);
448    }
449#endif
450#ifndef CBCSIMPLE_TIGHTEN_BOUNDS
451    model_->solver()->setColLower(iColumn, down_[0]);
452#else
453    model_->solver()->setColLower(iColumn, CoinMax(down_[0], olb));
454#endif
455    model_->solver()->setColUpper(iColumn, down_[1]);
456    //#define CBC_PRINT2
457#ifdef CBC_PRINT2
458    printf("%d branching down has bounds %g %g", iColumn, down_[0], down_[1]);
459#endif
460#ifdef FUNNY_BRANCHING2
461    // branch - do extra bounds
462    for (int i = 0; i < numberExtraChangedBounds_; i++) {
463      int variable = variables_[i];
464      if ((variable & 0x40000000) != 0) {
465        // for going down
466        int k = variable & 0x3fffffff;
467        assert(k != iColumn);
468        if ((variable & 0x80000000) == 0) {
469          // lower bound changing
470#ifdef CBC_PRINT2
471          printf(" extra for %d changes lower from %g to %g",
472            k, model_->solver()->getColLower()[k], newBounds_[i]);
473#endif
474          model_->solver()->setColLower(k, newBounds_[i]);
475        } else {
476          // upper bound changing
477#ifdef CBC_PRINT2
478          printf(" extra for %d changes upper from %g to %g",
479            k, model_->solver()->getColUpper()[k], newBounds_[i]);
480#endif
481          model_->solver()->setColUpper(k, newBounds_[i]);
482        }
483      }
484    }
485#endif
486#ifdef CBC_PRINT2
487    printf("\n");
488#endif
489    way_ = 1;
490  } else {
491#ifdef CBC_DEBUG
492    {
493      double olb, oub;
494      olb = model_->solver()->getColLower()[iColumn];
495      oub = model_->solver()->getColUpper()[iColumn];
496      printf("branching up on var %d: [%g,%g] => [%g,%g]\n",
497        iColumn, olb, oub, up_[0], up_[1]);
498    }
499#endif
500    model_->solver()->setColLower(iColumn, up_[0]);
501#ifndef CBCSIMPLE_TIGHTEN_BOUNDS
502    model_->solver()->setColUpper(iColumn, up_[1]);
503#else
504    model_->solver()->setColUpper(iColumn, CoinMin(up_[1], oub));
505#endif
506#ifdef CBC_PRINT2
507    printf("%d branching up has bounds %g %g", iColumn, up_[0], up_[1]);
508#endif
509#ifdef FUNNY_BRANCHING2
510    // branch - do extra bounds
511    for (int i = 0; i < numberExtraChangedBounds_; i++) {
512      int variable = variables_[i];
513      if ((variable & 0x40000000) == 0) {
514        // for going up
515        int k = variable & 0x3fffffff;
516        assert(k != iColumn);
517        if ((variable & 0x80000000) == 0) {
518          // lower bound changing
519#ifdef CBC_PRINT2
520          printf(" extra for %d changes lower from %g to %g",
521            k, model_->solver()->getColLower()[k], newBounds_[i]);
522#endif
523          model_->solver()->setColLower(k, newBounds_[i]);
524        } else {
525          // upper bound changing
526#ifdef CBC_PRINT2
527          printf(" extra for %d changes upper from %g to %g",
528            k, model_->solver()->getColUpper()[k], newBounds_[i]);
529#endif
530          model_->solver()->setColUpper(k, newBounds_[i]);
531        }
532      }
533    }
534#endif
535#ifdef CBC_PRINT2
536    printf("\n");
537#endif
538    way_ = -1; // Swap direction
539  }
540  double nlb = model_->solver()->getColLower()[iColumn];
541  double nub = model_->solver()->getColUpper()[iColumn];
542  if (nlb < olb) {
543#ifdef CBC_PRINT2
544    printf("bad lb change for column %d from %g to %g\n", iColumn, olb, nlb);
545#endif
546    //abort();
547    model_->solver()->setColLower(iColumn, CoinMin(olb, nub));
548    nlb = olb;
549  }
550  if (nub > oub) {
551#ifdef CBC_PRINT2
552    printf("bad ub change for column %d from %g to %g\n", iColumn, oub, nub);
553#endif
554    //abort();
555    model_->solver()->setColUpper(iColumn, CoinMax(oub, nlb));
556  }
557#ifdef CBC_PRINT2
558  if (nlb < olb + 1.0e-8 && nub > oub - 1.0e-8 && false)
559    printf("bad null change for column %d - bounds %g,%g\n", iColumn, olb, oub);
560#endif
561#ifdef SWITCH_VARIABLES
562  if (model_->logLevel() > 2)
563    printf("for column %d - old bounds %g,%g - new %g,%g\n", iColumn, olb, oub,
564      nlb, nub);
565  CbcSwitchingBinary *sObject = dynamic_cast< CbcSwitchingBinary * >(originalCbcObject_);
566  if (sObject)
567    sObject->setAssociatedBounds();
568    //(dynamic_cast<CbcSimpleInteger *>(originalCbcObject_))->setAssociatedBounds();
569#endif
570  return 0.0;
571}
572/* Update bounds in solver as in 'branch' and update given bounds.
573   branchState is -1 for 'down' +1 for 'up' */
574void CbcIntegerBranchingObject::fix(OsiSolverInterface * /*solver*/,
575  double *lower, double *upper,
576  int branchState) const
577{
578  int iColumn = originalCbcObject_->columnNumber();
579  assert(variable_ == iColumn);
580  if (branchState < 0) {
581    model_->solver()->setColLower(iColumn, down_[0]);
582    lower[iColumn] = down_[0];
583    model_->solver()->setColUpper(iColumn, down_[1]);
584    upper[iColumn] = down_[1];
585  } else {
586    model_->solver()->setColLower(iColumn, up_[0]);
587    lower[iColumn] = up_[0];
588    model_->solver()->setColUpper(iColumn, up_[1]);
589    upper[iColumn] = up_[1];
590  }
591}
592// Change (tighten) bounds in object to reflect bounds in solver.
593// Return true if now fixed
594bool CbcIntegerBranchingObject::tighten(OsiSolverInterface *solver)
595{
596  double lower = solver->getColLower()[variable_];
597  double upper = solver->getColUpper()[variable_];
598  assert(upper > lower);
599  down_[0] = CoinMax(down_[0], lower);
600  up_[0] = CoinMax(up_[0], lower);
601  down_[1] = CoinMin(down_[1], upper);
602  up_[1] = CoinMin(up_[1], upper);
603  return (down_[0] == up_[1]);
604}
605#ifdef FUNNY_BRANCHING2
606// Deactivate bounds for branching
607void CbcIntegerBranchingObject::deactivate()
608{
609  down_[1] = -COIN_DBL_MAX;
610}
611int CbcIntegerBranchingObject::applyExtraBounds(int iColumn, double lower, double upper, int way)
612{
613  // branch - do bounds
614
615  int i;
616  int found = 0;
617  if (variable_ == iColumn) {
618    printf("odd applyExtra %d\n", iColumn);
619    if (way < 0) {
620      down_[0] = CoinMax(lower, down_[0]);
621      down_[1] = CoinMin(upper, down_[1]);
622      assert(down_[0] <= down_[1]);
623    } else {
624      up_[0] = CoinMax(lower, up_[0]);
625      up_[1] = CoinMin(upper, up_[1]);
626      assert(up_[0] <= up_[1]);
627    }
628    return 0;
629  }
630  int check = (way < 0) ? 0x40000000 : 0;
631  double newLower = lower;
632  double newUpper = upper;
633  for (i = 0; i < numberExtraChangedBounds_; i++) {
634    int variable = variables_[i];
635    if ((variable & 0x40000000) == check) {
636      int k = variable & 0x3fffffff;
637      if (k == iColumn) {
638        if ((variable & 0x80000000) == 0) {
639          // lower bound changing
640          found |= 1;
641          newBounds_[i] = CoinMax(lower, newBounds_[i]);
642          newLower = newBounds_[i];
643        } else {
644          // upper bound changing
645          found |= 2;
646          newBounds_[i] = CoinMin(upper, newBounds_[i]);
647          newUpper = newBounds_[i];
648        }
649      }
650    }
651  }
652  int nAdd = 0;
653  if ((found & 2) == 0) {
654    // need to add new upper
655    nAdd++;
656  }
657  if ((found & 1) == 0) {
658    // need to add new lower
659    nAdd++;
660  }
661  if (nAdd) {
662    int size = (numberExtraChangedBounds_ + nAdd) * (sizeof(double) + sizeof(int));
663    char *temp = new char[size];
664    double *newBounds = (double *)temp;
665    int *variables = (int *)(newBounds + numberExtraChangedBounds_ + nAdd);
666
667    int i;
668    for (i = 0; i < numberExtraChangedBounds_; i++) {
669      variables[i] = variables_[i];
670      newBounds[i] = newBounds_[i];
671    }
672    delete[] newBounds_;
673    newBounds_ = newBounds;
674    variables_ = variables;
675    if ((found & 2) == 0) {
676      // need to add new upper
677      int variable = iColumn | 0x80000000;
678      variables_[numberExtraChangedBounds_] = variable;
679      newBounds_[numberExtraChangedBounds_++] = newUpper;
680    }
681    if ((found & 1) == 0) {
682      // need to add new lower
683      int variable = iColumn;
684      variables_[numberExtraChangedBounds_] = variable;
685      newBounds_[numberExtraChangedBounds_++] = newLower;
686    }
687  }
688
689  return (newUpper >= newLower) ? 0 : 1;
690}
691#endif
692// Print what would happen
693void CbcIntegerBranchingObject::print()
694{
695  int iColumn = originalCbcObject_->columnNumber();
696  assert(variable_ == iColumn);
697  if (way_ < 0) {
698    {
699      double olb, oub;
700      olb = model_->solver()->getColLower()[iColumn];
701      oub = model_->solver()->getColUpper()[iColumn];
702      printf("CbcInteger would branch down on var %d (int var %d): [%g,%g] => [%g,%g]\n",
703        iColumn, variable_, olb, oub, down_[0], down_[1]);
704    }
705  } else {
706    {
707      double olb, oub;
708      olb = model_->solver()->getColLower()[iColumn];
709      oub = model_->solver()->getColUpper()[iColumn];
710      printf("CbcInteger would branch up on var %d (int var %d): [%g,%g] => [%g,%g]\n",
711        iColumn, variable_, olb, oub, up_[0], up_[1]);
712    }
713  }
714}
715
716/** Compare the \c this with \c brObj. \c this and \c brObj must be os the
717    same type and must have the same original object, but they may have
718    different feasible regions.
719    Return the appropriate CbcRangeCompare value (first argument being the
720    sub/superset if that's the case). In case of overlap (and if \c
721    replaceIfOverlap is true) replace the current branching object with one
722    whose feasible region is the overlap.
723   */
724CbcRangeCompare
725CbcIntegerBranchingObject::compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap)
726{
727  const CbcIntegerBranchingObject *br = dynamic_cast< const CbcIntegerBranchingObject * >(brObj);
728  assert(br);
729  double *thisBd = way_ < 0 ? down_ : up_;
730  const double *otherBd = br->way_ < 0 ? br->down_ : br->up_;
731  return CbcCompareRanges(thisBd, otherBd, replaceIfOverlap);
732}
733
734/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
735*/
Note: See TracBrowser for help on using the repository browser.