source: branches/devel/Cbc/src/CbcBranchCut.cpp @ 400

Last change on this file since 400 was 310, checked in by andreasw, 14 years ago

first commit for autotools conversion to be able to move more files

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