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

Last change on this file since 484 was 439, checked in by forrest, 13 years ago

towards common use with other solvers

  • 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 <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()
189{
190  decrementNumberBranchesLeft();
191  OsiRowCut * cut;
192  if (way_<0) {
193    cut = &down_;
194    way_=1;
195  } else {
196    cut = &up_;
197    way_=-1;      // Swap direction
198  }
199  // See if cut just fixes variables
200  double lb = cut->lb();
201  double ub = cut->ub();
202  int n=cut->row().getNumElements();
203  const int * column = cut->row().getIndices();
204  const double * element = cut->row().getElements();
205  OsiSolverInterface * solver = model_->solver();
206  const double * upper = solver->getColUpper();
207  const double * lower = solver->getColLower();
208  double low = 0.0;
209  double high=0.0;
210  for (int i=0;i<n;i++) {
211    int iColumn = column[i];
212    double value = element[i];
213    if (value>0.0) {
214      high += upper[iColumn]*value;
215      low += lower[iColumn]*value;
216    } else {
217      high += lower[iColumn]*value;
218      low += upper[iColumn]*value;
219    }
220  }
221  // assume cut was cunningly constructed so we need not worry too much about tolerances
222  if (low+1.0e-8>=ub&&canFix_) {
223    // fix
224    for (int i=0;i<n;i++) {
225      int iColumn = column[i];
226      double value = element[i];
227      if (value>0.0) {
228        solver->setColUpper(iColumn,lower[iColumn]);
229      } else {
230        solver->setColLower(iColumn,upper[iColumn]);
231      }
232    }
233  } else if (high-1.0e-8<=lb&&canFix_) {
234    // fix
235    for (int i=0;i<n;i++) {
236      int iColumn = column[i];
237      double value = element[i];
238      if (value>0.0) {
239        solver->setColLower(iColumn,upper[iColumn]);
240      } else {
241        solver->setColUpper(iColumn,lower[iColumn]);
242      }
243    }
244  } else {
245    // leave as cut
246    model_->setNextRowCut(*cut);
247  }
248  return 0.0;
249}
250// Print what would happen 
251void
252CbcCutBranchingObject::print()
253{
254  OsiRowCut * cut;
255  if (way_<0) {
256    cut = &down_;
257    printf("CbcCut would branch down");
258  } else {
259    cut = &up_;
260    printf("CbcCut would branch up");
261  }
262  double lb = cut->lb();
263  double ub = cut->ub();
264  int n=cut->row().getNumElements();
265  const int * column = cut->row().getIndices();
266  const double * element = cut->row().getElements();
267  if (n>5) {
268    printf(" - %d elements, lo=%g, up=%g\n",n,lb,ub);
269  } else {
270    printf(" - %g <=",lb);
271    for (int i=0;i<n;i++) {
272      int iColumn = column[i];
273      double value = element[i];
274      printf(" (%d,%g)",iColumn,value);
275    }
276    printf(" <= %g\n",ub);
277  }
278}
279
280// Return true if branch should fix variables
281bool 
282CbcCutBranchingObject::boundBranch() const
283{
284  return false;
285}
286
287/** Default Constructor
288
289  Equivalent to an unspecified binary variable.
290*/
291CbcBranchToFixLots::CbcBranchToFixLots ()
292  : CbcBranchCut(),
293    djTolerance_(COIN_DBL_MAX),
294    fractionFixed_(1.0),
295    mark_(NULL),
296    depth_(-1),
297    numberClean_(0),
298    alwaysCreate_(false)
299{
300}
301
302/* Useful constructor - passed reduced cost tolerance and fraction we would like fixed.
303   Also depth level to do at.
304   Also passed number of 1 rows which when clean triggers fix
305   Always does if all 1 rows cleaned up and number>0 or if fraction columns reached
306   Also whether to create branch if can't reach fraction.
307*/ 
308CbcBranchToFixLots::CbcBranchToFixLots (CbcModel * model, double djTolerance,
309                                        double fractionFixed, int depth,
310                                        int numberClean,
311                                        const char * mark, bool alwaysCreate)
312  : CbcBranchCut(model)
313{
314  djTolerance_ = djTolerance;
315  fractionFixed_ = fractionFixed;
316  if (mark) {
317    int numberColumns = model->getNumCols();
318    mark_ = new char[numberColumns];
319    memcpy(mark_,mark,numberColumns);
320  }
321  depth_ = depth;
322  assert (model);
323  OsiSolverInterface * solver = model_->solver();
324  matrixByRow_ = *solver->getMatrixByRow();
325  numberClean_ = numberClean;
326  alwaysCreate_ = alwaysCreate;
327}
328// Copy constructor
329CbcBranchToFixLots::CbcBranchToFixLots ( const CbcBranchToFixLots & rhs)
330  :CbcBranchCut(rhs)
331{
332  djTolerance_ = rhs.djTolerance_;
333  fractionFixed_ = rhs.fractionFixed_;
334  int numberColumns = model_->getNumCols();
335  mark_ = CoinCopyOfArray(rhs.mark_,numberColumns);
336  matrixByRow_=rhs.matrixByRow_;
337  depth_ = rhs.depth_;
338  numberClean_ = rhs.numberClean_;
339  alwaysCreate_ = rhs.alwaysCreate_;
340}
341
342// Clone
343CbcObject *
344CbcBranchToFixLots::clone() const
345{
346  return new CbcBranchToFixLots(*this);
347}
348
349// Assignment operator
350CbcBranchToFixLots & 
351CbcBranchToFixLots::operator=( const CbcBranchToFixLots& rhs)
352{
353  if (this!=&rhs) {
354    CbcBranchCut::operator=(rhs);
355    djTolerance_ = rhs.djTolerance_;
356    fractionFixed_ = rhs.fractionFixed_;
357    int numberColumns = model_->getNumCols();
358    delete [] mark_;
359    mark_ = CoinCopyOfArray(rhs.mark_,numberColumns);
360    matrixByRow_=rhs.matrixByRow_;
361    depth_ = rhs.depth_;
362    numberClean_ = rhs.numberClean_;
363    alwaysCreate_ = rhs.alwaysCreate_;
364  }
365  return *this;
366}
367
368// Destructor
369CbcBranchToFixLots::~CbcBranchToFixLots ()
370{
371  delete [] mark_;
372}
373// Creates a branching object
374CbcBranchingObject * 
375CbcBranchToFixLots::createBranch(int way) 
376{
377  // by default way must be -1
378  assert (way==-1);
379  OsiSolverInterface * solver = model_->solver();
380  const double * solution = model_->testSolution();
381  const double * lower = solver->getColLower();
382  const double * upper = solver->getColUpper();
383  const double * dj = solver->getReducedCost();
384  int i;
385  int numberIntegers = model_->numberIntegers();
386  const int * integerVariable = model_->integerVariable();
387  double integerTolerance = 
388    model_->getDblParam(CbcModel::CbcIntegerTolerance);
389  // make smaller ?
390  double tolerance = CoinMin(1.0e-8,integerTolerance);
391  // How many fixed are we aiming at
392  int wantedFixed = (int) ((double)numberIntegers*fractionFixed_);
393  int nSort=0;
394  int numberFixed=0;
395  int numberColumns = solver->getNumCols();
396  int * sort = new int[numberColumns];
397  double * dsort = new double[numberColumns];
398  int type = shallWe();
399  assert (type);
400  // Take clean first
401  if (type==1) {
402    for (i=0;i<numberIntegers;i++) {
403      int iColumn = integerVariable[i];
404      if (upper[iColumn]>lower[iColumn]) {
405        if (!mark_||!mark_[iColumn]) {
406          if(solution[iColumn]<lower[iColumn]+tolerance) {
407            if (dj[iColumn]>djTolerance_) {
408              dsort[nSort]=-dj[iColumn];
409              sort[nSort++]=iColumn;
410            }
411          } else if (solution[iColumn]>upper[iColumn]-tolerance) {
412            if (dj[iColumn]<-djTolerance_) {
413              dsort[nSort]=dj[iColumn];
414              sort[nSort++]=iColumn;
415            }
416          }
417        }
418      } else {
419        numberFixed++;
420      }
421    }
422    // sort
423    CoinSort_2(dsort,dsort+nSort,sort);
424    nSort= CoinMin(nSort,wantedFixed-numberFixed);
425  } else {
426    int i;
427    //const double * rowLower = solver->getRowLower();
428    const double * rowUpper = solver->getRowUpper();
429    // Row copy
430    const double * elementByRow = matrixByRow_.getElements();
431    const int * column = matrixByRow_.getIndices();
432    const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
433    const int * rowLength = matrixByRow_.getVectorLengths();
434    const double * columnLower = solver->getColLower();
435    const double * columnUpper = solver->getColUpper();
436    const double * solution = solver->getColSolution();
437    int numberColumns = solver->getNumCols();
438    int numberRows = solver->getNumRows();
439    for (i=0;i<numberColumns;i++) {
440      sort[i]=i;
441      if (columnLower[i]!=columnUpper[i]){
442        dsort[i]=1.0e100;
443      } else {
444        dsort[i]=1.0e50;
445        numberFixed++;
446      }
447    }
448    for (i=0;i<numberRows;i++) {
449      double rhsValue = rowUpper[i];
450      bool oneRow=true;
451      // check elements
452      int numberUnsatisfied=0;
453      for (int j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
454        int iColumn = column[j];
455        double value = elementByRow[j];
456        double solValue = solution[iColumn];
457        if (columnLower[iColumn]!=columnUpper[iColumn]) {
458          if (solValue<1.0-integerTolerance&&solValue>integerTolerance)
459            numberUnsatisfied++;
460          if (value!=1.0) {
461            oneRow=false;
462            break;
463          }
464        } else {
465          rhsValue -= value*floor(solValue+0.5);
466        }
467      }
468      if (oneRow&&rhsValue<=1.0+tolerance) {
469        if (!numberUnsatisfied) {
470          for (int j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
471            int iColumn = column[j];
472            if (dsort[iColumn]>1.0e50){
473              dsort[iColumn]=0;
474              nSort++;
475            }
476          }
477        }
478      }
479    }
480    // sort
481    CoinSort_2(dsort,dsort+numberColumns,sort);
482  }
483  OsiRowCut down;
484  down.setLb(-COIN_DBL_MAX);
485  double rhs=0.0;
486  for (i=0;i<nSort;i++) {
487    int iColumn = sort[i];
488    if(solution[iColumn]<lower[iColumn]+tolerance) {
489      rhs += lower[iColumn];
490      dsort[i]=1.0;
491      assert (!lower[iColumn]);
492    } else {
493      assert (solution[iColumn]>upper[iColumn]-tolerance);
494      rhs -= upper[iColumn];
495      dsort[i]=-1.0;
496      //printf("%d at ub of %g\n",iColumn,upper[iColumn]);
497    }
498  }
499  down.setUb(rhs);
500  down.setRow(nSort,sort,dsort);
501  delete [] sort;
502  delete [] dsort;
503  // up is same - just with rhs changed
504  OsiRowCut up = down;
505  up.setLb(rhs +1.0);
506  up.setUb(COIN_DBL_MAX);
507  // Say can fix one way
508  CbcCutBranchingObject * newObject = 
509    new CbcCutBranchingObject(model_,down,up,true);
510  if (model_->messageHandler()->logLevel()>1)
511    printf("creating cut in CbcBranchCut\n");
512  return newObject;
513}
514/* Does a lot of the work,
515   Returns 0 if no good, 1 if dj, 2 if clean, 3 if both
516*/
517int 
518CbcBranchToFixLots::shallWe() const
519{
520  int returnCode=0;
521  OsiSolverInterface * solver = model_->solver();
522  int numberRows = matrixByRow_.getNumRows();
523  //if (numberRows!=solver->getNumRows())
524  //return 0;
525  const double * solution = model_->testSolution();
526  const double * lower = solver->getColLower();
527  const double * upper = solver->getColUpper();
528  const double * dj = solver->getReducedCost();
529  int i;
530  int numberIntegers = model_->numberIntegers();
531  const int * integerVariable = model_->integerVariable();
532  double integerTolerance = 
533    model_->getDblParam(CbcModel::CbcIntegerTolerance);
534  // make smaller ?
535  double tolerance = CoinMin(1.0e-8,integerTolerance);
536  // How many fixed are we aiming at
537  int wantedFixed = (int) ((double)numberIntegers*fractionFixed_);
538  if (djTolerance_<1.0e10) {
539    int nSort=0;
540    int numberFixed=0;
541    for (i=0;i<numberIntegers;i++) {
542      int iColumn = integerVariable[i];
543      if (upper[iColumn]>lower[iColumn]) {
544        if (!mark_||!mark_[iColumn]) {
545          if(solution[iColumn]<lower[iColumn]+tolerance) {
546            if (dj[iColumn]>djTolerance_) {
547              nSort++;
548            }
549          } else if (solution[iColumn]>upper[iColumn]-tolerance) {
550            if (dj[iColumn]<-djTolerance_) {
551              nSort++;
552            }
553          }
554        }
555      } else {
556        numberFixed++;
557      }
558    }
559    if (numberFixed+nSort<wantedFixed&&!alwaysCreate_) {
560      returnCode = 0;
561    } else if (numberFixed<wantedFixed) {
562      returnCode = 1;
563    } else {
564      returnCode = 0;
565    }
566  }
567  if (numberClean_) {
568    // see how many rows clean
569    int i;
570    //const double * rowLower = solver->getRowLower();
571    const double * rowUpper = solver->getRowUpper();
572    // Row copy
573    const double * elementByRow = matrixByRow_.getElements();
574    const int * column = matrixByRow_.getIndices();
575    const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
576    const int * rowLength = matrixByRow_.getVectorLengths();
577    const double * columnLower = solver->getColLower();
578    const double * columnUpper = solver->getColUpper();
579    const double * solution = solver->getColSolution();
580    int numberClean=0;
581    bool someToDoYet=false;
582    int numberColumns = solver->getNumCols();
583    char * mark = new char[numberColumns];
584    int numberFixed=0;
585    for (i=0;i<numberColumns;i++) {
586      if (columnLower[i]!=columnUpper[i]){
587        mark[i]=0;
588      } else {
589        mark[i]=1;
590        numberFixed++;
591      }
592    }
593    int numberNewFixed=0;
594    for (i=0;i<numberRows;i++) {
595      double rhsValue = rowUpper[i];
596      bool oneRow=true;
597      // check elements
598      int numberUnsatisfied=0;
599      for (int j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
600        int iColumn = column[j];
601        double value = elementByRow[j];
602        double solValue = solution[iColumn];
603        if (columnLower[iColumn]!=columnUpper[iColumn]) {
604          if (solValue<1.0-integerTolerance&&solValue>integerTolerance)
605            numberUnsatisfied++;
606          if (value!=1.0) {
607            oneRow=false;
608            break;
609          }
610        } else {
611          rhsValue -= value*floor(solValue+0.5);
612        }
613      }
614      if (oneRow&&rhsValue<=1.0+tolerance) {
615        if (numberUnsatisfied) {
616          someToDoYet=true;
617        } else {
618          numberClean++;
619          for (int j=rowStart[i];j<rowStart[i]+rowLength[i];j++) {
620            int iColumn = column[j];
621            if (columnLower[iColumn]!=columnUpper[iColumn]&&!mark[iColumn]){
622              mark[iColumn]=1;
623              numberNewFixed++;
624            }
625          }
626        }
627      }
628    }
629    delete [] mark;
630    //printf("%d clean, %d old fixed, %d new fixed\n",
631    //   numberClean,numberFixed,numberNewFixed);
632    if (someToDoYet&&numberClean<numberClean_
633        &&numberNewFixed+numberFixed<wantedFixed) {
634    } else if (numberFixed<wantedFixed) {
635      returnCode |= 2;
636    } else {
637    }
638  }
639  return returnCode;
640}
641// Infeasibility - large is 0.5
642double 
643CbcBranchToFixLots::infeasibility(int & preferredWay) const
644{
645  preferredWay=-1;
646  CbcNode * node = model_->currentNode();
647  int depth;
648  if (node)
649    depth=CoinMax(node->depth(),0);
650  else
651    return 0.0;
652  if (depth_<0) {
653    return 0.0;
654  } else if (depth_>0) {
655    if ((depth%depth_)!=0)
656      return 0.0;
657  }
658  if (!shallWe())
659    return 0.0;
660  else
661    return 1.0e20;
662}
663
664/** Default Constructor
665*/
666CbcBranchAllDifferent::CbcBranchAllDifferent ()
667  : CbcBranchCut(),
668    numberInSet_(0),
669    which_(NULL)
670{
671}
672
673/* Useful constructor - passed set of variables
674*/ 
675CbcBranchAllDifferent::CbcBranchAllDifferent (CbcModel * model, int numberInSet,
676                                              const int * members)
677  : CbcBranchCut(model)
678{
679  numberInSet_=numberInSet;
680  which_ = CoinCopyOfArray(members,numberInSet_);
681}
682// Copy constructor
683CbcBranchAllDifferent::CbcBranchAllDifferent ( const CbcBranchAllDifferent & rhs)
684  :CbcBranchCut(rhs)
685{
686  numberInSet_=rhs.numberInSet_;
687  which_ = CoinCopyOfArray(rhs.which_,numberInSet_);
688}
689
690// Clone
691CbcObject *
692CbcBranchAllDifferent::clone() const
693{
694  return new CbcBranchAllDifferent(*this);
695}
696
697// Assignment operator
698CbcBranchAllDifferent & 
699CbcBranchAllDifferent::operator=( const CbcBranchAllDifferent& rhs)
700{
701  if (this!=&rhs) {
702    CbcBranchCut::operator=(rhs);
703    delete [] which_;
704    numberInSet_=rhs.numberInSet_;
705    which_ = CoinCopyOfArray(rhs.which_,numberInSet_);
706  }
707  return *this;
708}
709
710// Destructor
711CbcBranchAllDifferent::~CbcBranchAllDifferent ()
712{
713  delete [] which_;
714}
715// Creates a branching object
716CbcBranchingObject * 
717CbcBranchAllDifferent::createBranch(int way) 
718{
719  // by default way must be -1
720  assert (way==-1);
721  const double * solution = model_->testSolution();
722  double * values = new double[numberInSet_];
723  int * which = new int[numberInSet_];
724  int i;
725  for (i=0;i<numberInSet_;i++) {
726    int iColumn = which_[i];
727    values[i]=solution[iColumn];
728    which[i]=iColumn;
729  }
730  CoinSort_2(values,values+numberInSet_,which);
731  double last = -1.0;
732  double closest=1.0;
733  int worst=-1;
734  for (i=0;i<numberInSet_;i++) {
735    if (values[i]-last<closest) {
736      closest=values[i]-last;
737      worst=i-1;
738    }
739    last=values[i];
740  }
741  assert (closest<=0.99999);
742  OsiRowCut down;
743  down.setLb(-COIN_DBL_MAX);
744  down.setUb(-1.0);
745  int pair[2];
746  double elements[]={1.0,-1.0};
747  pair[0]=which[worst];
748  pair[1]=which[worst+1];
749  delete [] values;
750  delete [] which;
751  down.setRow(2,pair,elements);
752  // up is same - just with rhs changed
753  OsiRowCut up = down;
754  up.setLb(1.0);
755  up.setUb(COIN_DBL_MAX);
756  // Say is not a fix type branch
757  CbcCutBranchingObject * newObject = 
758    new CbcCutBranchingObject(model_,down,up,false);
759  if (model_->messageHandler()->logLevel()>1)
760    printf("creating cut in CbcBranchCut\n");
761  return newObject;
762}
763// Infeasibility - large is 0.5
764double 
765CbcBranchAllDifferent::infeasibility(int & preferredWay) const
766{
767  preferredWay=-1;
768  //OsiSolverInterface * solver = model_->solver();
769  const double * solution = model_->testSolution();
770  //const double * lower = solver->getColLower();
771  //const double * upper = solver->getColUpper();
772  double * values = new double[numberInSet_];
773  int i;
774  for (i=0;i<numberInSet_;i++) {
775    int iColumn = which_[i];
776    values[i]=solution[iColumn];
777  }
778  std::sort(values,values+numberInSet_);
779  double last = -1.0;
780  double closest=1.0;
781  for (i=0;i<numberInSet_;i++) {
782    if (values[i]-last<closest) {
783      closest=values[i]-last;
784    }
785    last=values[i];
786  }
787  delete [] values;
788  if (closest>0.99999)
789    return 0.0;
790  else
791    return 0.5*(1.0-closest);
792}
Note: See TracBrowser for help on using the repository browser.