source: stable/2.0/Cbc/src/CbcBranchCut.cpp @ 905

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

include cstdlib before cmath to get things to compile on AIX with xlC (same as changeset 904 in trunk)

  • 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.