source: trunk/Cbc/src/CbcBranchCut.cpp @ 904

Last change on this file since 904 was 904, checked in by ladanyi, 13 years ago

include cstdlib before cmath to get things to compile on AIX with xlC

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.1 KB
Line 
1// Copyright (C) 2004, International Business Machines
2// Corporation and others.  All Rights Reserved.
3#if defined(_MSC_VER)
4// Turn off compiler warning about long names
5#  pragma warning(disable:4786)
6#endif
7#include <cassert>
8#include <cstdlib>
9#include <cmath>
10#include <cfloat>
11//#define CBC_DEBUG
12
13#include "OsiSolverInterface.hpp"
14#include "CbcModel.hpp"
15#include "CbcMessage.hpp"
16#include "CbcBranchCut.hpp"
17#include "CoinSort.hpp"
18#include "CoinError.hpp"
19
20
21/** Default Constructor
22
23*/
24CbcBranchCut::CbcBranchCut ()
25  : CbcObject()
26{
27}
28
29/* Constructor so model can be passed up
30*/ 
31CbcBranchCut::CbcBranchCut (CbcModel * model)
32  : CbcObject(model)
33{
34}
35// Copy constructor
36CbcBranchCut::CbcBranchCut ( const CbcBranchCut & rhs)
37  :CbcObject(rhs)
38
39{
40}
41
42// Clone
43CbcObject *
44CbcBranchCut::clone() const
45{
46  return new CbcBranchCut(*this);
47}
48
49// Assignment operator
50CbcBranchCut & 
51CbcBranchCut::operator=( const CbcBranchCut& rhs)
52{
53  return *this;
54}
55
56// Destructor
57CbcBranchCut::~CbcBranchCut ()
58{
59}
60
61// Infeasibility - large is 0.5
62double 
63CbcBranchCut::infeasibility(int & preferredWay) const
64{
65  throw CoinError("Use of base class","infeasibility","CbcBranchCut");
66  preferredWay=-1;
67  return 0.0;
68}
69
70// This looks at solution and sets bounds to contain solution
71/** More precisely: it first forces the variable within the existing
72    bounds, and then tightens the bounds to fix the variable at the
73    nearest integer value.
74*/
75void 
76CbcBranchCut::feasibleRegion()
77{
78}
79/* Return true if branch created by object should fix variables
80 */
81bool 
82CbcBranchCut::boundBranch() const 
83{return false;}
84
85// Creates a branching object
86CbcBranchingObject * 
87CbcBranchCut::createBranch(int way) 
88{
89  throw CoinError("Use of base class","createBranch","CbcBranchCut");
90  return new CbcCutBranchingObject();
91}
92
93
94/* Given valid solution (i.e. satisfied) and reduced costs etc
95   returns a branching object which would give a new feasible
96   point in direction reduced cost says would be cheaper.
97   If no feasible point returns null
98*/
99CbcBranchingObject * 
100CbcBranchCut::preferredNewFeasible() const
101{
102  throw CoinError("Use of base class","preferredNewFeasible","CbcBranchCut");
103  return new CbcCutBranchingObject();
104}
105 
106/* Given valid solution (i.e. satisfied) and reduced costs etc
107   returns a branching object which would give a new feasible
108   point in direction opposite to one reduced cost says would be cheaper.
109   If no feasible point returns null
110*/
111CbcBranchingObject * 
112CbcBranchCut::notPreferredNewFeasible() const 
113{
114  throw CoinError("Use of base class","notPreferredNewFeasible","CbcBranchCut");
115  return new CbcCutBranchingObject();
116}
117 
118/*
119  Bounds may be tightened, so it may be good to be able to refresh the local
120  copy of the original bounds.
121 */
122void 
123CbcBranchCut::resetBounds()
124{
125}
126
127
128// Default Constructor
129CbcCutBranchingObject::CbcCutBranchingObject()
130  :CbcBranchingObject()
131{
132  down_=OsiRowCut();
133  up_=OsiRowCut();
134  canFix_=false;
135}
136
137// Useful constructor
138CbcCutBranchingObject::CbcCutBranchingObject (CbcModel * model, 
139                                              OsiRowCut & down,
140                                              OsiRowCut &up,
141                                              bool canFix)
142  :CbcBranchingObject(model,0,-1,0.0)
143{
144  down_ = down;
145  up_ = up;
146  canFix_ = canFix;
147}
148
149// Copy constructor
150CbcCutBranchingObject::CbcCutBranchingObject ( const CbcCutBranchingObject & rhs) :CbcBranchingObject(rhs)
151{
152  down_ = rhs.down_;
153  up_ = rhs.up_;
154  canFix_ = rhs.canFix_;
155}
156
157// Assignment operator
158CbcCutBranchingObject & 
159CbcCutBranchingObject::operator=( const CbcCutBranchingObject& rhs)
160{
161  if (this != &rhs) {
162    CbcBranchingObject::operator=(rhs);
163    down_ = rhs.down_;
164    up_ = rhs.up_;
165    canFix_ = rhs.canFix_;
166  }
167  return *this;
168}
169CbcBranchingObject * 
170CbcCutBranchingObject::clone() const
171{ 
172  return (new CbcCutBranchingObject(*this));
173}
174
175
176// Destructor
177CbcCutBranchingObject::~CbcCutBranchingObject ()
178{
179}
180
181/*
182  Perform a branch by adjusting bounds and/or adding a cut. Note
183  that each arm of the branch advances the object to the next arm by
184  advancing the value of way_.
185
186  Returns change in guessed objective on next branch
187*/
188double
189CbcCutBranchingObject::branch()
190{
191  decrementNumberBranchesLeft();
192  OsiRowCut * cut;
193  if (way_<0) {
194    cut = &down_;
195    way_=1;
196  } else {
197    cut = &up_;
198    way_=-1;      // Swap direction
199  }
200  // See if cut just fixes variables
201  double lb = cut->lb();
202  double ub = cut->ub();
203  int n=cut->row().getNumElements();
204  const int * column = cut->row().getIndices();
205  const double * element = cut->row().getElements();
206  OsiSolverInterface * solver = model_->solver();
207  const double * upper = solver->getColUpper();
208  const double * lower = solver->getColLower();
209  double low = 0.0;
210  double high=0.0;
211  for (int i=0;i<n;i++) {
212    int iColumn = column[i];
213    double value = element[i];
214    if (value>0.0) {
215      high += upper[iColumn]*value;
216      low += lower[iColumn]*value;
217    } else {
218      high += lower[iColumn]*value;
219      low += upper[iColumn]*value;
220    }
221  }
222  // assume cut was cunningly constructed so we need not worry too much about tolerances
223  if (low+1.0e-8>=ub&&canFix_) {
224    // fix
225    for (int i=0;i<n;i++) {
226      int iColumn = column[i];
227      double value = element[i];
228      if (value>0.0) {
229        solver->setColUpper(iColumn,lower[iColumn]);
230      } else {
231        solver->setColLower(iColumn,upper[iColumn]);
232      }
233    }
234  } else if (high-1.0e-8<=lb&&canFix_) {
235    // fix
236    for (int i=0;i<n;i++) {
237      int iColumn = column[i];
238      double value = element[i];
239      if (value>0.0) {
240        solver->setColLower(iColumn,upper[iColumn]);
241      } else {
242        solver->setColUpper(iColumn,lower[iColumn]);
243      }
244    }
245  } else {
246    // leave as cut
247    model_->setNextRowCut(*cut);
248  }
249  return 0.0;
250}
251// Print what would happen 
252void
253CbcCutBranchingObject::print()
254{
255  OsiRowCut * cut;
256  if (way_<0) {
257    cut = &down_;
258    printf("CbcCut would branch down");
259  } else {
260    cut = &up_;
261    printf("CbcCut would branch up");
262  }
263  double lb = cut->lb();
264  double ub = cut->ub();
265  int n=cut->row().getNumElements();
266  const int * column = cut->row().getIndices();
267  const double * element = cut->row().getElements();
268  if (n>5) {
269    printf(" - %d elements, lo=%g, up=%g\n",n,lb,ub);
270  } else {
271    printf(" - %g <=",lb);
272    for (int i=0;i<n;i++) {
273      int iColumn = column[i];
274      double value = element[i];
275      printf(" (%d,%g)",iColumn,value);
276    }
277    printf(" <= %g\n",ub);
278  }
279}
280
281// Return true if branch should fix variables
282bool 
283CbcCutBranchingObject::boundBranch() const
284{
285  return false;
286}
287
288/** Default Constructor
289
290  Equivalent to an unspecified binary variable.
291*/
292CbcBranchToFixLots::CbcBranchToFixLots ()
293  : CbcBranchCut(),
294    djTolerance_(COIN_DBL_MAX),
295    fractionFixed_(1.0),
296    mark_(NULL),
297    depth_(-1),
298    numberClean_(0),
299    alwaysCreate_(false)
300{
301}
302
303/* Useful constructor - passed reduced cost tolerance and fraction we would like fixed.
304   Also depth level to do at.
305   Also passed number of 1 rows which when clean triggers fix
306   Always does if all 1 rows cleaned up and number>0 or if fraction columns reached
307   Also whether to create branch if can't reach fraction.
308*/ 
309CbcBranchToFixLots::CbcBranchToFixLots (CbcModel * model, double djTolerance,
310                                        double fractionFixed, int depth,
311                                        int numberClean,
312                                        const char * mark, bool alwaysCreate)
313  : CbcBranchCut(model)
314{
315  djTolerance_ = djTolerance;
316  fractionFixed_ = fractionFixed;
317  if (mark) {
318    int numberColumns = model->getNumCols();
319    mark_ = new char[numberColumns];
320    memcpy(mark_,mark,numberColumns);
321  }
322  depth_ = depth;
323  assert (model);
324  OsiSolverInterface * solver = model_->solver();
325  matrixByRow_ = *solver->getMatrixByRow();
326  numberClean_ = numberClean;
327  alwaysCreate_ = alwaysCreate;
328}
329// Copy constructor
330CbcBranchToFixLots::CbcBranchToFixLots ( const CbcBranchToFixLots & rhs)
331  :CbcBranchCut(rhs)
332{
333  djTolerance_ = rhs.djTolerance_;
334  fractionFixed_ = rhs.fractionFixed_;
335  int numberColumns = model_->getNumCols();
336  mark_ = CoinCopyOfArray(rhs.mark_,numberColumns);
337  matrixByRow_=rhs.matrixByRow_;
338  depth_ = rhs.depth_;
339  numberClean_ = rhs.numberClean_;
340  alwaysCreate_ = rhs.alwaysCreate_;
341}
342
343// Clone
344CbcObject *
345CbcBranchToFixLots::clone() const
346{
347  return new CbcBranchToFixLots(*this);
348}
349
350// Assignment operator
351CbcBranchToFixLots & 
352CbcBranchToFixLots::operator=( const CbcBranchToFixLots& rhs)
353{
354  if (this!=&rhs) {
355    CbcBranchCut::operator=(rhs);
356    djTolerance_ = rhs.djTolerance_;
357    fractionFixed_ = rhs.fractionFixed_;
358    int numberColumns = model_->getNumCols();
359    delete [] mark_;
360    mark_ = CoinCopyOfArray(rhs.mark_,numberColumns);
361    matrixByRow_=rhs.matrixByRow_;
362    depth_ = rhs.depth_;
363    numberClean_ = rhs.numberClean_;
364    alwaysCreate_ = rhs.alwaysCreate_;
365  }
366  return *this;
367}
368
369// Destructor
370CbcBranchToFixLots::~CbcBranchToFixLots ()
371{
372  delete [] mark_;
373}
374// Creates a branching object
375CbcBranchingObject * 
376CbcBranchToFixLots::createBranch(int way) 
377{
378  // by default way must be -1
379  assert (way==-1);
380  OsiSolverInterface * solver = model_->solver();
381  const double * solution = model_->testSolution();
382  const double * lower = solver->getColLower();
383  const double * upper = solver->getColUpper();
384  const double * dj = solver->getReducedCost();
385  int i;
386  int numberIntegers = model_->numberIntegers();
387  const int * integerVariable = model_->integerVariable();
388  double integerTolerance = 
389    model_->getDblParam(CbcModel::CbcIntegerTolerance);
390  // make smaller ?
391  double tolerance = CoinMin(1.0e-8,integerTolerance);
392  // How many fixed are we aiming at
393  int wantedFixed = (int) ((double)numberIntegers*fractionFixed_);
394  int nSort=0;
395  int numberFixed=0;
396  int numberColumns = solver->getNumCols();
397  int * sort = new int[numberColumns];
398  double * dsort = new double[numberColumns];
399  int type = shallWe();
400  assert (type);
401  // Take clean first
402  if (type==1) {
403    for (i=0;i<numberIntegers;i++) {
404      int iColumn = integerVariable[i];
405      if (upper[iColumn]>lower[iColumn]) {
406        if (!mark_||!mark_[iColumn]) {
407          if(solution[iColumn]<lower[iColumn]+tolerance) {
408            if (dj[iColumn]>djTolerance_) {
409              dsort[nSort]=-dj[iColumn];
410              sort[nSort++]=iColumn;
411            }
412          } else if (solution[iColumn]>upper[iColumn]-tolerance) {
413            if (dj[iColumn]<-djTolerance_) {
414              dsort[nSort]=dj[iColumn];
415              sort[nSort++]=iColumn;
416            }
417          }
418        }
419      } else {
420        numberFixed++;
421      }
422    }
423    // sort
424    CoinSort_2(dsort,dsort+nSort,sort);
425    nSort= CoinMin(nSort,wantedFixed-numberFixed);
426  } else {
427    int i;
428    //const double * rowLower = solver->getRowLower();
429    const double * rowUpper = solver->getRowUpper();
430    // Row copy
431    const double * elementByRow = matrixByRow_.getElements();
432    const int * column = matrixByRow_.getIndices();
433    const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
434    const int * rowLength = matrixByRow_.getVectorLengths();
435    const double * columnLower = solver->getColLower();
436    const double * columnUpper = solver->getColUpper();
437    const double * solution = solver->getColSolution();
438    int numberColumns = solver->getNumCols();
439    int numberRows = solver->getNumRows();
440    for (i=0;i<numberColumns;i++) {
441      sort[i]=i;
442      if (columnLower[i]!=columnUpper[i]){
443        dsort[i]=1.0e100;
444      } else {
445        dsort[i]=1.0e50;
446        numberFixed++;
447      }
448    }
449    for (i=0;i<numberRows;i++) {
450      double rhsValue = rowUpper[i];
451      bool oneRow=true;
452      // check elements
453      int numberUnsatisfied=0;
454      for (int j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
455        int iColumn = column[j];
456        double value = elementByRow[j];
457        double solValue = solution[iColumn];
458        if (columnLower[iColumn]!=columnUpper[iColumn]) {
459          if (solValue<1.0-integerTolerance&&solValue>integerTolerance)
460            numberUnsatisfied++;
461          if (value!=1.0) {
462            oneRow=false;
463            break;
464          }
465        } else {
466          rhsValue -= value*floor(solValue+0.5);
467        }
468      }
469      if (oneRow&&rhsValue<=1.0+tolerance) {
470        if (!numberUnsatisfied) {
471          for (int j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
472            int iColumn = column[j];
473            if (dsort[iColumn]>1.0e50){
474              dsort[iColumn]=0;
475              nSort++;
476            }
477          }
478        }
479      }
480    }
481    // sort
482    CoinSort_2(dsort,dsort+numberColumns,sort);
483  }
484  OsiRowCut down;
485  down.setLb(-COIN_DBL_MAX);
486  double rhs=0.0;
487  for (i=0;i<nSort;i++) {
488    int iColumn = sort[i];
489    if(solution[iColumn]<lower[iColumn]+tolerance) {
490      rhs += lower[iColumn];
491      dsort[i]=1.0;
492      assert (!lower[iColumn]);
493    } else {
494      assert (solution[iColumn]>upper[iColumn]-tolerance);
495      rhs -= upper[iColumn];
496      dsort[i]=-1.0;
497      //printf("%d at ub of %g\n",iColumn,upper[iColumn]);
498    }
499  }
500  down.setUb(rhs);
501  down.setRow(nSort,sort,dsort);
502  delete [] sort;
503  delete [] dsort;
504  // up is same - just with rhs changed
505  OsiRowCut up = down;
506  up.setLb(rhs +1.0);
507  up.setUb(COIN_DBL_MAX);
508  // Say can fix one way
509  CbcCutBranchingObject * newObject = 
510    new CbcCutBranchingObject(model_,down,up,true);
511  if (model_->messageHandler()->logLevel()>1)
512    printf("creating cut in CbcBranchCut\n");
513  return newObject;
514}
515/* Does a lot of the work,
516   Returns 0 if no good, 1 if dj, 2 if clean, 3 if both
517*/
518int 
519CbcBranchToFixLots::shallWe() const
520{
521  int returnCode=0;
522  OsiSolverInterface * solver = model_->solver();
523  int numberRows = matrixByRow_.getNumRows();
524  //if (numberRows!=solver->getNumRows())
525  //return 0;
526  const double * solution = model_->testSolution();
527  const double * lower = solver->getColLower();
528  const double * upper = solver->getColUpper();
529  const double * dj = solver->getReducedCost();
530  int i;
531  int numberIntegers = model_->numberIntegers();
532  const int * integerVariable = model_->integerVariable();
533  double integerTolerance = 
534    model_->getDblParam(CbcModel::CbcIntegerTolerance);
535  // make smaller ?
536  double tolerance = CoinMin(1.0e-8,integerTolerance);
537  // How many fixed are we aiming at
538  int wantedFixed = (int) ((double)numberIntegers*fractionFixed_);
539  if (djTolerance_<1.0e10) {
540    int nSort=0;
541    int numberFixed=0;
542    for (i=0;i<numberIntegers;i++) {
543      int iColumn = integerVariable[i];
544      if (upper[iColumn]>lower[iColumn]) {
545        if (!mark_||!mark_[iColumn]) {
546          if(solution[iColumn]<lower[iColumn]+tolerance) {
547            if (dj[iColumn]>djTolerance_) {
548              nSort++;
549            }
550          } else if (solution[iColumn]>upper[iColumn]-tolerance) {
551            if (dj[iColumn]<-djTolerance_) {
552              nSort++;
553            }
554          }
555        }
556      } else {
557        numberFixed++;
558      }
559    }
560    if (numberFixed+nSort<wantedFixed&&!alwaysCreate_) {
561      returnCode = 0;
562    } else if (numberFixed<wantedFixed) {
563      returnCode = 1;
564    } else {
565      returnCode = 0;
566    }
567  }
568  if (numberClean_) {
569    // see how many rows clean
570    int i;
571    //const double * rowLower = solver->getRowLower();
572    const double * rowUpper = solver->getRowUpper();
573    // Row copy
574    const double * elementByRow = matrixByRow_.getElements();
575    const int * column = matrixByRow_.getIndices();
576    const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
577    const int * rowLength = matrixByRow_.getVectorLengths();
578    const double * columnLower = solver->getColLower();
579    const double * columnUpper = solver->getColUpper();
580    const double * solution = solver->getColSolution();
581    int numberClean=0;
582    bool someToDoYet=false;
583    int numberColumns = solver->getNumCols();
584    char * mark = new char[numberColumns];
585    int numberFixed=0;
586    for (i=0;i<numberColumns;i++) {
587      if (columnLower[i]!=columnUpper[i]){
588        mark[i]=0;
589      } else {
590        mark[i]=1;
591        numberFixed++;
592      }
593    }
594    int numberNewFixed=0;
595    for (i=0;i<numberRows;i++) {
596      double rhsValue = rowUpper[i];
597      bool oneRow=true;
598      // check elements
599      int numberUnsatisfied=0;
600      for (int j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
601        int iColumn = column[j];
602        double value = elementByRow[j];
603        double solValue = solution[iColumn];
604        if (columnLower[iColumn]!=columnUpper[iColumn]) {
605          if (solValue<1.0-integerTolerance&&solValue>integerTolerance)
606            numberUnsatisfied++;
607          if (value!=1.0) {
608            oneRow=false;
609            break;
610          }
611        } else {
612          rhsValue -= value*floor(solValue+0.5);
613        }
614      }
615      if (oneRow&&rhsValue<=1.0+tolerance) {
616        if (numberUnsatisfied) {
617          someToDoYet=true;
618        } else {
619          numberClean++;
620          for (int j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
621            int iColumn = column[j];
622            if (columnLower[iColumn]!=columnUpper[iColumn]&&!mark[iColumn]){
623              mark[iColumn]=1;
624              numberNewFixed++;
625            }
626          }
627        }
628      }
629    }
630    delete [] mark;
631    //printf("%d clean, %d old fixed, %d new fixed\n",
632    //   numberClean,numberFixed,numberNewFixed);
633    if (someToDoYet&&numberClean<numberClean_
634        &&numberNewFixed+numberFixed<wantedFixed) {
635    } else if (numberFixed<wantedFixed) {
636      returnCode |= 2;
637    } else {
638    }
639  }
640  return returnCode;
641}
642// Infeasibility - large is 0.5
643double 
644CbcBranchToFixLots::infeasibility(int & preferredWay) const
645{
646  preferredWay=-1;
647  CbcNode * node = model_->currentNode();
648  int depth;
649  if (node)
650    depth=CoinMax(node->depth(),0);
651  else
652    return 0.0;
653  if (depth_<0) {
654    return 0.0;
655  } else if (depth_>0) {
656    if ((depth%depth_)!=0)
657      return 0.0;
658  }
659  if (!shallWe())
660    return 0.0;
661  else
662    return 1.0e20;
663}
664
665/** Default Constructor
666*/
667CbcBranchAllDifferent::CbcBranchAllDifferent ()
668  : CbcBranchCut(),
669    numberInSet_(0),
670    which_(NULL)
671{
672}
673
674/* Useful constructor - passed set of variables
675*/ 
676CbcBranchAllDifferent::CbcBranchAllDifferent (CbcModel * model, int numberInSet,
677                                              const int * members)
678  : CbcBranchCut(model)
679{
680  numberInSet_=numberInSet;
681  which_ = CoinCopyOfArray(members,numberInSet_);
682}
683// Copy constructor
684CbcBranchAllDifferent::CbcBranchAllDifferent ( const CbcBranchAllDifferent & rhs)
685  :CbcBranchCut(rhs)
686{
687  numberInSet_=rhs.numberInSet_;
688  which_ = CoinCopyOfArray(rhs.which_,numberInSet_);
689}
690
691// Clone
692CbcObject *
693CbcBranchAllDifferent::clone() const
694{
695  return new CbcBranchAllDifferent(*this);
696}
697
698// Assignment operator
699CbcBranchAllDifferent & 
700CbcBranchAllDifferent::operator=( const CbcBranchAllDifferent& rhs)
701{
702  if (this!=&rhs) {
703    CbcBranchCut::operator=(rhs);
704    delete [] which_;
705    numberInSet_=rhs.numberInSet_;
706    which_ = CoinCopyOfArray(rhs.which_,numberInSet_);
707  }
708  return *this;
709}
710
711// Destructor
712CbcBranchAllDifferent::~CbcBranchAllDifferent ()
713{
714  delete [] which_;
715}
716// Creates a branching object
717CbcBranchingObject * 
718CbcBranchAllDifferent::createBranch(int way) 
719{
720  // by default way must be -1
721  assert (way==-1);
722  const double * solution = model_->testSolution();
723  double * values = new double[numberInSet_];
724  int * which = new int[numberInSet_];
725  int i;
726  for (i=0;i<numberInSet_;i++) {
727    int iColumn = which_[i];
728    values[i]=solution[iColumn];
729    which[i]=iColumn;
730  }
731  CoinSort_2(values,values+numberInSet_,which);
732  double last = -1.0;
733  double closest=1.0;
734  int worst=-1;
735  for (i=0;i<numberInSet_;i++) {
736    if (values[i]-last<closest) {
737      closest=values[i]-last;
738      worst=i-1;
739    }
740    last=values[i];
741  }
742  assert (closest<=0.99999);
743  OsiRowCut down;
744  down.setLb(-COIN_DBL_MAX);
745  down.setUb(-1.0);
746  int pair[2];
747  double elements[]={1.0,-1.0};
748  pair[0]=which[worst];
749  pair[1]=which[worst+1];
750  delete [] values;
751  delete [] which;
752  down.setRow(2,pair,elements);
753  // up is same - just with rhs changed
754  OsiRowCut up = down;
755  up.setLb(1.0);
756  up.setUb(COIN_DBL_MAX);
757  // Say is not a fix type branch
758  CbcCutBranchingObject * newObject = 
759    new CbcCutBranchingObject(model_,down,up,false);
760  if (model_->messageHandler()->logLevel()>1)
761    printf("creating cut in CbcBranchCut\n");
762  return newObject;
763}
764// Infeasibility - large is 0.5
765double 
766CbcBranchAllDifferent::infeasibility(int & preferredWay) const
767{
768  preferredWay=-1;
769  //OsiSolverInterface * solver = model_->solver();
770  const double * solution = model_->testSolution();
771  //const double * lower = solver->getColLower();
772  //const double * upper = solver->getColUpper();
773  double * values = new double[numberInSet_];
774  int i;
775  for (i=0;i<numberInSet_;i++) {
776    int iColumn = which_[i];
777    values[i]=solution[iColumn];
778  }
779  std::sort(values,values+numberInSet_);
780  double last = -1.0;
781  double closest=1.0;
782  for (i=0;i<numberInSet_;i++) {
783    if (values[i]-last<closest) {
784      closest=values[i]-last;
785    }
786    last=values[i];
787  }
788  delete [] values;
789  if (closest>0.99999)
790    return 0.0;
791  else
792    return 0.5*(1.0-closest);
793}
Note: See TracBrowser for help on using the repository browser.