source: trunk/CbcHeuristic.cpp @ 129

Last change on this file since 129 was 95, checked in by forrest, 16 years ago

fix minor bug

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.7 KB
Line 
1// Copyright (C) 2002, 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
11#include "OsiSolverInterface.hpp"
12#include "CbcModel.hpp"
13#include "CbcMessage.hpp"
14#include "CbcHeuristic.hpp"
15
16// Default Constructor
17CbcHeuristic::CbcHeuristic() 
18  :model_(NULL),
19   when_(2)
20{
21}
22
23// Constructor from model
24CbcHeuristic::CbcHeuristic(CbcModel & model)
25:
26  model_(&model),
27  when_(2)
28{
29}
30// Resets stuff if model changes
31void 
32CbcHeuristic::resetModel(CbcModel * model)
33{
34  model_=model;
35}
36
37// Destructor
38CbcHeuristic::~CbcHeuristic ()
39{
40}
41
42// update model
43void CbcHeuristic::setModel(CbcModel * model)
44{
45  model_ = model;
46}
47
48// Default Constructor
49CbcRounding::CbcRounding() 
50  :CbcHeuristic()
51{
52  // matrix and row copy will automatically be empty
53}
54
55// Constructor from model
56CbcRounding::CbcRounding(CbcModel & model)
57  :CbcHeuristic(model)
58{
59  // Get a copy of original matrix (and by row for rounding);
60  assert(model.solver());
61  matrix_ = *model.solver()->getMatrixByCol();
62  matrixByRow_ = *model.solver()->getMatrixByRow();
63  seed_=1;
64}
65
66// Destructor
67CbcRounding::~CbcRounding ()
68{
69}
70
71// Clone
72CbcHeuristic *
73CbcRounding::clone() const
74{
75  return new CbcRounding(*this);
76}
77
78// Copy constructor
79CbcRounding::CbcRounding(const CbcRounding & rhs)
80:
81  CbcHeuristic(rhs),
82  matrix_(rhs.matrix_),
83  matrixByRow_(rhs.matrixByRow_),
84  seed_(rhs.seed_)
85{
86  setWhen(rhs.when());
87}
88
89// Resets stuff if model changes
90void 
91CbcRounding::resetModel(CbcModel * model)
92{
93  model_=model;
94  // Get a copy of original matrix (and by row for rounding);
95  assert(model_->solver());
96  matrix_ = *model_->solver()->getMatrixByCol();
97  matrixByRow_ = *model_->solver()->getMatrixByRow();
98}
99// See if rounding will give solution
100// Sets value of solution
101// Assumes rhs for original matrix still okay
102// At present only works with integers
103// Fix values if asked for
104// Returns 1 if solution, 0 if not
105int
106CbcRounding::solution(double & solutionValue,
107                         double * betterSolution)
108{
109
110  // See if to do
111  if (!when()||(when()%10==1&&model_->phase()!=1)||
112      (when()%10==2&&model_->phase()!=2))
113    return 0; // switched off
114
115  OsiSolverInterface * solver = model_->solver();
116  const double * lower = solver->getColLower();
117  const double * upper = solver->getColUpper();
118  const double * rowLower = solver->getRowLower();
119  const double * rowUpper = solver->getRowUpper();
120  const double * solution = solver->getColSolution();
121  const double * objective = solver->getObjCoefficients();
122  double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);
123  double primalTolerance;
124  solver->getDblParam(OsiPrimalTolerance,primalTolerance);
125
126  int numberRows = matrix_.getNumRows();
127
128  int numberIntegers = model_->numberIntegers();
129  const int * integerVariable = model_->integerVariable();
130  int i;
131  double direction = solver->getObjSense();
132  double newSolutionValue = direction*solver->getObjValue();
133  int returnCode = 0;
134
135  // Column copy
136  const double * element = matrix_.getElements();
137  const int * row = matrix_.getIndices();
138  const CoinBigIndex * columnStart = matrix_.getVectorStarts();
139  const int * columnLength = matrix_.getVectorLengths();
140  // Row copy
141  const double * elementByRow = matrixByRow_.getElements();
142  const int * column = matrixByRow_.getIndices();
143  const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
144  const int * rowLength = matrixByRow_.getVectorLengths();
145
146  // Get solution array for heuristic solution
147  int numberColumns = solver->getNumCols();
148  double * newSolution = new double [numberColumns];
149  memcpy(newSolution,solution,numberColumns*sizeof(double));
150
151  double * rowActivity = new double[numberRows];
152  memset(rowActivity,0,numberRows*sizeof(double));
153  for (i=0;i<numberColumns;i++) {
154    int j;
155    double value = newSolution[i];
156    if (value<lower[i]) {
157      value=lower[i];
158      newSolution[i]=value;
159    } else if (value>upper[i]) {
160      value=upper[i];
161      newSolution[i]=value;
162    }
163    if (value) {
164      for (j=columnStart[i];
165           j<columnStart[i]+columnLength[i];j++) {
166        int iRow=row[j];
167        rowActivity[iRow] += value*element[j];
168      }
169    }
170  }
171  // check was feasible - if not adjust (cleaning may move)
172  for (i=0;i<numberRows;i++) {
173    if(rowActivity[i]<rowLower[i]) {
174      //assert (rowActivity[i]>rowLower[i]-1000.0*primalTolerance);
175      rowActivity[i]=rowLower[i];
176    } else if(rowActivity[i]>rowUpper[i]) {
177      //assert (rowActivity[i]<rowUpper[i]+1000.0*primalTolerance);
178      rowActivity[i]=rowUpper[i];
179    }
180  }
181  for (i=0;i<numberIntegers;i++) {
182    int iColumn = integerVariable[i];
183    double value=newSolution[iColumn];
184    if (fabs(floor(value+0.5)-value)>integerTolerance) {
185      double below = floor(value);
186      double newValue=newSolution[iColumn];
187      double cost = direction * objective[iColumn];
188      double move;
189      if (cost>0.0) {
190        // try up
191        move = 1.0 -(value-below);
192      } else if (cost<0.0) {
193        // try down
194        move = below-value;
195      } else {
196        // won't be able to move unless we can grab another variable
197        double randomNumber = CoinDrand48();
198        // which way?
199        if (randomNumber<0.5) 
200          move = below-value;
201        else
202          move = 1.0 -(value-below);
203      }
204      newValue += move;
205      newSolution[iColumn] = newValue;
206      newSolutionValue += move*cost;
207      int j;
208      for (j=columnStart[iColumn];
209           j<columnStart[iColumn]+columnLength[iColumn];j++) {
210        int iRow = row[j];
211        rowActivity[iRow] += move*element[j];
212      }
213    }
214  }
215
216  double penalty=0.0;
217 
218  // see if feasible - just using singletons
219  for (i=0;i<numberRows;i++) {
220    double value = rowActivity[i];
221    double thisInfeasibility=0.0;
222    if (value<rowLower[i]-primalTolerance)
223      thisInfeasibility = value-rowLower[i];
224    else if (value>rowUpper[i]+primalTolerance)
225      thisInfeasibility = value-rowUpper[i];
226    if (thisInfeasibility) {
227      // See if there are any slacks I can use to fix up
228      // maybe put in coding for multiple slacks?
229      double bestCost = 1.0e50;
230      int k;
231      int iBest=-1;
232      double addCost=0.0;
233      double newValue=0.0;
234      double changeRowActivity=0.0;
235      double absInfeasibility = fabs(thisInfeasibility);
236      for (k=rowStart[i];k<rowStart[i]+rowLength[i];k++) {
237        int iColumn = column[k];
238        // See if all elements help
239        if (columnLength[iColumn]==1) {
240          double currentValue = newSolution[iColumn];
241          double elementValue = elementByRow[k];
242          double lowerValue = lower[iColumn];
243          double upperValue = upper[iColumn];
244          double gap = rowUpper[i]-rowLower[i];
245          double absElement=fabs(elementValue);
246          if (thisInfeasibility*elementValue>0.0) {
247            // we want to reduce
248            if ((currentValue-lowerValue)*absElement>=absInfeasibility) {
249              // possible - check if integer
250              double distance = absInfeasibility/absElement;
251              double thisCost = -direction*objective[iColumn]*distance;
252              if (solver->isInteger(iColumn)) {
253                distance = ceil(distance-primalTolerance);
254                if (currentValue-distance>=lowerValue-primalTolerance) {
255                  if (absInfeasibility-distance*absElement< -gap-primalTolerance)
256                    thisCost=1.0e100; // no good
257                  else
258                    thisCost = -direction*objective[iColumn]*distance;
259                } else {
260                  thisCost=1.0e100; // no good
261                }
262              }
263              if (thisCost<bestCost) {
264                bestCost=thisCost;
265                iBest=iColumn;
266                addCost = thisCost;
267                newValue = currentValue-distance;
268                changeRowActivity = -distance*elementValue;
269              }
270            }
271          } else {
272            // we want to increase
273            if ((upperValue-currentValue)*absElement>=absInfeasibility) {
274              // possible - check if integer
275              double distance = absInfeasibility/absElement;
276              double thisCost = direction*objective[iColumn]*distance;
277              if (solver->isInteger(iColumn)) {
278                distance = ceil(distance-1.0e-7);
279                assert (currentValue-distance<=upperValue+primalTolerance);
280                if (absInfeasibility-distance*absElement< -gap-primalTolerance)
281                  thisCost=1.0e100; // no good
282                else
283                  thisCost = direction*objective[iColumn]*distance;
284              }
285              if (thisCost<bestCost) {
286                bestCost=thisCost;
287                iBest=iColumn;
288                addCost = thisCost;
289                newValue = currentValue+distance;
290                changeRowActivity = distance*elementValue;
291              }
292            }
293          }
294        }
295      }
296      if (iBest>=0) {
297        /*printf("Infeasibility of %g on row %d cost %g\n",
298          thisInfeasibility,i,addCost);*/
299        newSolution[iBest]=newValue;
300        thisInfeasibility=0.0;
301        newSolutionValue += addCost;
302        rowActivity[i] += changeRowActivity;
303      }
304      penalty += fabs(thisInfeasibility);
305    }
306  }
307  if (penalty) {
308    // see if feasible using any
309    // first continuous
310    double penaltyChange=0.0;
311    int iColumn;
312    for (iColumn=0;iColumn<numberColumns;iColumn++) {
313      if (solver->isInteger(iColumn))
314        continue;
315      double currentValue = newSolution[iColumn];
316      double lowerValue = lower[iColumn];
317      double upperValue = upper[iColumn];
318      int j;
319      int anyBadDown=0;
320      int anyBadUp=0;
321      double upImprovement=0.0;
322      double downImprovement=0.0;
323      for (j=columnStart[iColumn];
324           j<columnStart[iColumn]+columnLength[iColumn];j++) {
325        int iRow = row[j];
326        if (rowUpper[iRow]>rowLower[iRow]) {
327          double value = element[j];
328          if (rowActivity[iRow]>rowUpper[iRow]+primalTolerance) {
329            // infeasible above
330            downImprovement += value;
331            upImprovement -= value;
332            if (value>0.0) 
333              anyBadUp++;
334            else 
335              anyBadDown++;
336          } else if (rowActivity[iRow]>rowUpper[iRow]-primalTolerance) {
337            // feasible at ub
338            if (value>0.0) {
339              upImprovement -= value;
340              anyBadUp++;
341            } else {
342              downImprovement += value;
343              anyBadDown++;
344            }
345          } else if (rowActivity[iRow]>rowLower[iRow]+primalTolerance) {
346            // feasible in interior
347          } else if (rowActivity[iRow]>rowLower[iRow]-primalTolerance) {
348            // feasible at lb
349            if (value<0.0) {
350              upImprovement += value;
351              anyBadUp++;
352            } else {
353              downImprovement -= value;
354              anyBadDown++;
355            }
356          } else {
357            // infeasible below
358            downImprovement -= value;
359            upImprovement += value;
360            if (value<0.0) 
361              anyBadUp++;
362            else 
363              anyBadDown++;
364          }
365        } else {
366          // equality row
367          double value = element[j];
368          if (rowActivity[iRow]>rowUpper[iRow]+primalTolerance) {
369            // infeasible above
370            downImprovement += value;
371            upImprovement -= value;
372            if (value>0.0) 
373              anyBadUp++;
374            else 
375              anyBadDown++;
376          } else if (rowActivity[iRow]<rowLower[iRow]-primalTolerance) {
377            // infeasible below
378            downImprovement -= value;
379            upImprovement += value;
380            if (value<0.0) 
381              anyBadUp++;
382            else 
383              anyBadDown++;
384          } else {
385            // feasible - no good
386            anyBadUp=-1;
387            break;
388          }
389        }
390      }
391      // could change tests for anyBad
392      if (anyBadUp)
393        upImprovement=0.0;
394      if (anyBadDown)
395        downImprovement=0.0;
396      double way=0.0;
397      double improvement=0.0;
398      if (downImprovement>0.0&&currentValue>lowerValue) {
399        way=-1.0;
400        improvement = downImprovement;
401      } else if (upImprovement>0.0&&currentValue<upperValue) {
402        way=1.0;
403        improvement = upImprovement;
404      }
405      if (way) {
406        // can improve
407        double distance=COIN_DBL_MAX;
408        for (j=columnStart[iColumn];
409             j<columnStart[iColumn]+columnLength[iColumn];j++) {
410          int iRow = row[j];
411          double value = element[j]*way;
412          if (rowActivity[iRow]>rowUpper[iRow]+primalTolerance) {
413            // infeasible above
414            assert (value<0.0);
415            double gap = rowActivity[iRow]-rowUpper[iRow];
416            if (gap+value*distance<0.0) 
417              distance = -gap/value;
418          } else if (rowActivity[iRow]<rowLower[iRow]-primalTolerance) {
419            // infeasible below
420            assert (value>0.0);
421            double gap = rowActivity[iRow]-rowLower[iRow];
422            if (gap+value*distance>0.0) 
423              distance = -gap/value;
424          } else {
425            // feasible
426            if (value>0) {
427              double gap = rowActivity[iRow]-rowUpper[iRow];
428              if (gap+value*distance>0.0) 
429              distance = -gap/value;
430            } else {
431              double gap = rowActivity[iRow]-rowLower[iRow];
432              if (gap+value*distance<0.0) 
433                distance = -gap/value;
434            }
435          }
436        }
437        //move
438        penaltyChange += improvement*distance;
439        distance *= way;
440        newSolution[iColumn] += distance;
441        newSolutionValue += direction*objective[iColumn]*distance;
442        for (j=columnStart[iColumn];
443             j<columnStart[iColumn]+columnLength[iColumn];j++) {
444          int iRow = row[j];
445          double value = element[j];
446          rowActivity[iRow] += distance*value;
447        }
448      }
449    }
450    // and now all if improving
451    double lastChange= penaltyChange ? 1.0 : 0.0;
452    while (lastChange>1.0e-2) {
453      lastChange=0;
454      for (iColumn=0;iColumn<numberColumns;iColumn++) {
455        bool isInteger = solver->isInteger(iColumn);
456        double currentValue = newSolution[iColumn];
457        double lowerValue = lower[iColumn];
458        double upperValue = upper[iColumn];
459        int j;
460        int anyBadDown=0;
461        int anyBadUp=0;
462        double upImprovement=0.0;
463        double downImprovement=0.0;
464        for (j=columnStart[iColumn];
465             j<columnStart[iColumn]+columnLength[iColumn];j++) {
466          int iRow = row[j];
467          double value = element[j];
468          if (isInteger) {
469            if (value>0.0) {
470              if (rowActivity[iRow]+value>rowUpper[iRow]+primalTolerance)
471                anyBadUp++;
472              if (rowActivity[iRow]-value<rowLower[iRow]-primalTolerance)
473                anyBadDown++;
474            } else {
475              if (rowActivity[iRow]-value>rowUpper[iRow]+primalTolerance)
476                anyBadDown++;
477              if (rowActivity[iRow]+value<rowLower[iRow]-primalTolerance)
478                anyBadUp++;
479            }
480          }
481          if (rowUpper[iRow]>rowLower[iRow]) {
482            if (rowActivity[iRow]>rowUpper[iRow]+primalTolerance) {
483              // infeasible above
484              downImprovement += value;
485              upImprovement -= value;
486              if (value>0.0) 
487                anyBadUp++;
488              else 
489                anyBadDown++;
490            } else if (rowActivity[iRow]>rowUpper[iRow]-primalTolerance) {
491              // feasible at ub
492              if (value>0.0) {
493                upImprovement -= value;
494                anyBadUp++;
495              } else {
496                downImprovement += value;
497                anyBadDown++;
498              }
499            } else if (rowActivity[iRow]>rowLower[iRow]+primalTolerance) {
500              // feasible in interior
501            } else if (rowActivity[iRow]>rowLower[iRow]-primalTolerance) {
502              // feasible at lb
503              if (value<0.0) {
504                upImprovement += value;
505                anyBadUp++;
506              } else {
507                downImprovement -= value;
508                anyBadDown++;
509              }
510            } else {
511              // infeasible below
512              downImprovement -= value;
513              upImprovement += value;
514              if (value<0.0) 
515                anyBadUp++;
516              else 
517                anyBadDown++;
518            }
519          } else {
520            // equality row
521            if (rowActivity[iRow]>rowUpper[iRow]+primalTolerance) {
522              // infeasible above
523              downImprovement += value;
524              upImprovement -= value;
525              if (value>0.0) 
526                anyBadUp++;
527              else 
528                anyBadDown++;
529            } else if (rowActivity[iRow]<rowLower[iRow]-primalTolerance) {
530              // infeasible below
531              downImprovement -= value;
532              upImprovement += value;
533              if (value<0.0) 
534                anyBadUp++;
535              else 
536                anyBadDown++;
537            } else {
538              // feasible - no good
539              anyBadUp=-1;
540              anyBadDown=-1;
541              break;
542            }
543          }
544        }
545        // could change tests for anyBad
546        if (anyBadUp)
547          upImprovement=0.0;
548        if (anyBadDown)
549          downImprovement=0.0;
550        double way=0.0;
551        double improvement=0.0;
552        if (downImprovement>0.0&&currentValue>lowerValue) {
553          way=-1.0;
554          improvement = downImprovement;
555        } else if (upImprovement>0.0&&currentValue<upperValue) {
556          way=1.0;
557          improvement = upImprovement;
558        }
559        if (way) {
560          // can improve
561          double distance=COIN_DBL_MAX;
562          for (j=columnStart[iColumn];
563               j<columnStart[iColumn]+columnLength[iColumn];j++) {
564            int iRow = row[j];
565            double value = element[j]*way;
566            if (rowActivity[iRow]>rowUpper[iRow]+primalTolerance) {
567              // infeasible above
568              assert (value<0.0);
569              double gap = rowActivity[iRow]-rowUpper[iRow];
570              if (gap+value*distance<0.0) {
571                // If integer then has to move by 1
572                if (!isInteger)
573                  distance = -gap/value;
574                else
575                  distance = CoinMax(-gap/value,1.0);
576              }
577            } else if (rowActivity[iRow]<rowLower[iRow]-primalTolerance) {
578              // infeasible below
579              assert (value>0.0);
580              double gap = rowActivity[iRow]-rowLower[iRow];
581              if (gap+value*distance>0.0) {
582                // If integer then has to move by 1
583                if (!isInteger)
584                  distance = -gap/value;
585                else
586                  distance = CoinMax(-gap/value,1.0);
587              }
588            } else {
589              // feasible
590              if (value>0) {
591                double gap = rowActivity[iRow]-rowUpper[iRow];
592                if (gap+value*distance>0.0) 
593                  distance = -gap/value;
594              } else {
595                double gap = rowActivity[iRow]-rowLower[iRow];
596                if (gap+value*distance<0.0) 
597                  distance = -gap/value;
598              }
599            }
600          }
601          if (isInteger)
602            distance = floor(distance+1.0e-8);
603          if (!distance) {
604            // should never happen
605            printf("zero distance in CbcRounding - debug\n");
606          }
607          //move
608          lastChange += improvement*distance;
609          distance *= way;
610          newSolution[iColumn] += distance;
611          newSolutionValue += direction*objective[iColumn]*distance;
612          for (j=columnStart[iColumn];
613               j<columnStart[iColumn]+columnLength[iColumn];j++) {
614            int iRow = row[j];
615            double value = element[j];
616            rowActivity[iRow] += distance*value;
617          }
618        }
619      }
620      penaltyChange += lastChange;
621    }
622    penalty -= penaltyChange;
623    if (penalty<1.0e-5*fabs(penaltyChange)) {
624      // recompute
625      penalty=0.0;
626      for (i=0;i<numberRows;i++) {
627        double value = rowActivity[i];
628        if (value<rowLower[i]-primalTolerance)
629          penalty += rowLower[i]-value;
630        else if (value>rowUpper[i]+primalTolerance)
631          penalty += value-rowUpper[i];
632      }
633    }
634  }
635
636  // Could also set SOS (using random) and repeat
637  if (!penalty) {
638    // See if we can do better
639    //seed_++;
640    //CoinSeedRandom(seed_);
641    // Random number between 0 and 1.
642    double randomNumber = CoinDrand48();
643    int iPass;
644    int start[2];
645    int end[2];
646    int iRandom = (int) (randomNumber*((double) numberIntegers));
647    start[0]=iRandom;
648    end[0]=numberIntegers;
649    start[1]=0;
650    end[1]=iRandom;
651    for (iPass=0;iPass<2;iPass++) {
652      int i;
653      for (i=start[iPass];i<end[iPass];i++) {
654        int iColumn = integerVariable[i];
655        double value=newSolution[iColumn];
656        assert (fabs(floor(value+0.5)-value)<integerTolerance);
657        double cost = direction * objective[iColumn];
658        double move=0.0;
659        if (cost>0.0)
660          move = -1.0;
661        else if (cost<0.0)
662          move=1.0;
663        while (move) {
664          bool good=true;
665          double newValue=newSolution[iColumn]+move;
666          if (newValue<lower[iColumn]-primalTolerance||
667              newValue>upper[iColumn]+primalTolerance) {
668            move=0.0;
669          } else {
670            // see if we can move
671            int j;
672            for (j=columnStart[iColumn];
673                 j<columnStart[iColumn]+columnLength[iColumn];j++) {
674              int iRow = row[j];
675              double newActivity = rowActivity[iRow] + move*element[j];
676              if (newActivity<rowLower[iRow]-primalTolerance||
677                  newActivity>rowUpper[iRow]+primalTolerance) {
678                good=false;
679                break;
680              }
681            }
682            if (good) {
683              newSolution[iColumn] = newValue;
684              newSolutionValue += move*cost;
685              int j;
686              for (j=columnStart[iColumn];
687                   j<columnStart[iColumn]+columnLength[iColumn];j++) {
688                int iRow = row[j];
689                rowActivity[iRow] += move*element[j];
690              }
691            } else {
692              move=0.0;
693            }
694          }
695        }
696      }
697    }
698    if (newSolutionValue<solutionValue) {
699      // paranoid check
700      memset(rowActivity,0,numberRows*sizeof(double));
701      for (i=0;i<numberColumns;i++) {
702        int j;
703        double value = newSolution[i];
704        if (value) {
705          for (j=columnStart[i];
706               j<columnStart[i]+columnLength[i];j++) {
707            int iRow=row[j];
708            rowActivity[iRow] += value*element[j];
709          }
710        }
711      }
712      // check was approximately feasible
713      bool feasible=true;
714      for (i=0;i<numberRows;i++) {
715        if(rowActivity[i]<rowLower[i]) {
716          if (rowActivity[i]<rowLower[i]-1000.0*primalTolerance)
717            feasible = false;
718        } else if(rowActivity[i]>rowUpper[i]) {
719          if (rowActivity[i]>rowUpper[i]+1000.0*primalTolerance)
720            feasible = false;
721        }
722      }
723      if (feasible) {
724        // new solution
725        memcpy(betterSolution,newSolution,numberColumns*sizeof(double));
726        solutionValue = newSolutionValue;
727        //printf("** Solution of %g found by rounding\n",newSolutionValue);
728        returnCode=1;
729      } else {
730        // Can easily happen
731        //printf("Debug CbcRounding giving bad solution\n");
732      }
733    }
734  }
735  delete [] newSolution;
736  delete [] rowActivity;
737  return returnCode;
738}
739// update model
740void CbcRounding::setModel(CbcModel * model)
741{
742  model_ = model;
743  // Get a copy of original matrix (and by row for rounding);
744  assert(model_->solver());
745  matrix_ = *model_->solver()->getMatrixByCol();
746  matrixByRow_ = *model_->solver()->getMatrixByRow();
747  // make sure model okay for heuristic
748  validate();
749}
750// Validate model i.e. sets when_ to 0 if necessary (may be NULL)
751void 
752CbcRounding::validate() 
753{
754  if (model_&&when()<10) {
755    if (model_->numberIntegers()!=
756        model_->numberObjects())
757      setWhen(0);
758  }
759}
760
761 
Note: See TracBrowser for help on using the repository browser.