source: branches/devel/Cbc/src/CbcHeuristicFPump.cpp @ 439

Last change on this file since 439 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: 21.3 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
11#include "OsiSolverInterface.hpp"
12#include "CbcModel.hpp"
13#include "CbcMessage.hpp"
14#include "CbcHeuristicFPump.hpp"
15#include "CbcBranchActual.hpp"
16#include "CoinHelperFunctions.hpp"
17#include "CoinTime.hpp"
18
19
20// Default Constructor
21CbcHeuristicFPump::CbcHeuristicFPump() 
22  :CbcHeuristic(),
23   startTime_(0.0),
24   maximumTime_(0.0),
25   downValue_(0.5),
26   fakeCutoff_(COIN_DBL_MAX),
27   absoluteIncrement_(0.0),
28   relativeIncrement_(0.0),
29   maximumPasses_(100),
30   maximumRetries_(1),
31   roundExpensive_(false)
32{
33  setWhen(1);
34}
35
36// Constructor from model
37CbcHeuristicFPump::CbcHeuristicFPump(CbcModel & model,
38                                     double downValue,bool roundExpensive)
39  :CbcHeuristic(model),
40   startTime_(0.0),
41   maximumTime_(0.0),
42   downValue_(downValue),
43   fakeCutoff_(COIN_DBL_MAX),
44   absoluteIncrement_(0.0),
45   relativeIncrement_(0.0),
46   maximumPasses_(100),
47   maximumRetries_(1),
48   roundExpensive_(roundExpensive)
49{
50  setWhen(1);
51}
52
53// Destructor
54CbcHeuristicFPump::~CbcHeuristicFPump ()
55{
56}
57
58// Clone
59CbcHeuristic *
60CbcHeuristicFPump::clone() const
61{
62  return new CbcHeuristicFPump(*this);
63}
64// Create C++ lines to get to current state
65void 
66CbcHeuristicFPump::generateCpp( FILE * fp) 
67{
68  CbcHeuristicFPump other;
69  fprintf(fp,"0#include \"CbcHeuristicFPump.hpp\"\n");
70  fprintf(fp,"3  CbcHeuristicFPump heuristicFPump(*cbcModel);\n");
71  if (maximumPasses_!=other.maximumPasses_)
72    fprintf(fp,"3  heuristicFPump.setMaximumPasses(%d);\n",maximumPasses_);
73  else
74    fprintf(fp,"4  heuristicFPump.setMaximumPasses(%d);\n",maximumPasses_);
75  if (maximumRetries_!=other.maximumRetries_)
76    fprintf(fp,"3  heuristicFPump.setMaximumRetries(%d);\n",maximumRetries_);
77  else
78    fprintf(fp,"4  heuristicFPump.setMaximumRetries(%d);\n",maximumRetries_);
79  if (maximumTime_!=other.maximumTime_)
80    fprintf(fp,"3  heuristicFPump.setMaximumTime(%g);\n",maximumTime_);
81  else
82    fprintf(fp,"4  heuristicFPump.setMaximumTime(%g);\n",maximumTime_);
83  if (fakeCutoff_!=other.fakeCutoff_)
84    fprintf(fp,"3  heuristicFPump.setFakeCutoff(%g);\n",fakeCutoff_);
85  else
86    fprintf(fp,"4  heuristicFPump.setFakeCutoff(%g);\n",fakeCutoff_);
87  if (absoluteIncrement_!=other.absoluteIncrement_)
88    fprintf(fp,"3  heuristicFPump.setAbsoluteIncrement(%g);\n",absoluteIncrement_);
89  else
90    fprintf(fp,"4  heuristicFPump.setAbsoluteIncrement(%g);\n",absoluteIncrement_);
91  if (relativeIncrement_!=other.relativeIncrement_)
92    fprintf(fp,"3  heuristicFPump.setRelativeIncrement(%g);\n",relativeIncrement_);
93  else
94    fprintf(fp,"4  heuristicFPump.setRelativeIncrement(%g);\n",relativeIncrement_);
95  fprintf(fp,"3  cbcModel->addHeuristic(&heuristicFPump);\n");
96}
97
98// Copy constructor
99CbcHeuristicFPump::CbcHeuristicFPump(const CbcHeuristicFPump & rhs)
100:
101  CbcHeuristic(rhs),
102  startTime_(rhs.startTime_),
103  maximumTime_(rhs.maximumTime_),
104  downValue_(rhs.downValue_),
105  fakeCutoff_(rhs.fakeCutoff_),
106  absoluteIncrement_(rhs.absoluteIncrement_),
107  relativeIncrement_(rhs.relativeIncrement_),
108  maximumPasses_(rhs.maximumPasses_),
109  maximumRetries_(rhs.maximumRetries_),
110  roundExpensive_(rhs.roundExpensive_)
111{
112  setWhen(rhs.when());
113}
114// Resets stuff if model changes
115void 
116CbcHeuristicFPump::resetModel(CbcModel * model)
117{
118}
119
120/**************************BEGIN MAIN PROCEDURE ***********************************/
121
122// See if feasibility pump will give better solution
123// Sets value of solution
124// Returns 1 if solution, 0 if not
125int
126CbcHeuristicFPump::solution(double & solutionValue,
127                         double * betterSolution)
128{
129  if (!when()||(when()==1&&model_->phase()!=1))
130    return 0; // switched off
131  // See if at root node
132  bool atRoot = model_->getNodeCount()==0;
133  int passNumber = model_->getCurrentPassNumber();
134  // just do once
135  if (!atRoot||passNumber!=1)
136    return 0;
137  // probably a good idea
138  if (model_->getSolutionCount()) return 0;
139  // loop round doing repeated pumps
140  double cutoff;
141  model_->solver()->getDblParam(OsiDualObjectiveLimit,cutoff);
142  double direction = model_->solver()->getObjSense();
143  cutoff *= direction;
144  cutoff = CoinMin(cutoff,solutionValue);
145  // space for rounded solution
146  int numberColumns = model_->getNumCols();
147  double * newSolution = new double [numberColumns];
148  double newSolutionValue=COIN_DBL_MAX;
149  bool solutionFound=false;
150  char * usedColumn = NULL;
151  double * lastSolution=NULL;
152  bool fixContinuous=false;
153  bool fixInternal=false;
154  if (when_>=11&&when_<=13) {
155    fixInternal = when_ >11;
156    fixContinuous = when_==13;
157    when_=1;
158    usedColumn = new char [numberColumns];
159    memset(usedColumn,0,numberColumns);
160    model_->solver()->resolve();
161    assert (model_->solver()->isProvenOptimal());
162    lastSolution = CoinCopyOfArray(model_->solver()->getColSolution(),numberColumns);
163  }
164  int finalReturnCode=0;
165  int totalNumberPasses=0;
166  int numberTries=0;
167  while (true) {
168    int numberPasses=0;
169    numberTries++;
170    // Clone solver - otherwise annoys root node computations
171    OsiSolverInterface * solver = model_->solver()->clone();
172    // if cutoff exists then add constraint
173    if (fabs(cutoff)<1.0e20&&(fakeCutoff_!=COIN_DBL_MAX||numberTries>1)) {
174      cutoff = CoinMin(cutoff,fakeCutoff_);
175      const double * objective = solver->getObjCoefficients();
176      int numberColumns = solver->getNumCols();
177      int * which = new int[numberColumns];
178      double * els = new double[numberColumns];
179      int nel=0;
180      for (int i=0;i<numberColumns;i++) {
181        double value = objective[i];
182        if (value) {
183          which[nel]=i;
184          els[nel++] = direction*value;
185        }
186      }
187      solver->addRow(nel,which,els,-COIN_DBL_MAX,cutoff);
188      delete [] which;
189      delete [] els;
190    }
191    solver->setDblParam(OsiDualObjectiveLimit,1.0e50);
192    solver->resolve();
193    // Solver may not be feasible
194    if (!solver->isProvenOptimal()) {
195      break;
196    }
197    const double * lower = solver->getColLower();
198    const double * upper = solver->getColUpper();
199    const double * solution = solver->getColSolution();
200    if (lastSolution)
201      memcpy(lastSolution,solution,numberColumns*sizeof(double));
202    double primalTolerance;
203    solver->getDblParam(OsiPrimalTolerance,primalTolerance);
204   
205    int numberIntegers = model_->numberIntegers();
206    const int * integerVariable = model_->integerVariable();
207
208    // 1. initially check 0-1
209    int i,j;
210    int general=0;
211    for (i=0;i<numberIntegers;i++) {
212      int iColumn = integerVariable[i];
213#ifndef NDEBUG
214      const OsiObject * object = model_->object(i);
215      const CbcSimpleInteger * integerObject = 
216        dynamic_cast<const  CbcSimpleInteger *> (object);
217      const OsiSimpleInteger * integerObject2 = 
218        dynamic_cast<const  OsiSimpleInteger *> (object);
219      assert(integerObject||integerObject2);
220#endif
221      if (upper[iColumn]-lower[iColumn]>1.000001) {
222        general++;
223        break;
224      }
225    }
226    if (general*3>numberIntegers) {
227      delete solver;
228      return 0;
229    }
230   
231    // 2 space for last rounded solutions
232#define NUMBER_OLD 4
233    double ** oldSolution = new double * [NUMBER_OLD];
234    for (j=0;j<NUMBER_OLD;j++) {
235      oldSolution[j]= new double[numberColumns];
236      for (i=0;i<numberColumns;i++) oldSolution[j][i]=-COIN_DBL_MAX;
237    }
238   
239    // 3. Replace objective with an initial 0-valued objective
240    double * saveObjective = new double [numberColumns];
241    memcpy(saveObjective,solver->getObjCoefficients(),numberColumns*sizeof(double));
242    for (i=0;i<numberColumns;i++) {
243      solver->setObjCoeff(i,0.0);
244    }
245    bool finished=false;
246    double direction = solver->getObjSense();
247    int returnCode=0;
248    bool takeHint;
249    OsiHintStrength strength;
250    solver->getHintParam(OsiDoDualInResolve,takeHint,strength);
251    solver->setHintParam(OsiDoDualInResolve,false);
252    solver->messageHandler()->setLogLevel(0);
253   
254    // 4. Save objective offset so we can see progress
255    double saveOffset;
256    solver->getDblParam(OsiObjOffset,saveOffset);
257   
258    // 5. MAIN WHILE LOOP
259    bool newLineNeeded=false;
260    while (!finished) {
261      returnCode=0;
262      // see what changed
263      if (usedColumn) {
264        for (i=0;i<numberColumns;i++) {
265          if (fabs(solution[i]-lastSolution[i])>1.0e-8) 
266            usedColumn[i]=1;
267          lastSolution[i]=solution[i];
268        }
269      }
270      if (numberPasses>=maximumPasses_) {
271        break;
272      }
273      if (maximumTime_>0.0&&CoinCpuTime()>=startTime_+maximumTime_) break;
274      numberPasses++;
275      memcpy(newSolution,solution,numberColumns*sizeof(double));
276      int flip;
277      returnCode = rounds(newSolution,saveObjective,roundExpensive_,downValue_,&flip);
278      if (returnCode) {
279        // SOLUTION IS INTEGER
280        // Put back correct objective
281        for (i=0;i<numberColumns;i++)
282          solver->setObjCoeff(i,saveObjective[i]);
283
284        // solution - but may not be better
285        // Compute using dot product
286        solver->setDblParam(OsiObjOffset,saveOffset);
287        newSolutionValue = -saveOffset;
288        for (  i=0 ; i<numberColumns ; i++ )
289          newSolutionValue += saveObjective[i]*newSolution[i];
290        newSolutionValue *= direction;
291        if (model_->logLevel())
292          printf(" - solution found of %g",newSolutionValue);
293        newLineNeeded=false;
294        if (newSolutionValue<solutionValue) {
295          double saveValue = newSolutionValue;
296          if (general) {
297            int numberLeft=0;
298            for (i=0;i<numberIntegers;i++) {
299              int iColumn = integerVariable[i];
300              double value = floor(newSolution[iColumn]+0.5);
301              if(solver->isBinary(iColumn)) {
302                solver->setColLower(iColumn,value);
303                solver->setColUpper(iColumn,value);
304              } else {
305                if (fabs(value-newSolution[iColumn])>1.0e-7) 
306                  numberLeft++;
307              }
308            }
309            if (numberLeft) {
310              returnCode = smallBranchAndBound(solver,200,newSolution,newSolutionValue,
311                                               solutionValue,"CbcHeuristicFpump");
312            }
313          }
314          if (returnCode) {
315            memcpy(betterSolution,newSolution,numberColumns*sizeof(double));
316            solutionValue=newSolutionValue;
317            solutionFound=true;
318            if (general&&saveValue!=newSolutionValue)
319              printf(" - cleaned solution of %g\n",solutionValue);
320            else
321              printf("\n");
322          } else {
323          if (model_->logLevel()) 
324            printf(" - not good enough after small branch and bound\n");
325          }
326        } else {
327          if (model_->logLevel()) 
328            printf(" - not good enough\n");
329          newLineNeeded=false;
330          returnCode=0;
331        }     
332        break;
333      } else {
334        // SOLUTION IS not INTEGER
335        // 1. check for loop
336        bool matched;
337        for (int k = NUMBER_OLD-1; k > 0; k--) {
338          double * b = oldSolution[k];
339          matched = true;
340          for (i = 0; i <numberIntegers; i++) {
341            int iColumn = integerVariable[i];
342            if(!solver->isBinary(iColumn))
343              continue;
344            if (newSolution[iColumn]!=b[iColumn]) {
345              matched=false;
346              break;
347            }
348          }
349          if (matched) break;
350        }
351        if (matched || numberPasses%100 == 0) {
352          // perturbation
353          if (model_->logLevel())
354            printf("Perturbation applied");
355          newLineNeeded=true;
356          for (i=0;i<numberIntegers;i++) {
357            int iColumn = integerVariable[i];
358            if(!solver->isBinary(iColumn))
359              continue;
360            double value = max(0.0,CoinDrand48()-0.3);
361            double difference = fabs(solution[iColumn]-newSolution[iColumn]);
362            if (difference+value>0.5) {
363              if (newSolution[iColumn]<lower[iColumn]+primalTolerance) newSolution[iColumn] += 1.0;
364              else if (newSolution[iColumn]>upper[iColumn]-primalTolerance) newSolution[iColumn] -= 1.0;
365              else abort();
366            }
367          }
368        } else {
369          for (j=NUMBER_OLD-1;j>0;j--) {
370            for (i = 0; i < numberColumns; i++) oldSolution[j][i]=oldSolution[j-1][i];
371          }
372          for (j = 0; j < numberColumns; j++) oldSolution[0][j] = newSolution[j];
373        }
374       
375        // 2. update the objective function based on the new rounded solution
376        double offset=0.0;
377        for (i=0;i<numberIntegers;i++) {
378          int iColumn = integerVariable[i];
379          if(!solver->isBinary(iColumn))
380            continue;
381          double costValue = 1.0;
382          // deal with fixed variables (i.e., upper=lower)
383          if (fabs(lower[iColumn]-upper[iColumn]) < primalTolerance) {
384            if (lower[iColumn] > 1. - primalTolerance) solver->setObjCoeff(iColumn,-costValue);
385            else                                       solver->setObjCoeff(iColumn,costValue);
386            continue;
387          }
388          if (newSolution[iColumn]<lower[iColumn]+primalTolerance) {
389            solver->setObjCoeff(iColumn,costValue);
390          } else {
391            if (newSolution[iColumn]>upper[iColumn]-primalTolerance) {
392              solver->setObjCoeff(iColumn,-costValue);
393            } else {
394              abort();
395            }
396          }
397          offset += costValue*newSolution[iColumn];
398        }
399        solver->setDblParam(OsiObjOffset,-offset);
400        if (!general&false) {
401          // Solve in two goes - first keep satisfied ones fixed
402          double * saveLower = new double [numberIntegers];
403          double * saveUpper = new double [numberIntegers];
404          for (i=0;i<numberIntegers;i++) {
405            int iColumn = integerVariable[i];
406            saveLower[i]=COIN_DBL_MAX;
407            saveUpper[i]=-COIN_DBL_MAX;
408            if (solution[iColumn]<lower[iColumn]+primalTolerance) {
409              saveUpper[i]=upper[iColumn];
410              solver->setColUpper(iColumn,lower[iColumn]);
411            } else if (solution[iColumn]>upper[iColumn]-primalTolerance) {
412              saveLower[i]=lower[iColumn];
413              solver->setColLower(iColumn,upper[iColumn]);
414            }
415          }
416          solver->resolve();
417          assert (solver->isProvenOptimal());
418          for (i=0;i<numberIntegers;i++) {
419            int iColumn = integerVariable[i];
420            if (saveLower[i]!=COIN_DBL_MAX)
421              solver->setColLower(iColumn,saveLower[i]);
422            if (saveUpper[i]!=-COIN_DBL_MAX)
423              solver->setColUpper(iColumn,saveUpper[i]);
424            saveUpper[i]=-COIN_DBL_MAX;
425          }
426          memcpy(newSolution,solution,numberColumns*sizeof(double));
427          int flip;
428          returnCode = rounds(newSolution,saveObjective,roundExpensive_,downValue_,&flip);
429          if (returnCode) {
430            // solution - but may not be better
431            // Compute using dot product
432            double newSolutionValue = -saveOffset;
433            for (  i=0 ; i<numberColumns ; i++ )
434              newSolutionValue += saveObjective[i]*newSolution[i];
435            newSolutionValue *= direction;
436            if (model_->logLevel())
437              printf(" - intermediate solution found of %g",newSolutionValue);
438            if (newSolutionValue<solutionValue) {
439              memcpy(betterSolution,newSolution,numberColumns*sizeof(double));
440              solutionValue=newSolutionValue;
441              solutionFound=true;
442            } else {
443              returnCode=0;
444            }
445          }     
446        }
447        solver->resolve();
448        assert (solver->isProvenOptimal());
449        if (model_->logLevel())
450          printf("\npass %3d: obj. %10.5f --> ", numberPasses+totalNumberPasses,solver->getObjValue());
451        newLineNeeded=true;
452       
453      }
454    } // END WHILE
455    if (newLineNeeded&&model_->logLevel())
456      printf(" - no solution found\n");
457    delete solver;
458    for ( j=0;j<NUMBER_OLD;j++) 
459      delete [] oldSolution[j];
460    delete [] oldSolution;
461    delete [] saveObjective;
462    if (usedColumn) {
463      OsiSolverInterface * newSolver = model_->continuousSolver()->clone();
464      const double * colLower = newSolver->getColLower();
465      const double * colUpper = newSolver->getColUpper();
466      int i;
467      int nFix=0;
468      int nFixI=0;
469      int nFixC=0;
470      for (i=0;i<numberIntegers;i++) {
471        int iColumn=integerVariable[i];
472        const OsiObject * object = model_->object(i);
473        double originalLower;
474        double originalUpper;
475        getIntegerInformation( object,originalLower, originalUpper); 
476        assert(colLower[iColumn]==originalLower);
477        newSolver->setColLower(iColumn,CoinMax(colLower[iColumn],originalLower));
478        assert(colUpper[iColumn]==originalUpper);
479        newSolver->setColUpper(iColumn,CoinMin(colUpper[iColumn],originalUpper));
480        if (!usedColumn[iColumn]) {
481          double value=lastSolution[iColumn];
482          double nearest = floor(value+0.5);
483          if (fabs(value-nearest)<1.0e-7) {
484            if (nearest==colLower[iColumn]) {
485              newSolver->setColUpper(iColumn,colLower[iColumn]);
486              nFix++;
487            } else if (nearest==colUpper[iColumn]) {
488              newSolver->setColLower(iColumn,colUpper[iColumn]);
489              nFix++;
490            } else if (fixInternal) {
491              newSolver->setColLower(iColumn,nearest);
492              newSolver->setColUpper(iColumn,nearest);
493              nFix++;
494              nFixI++;
495            }
496          }
497        }
498      }
499      if (fixContinuous) {
500        for (int iColumn=0;iColumn<numberColumns;iColumn++) {
501          if (!newSolver->isInteger(iColumn)&&!usedColumn[iColumn]) {
502            double value=lastSolution[iColumn];
503            if (value<colLower[iColumn]+1.0e-8) {
504              newSolver->setColUpper(iColumn,colLower[iColumn]);
505              nFixC++;
506            } else if (value>colUpper[iColumn]-1.0e-8) {
507              newSolver->setColLower(iColumn,colUpper[iColumn]);
508              nFixC++;
509            }
510          }
511        }
512      }
513      newSolver->initialSolve();
514      if (!newSolver->isProvenOptimal()) {
515        newSolver->writeMps("bad.mps");
516        assert (newSolver->isProvenOptimal());
517        break;
518      }
519      printf("%d integers at bound fixed (of which %d were internal) and %d continuous\n",
520             nFix,nFixI,nFixC);
521      double saveValue = newSolutionValue;
522      returnCode = smallBranchAndBound(newSolver,200,newSolution,newSolutionValue,
523                                       newSolutionValue,"CbcHeuristicLocalAfterFPump");
524      if (returnCode) {
525        printf("old sol of %g new of %g\n",saveValue,newSolutionValue);
526        memcpy(betterSolution,newSolution,numberColumns*sizeof(double));
527        solutionValue=newSolutionValue;
528        solutionFound=true;
529      }
530      delete newSolver;
531    }
532    if (solutionFound) finalReturnCode=1;
533    cutoff = CoinMin(cutoff,solutionValue);
534    if (numberTries>=CoinAbs(maximumRetries_)||!solutionFound) {
535      break;
536    } else if (absoluteIncrement_>0.0||relativeIncrement_>0.0) {
537      solutionFound=false;
538      double gap = relativeIncrement_*fabs(solutionValue);
539      cutoff -= CoinMax(CoinMax(gap,absoluteIncrement_),model_->getCutoffIncrement());
540      printf("round again with cutoff of %g\n",cutoff);
541      if (maximumRetries_<0)
542        memset(usedColumn,0,numberColumns);
543      totalNumberPasses += numberPasses;
544    } else {
545      break;
546    }
547  }
548  delete [] usedColumn;
549  delete [] lastSolution;
550  delete [] newSolution;
551  return finalReturnCode;
552}
553
554/**************************END MAIN PROCEDURE ***********************************/
555
556// update model
557void CbcHeuristicFPump::setModel(CbcModel * model)
558{
559  model_ = model;
560}
561
562/* Rounds solution - down if < downValue
563   returns 1 if current is a feasible solution
564*/
565int 
566CbcHeuristicFPump::rounds(double * solution,
567                          const double * objective,
568                          bool roundExpensive, double downValue, int *flip)
569{
570  OsiSolverInterface * solver = model_->solver();
571  double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);
572  double primalTolerance ;
573  solver->getDblParam(OsiPrimalTolerance,primalTolerance) ;
574  int numberIntegers = model_->numberIntegers();
575  const int * integerVariable = model_->integerVariable();
576
577  int i;
578
579  static int iter = 0;
580  int numberColumns = model_->getNumCols();
581  // tmp contains the current obj coefficients
582  double * tmp = new double [numberColumns];
583  memcpy(tmp,solver->getObjCoefficients(),numberColumns*sizeof(double));
584  int flip_up = 0;
585  int flip_down  = 0;
586  double  v = CoinDrand48() * 20;
587  int nn = 10 + (int) v;
588  int nnv = 0;
589  int * list = new int [nn];
590  double * val = new double [nn];
591  for (i = 0; i < nn; i++) val[i] = .001;
592
593  // return rounded solution
594  for (i=0;i<numberIntegers;i++) {
595    int iColumn = integerVariable[i];
596    if(!solver->isBinary(iColumn))
597      continue;
598#ifndef NDEBUG
599      const OsiObject * object = model_->object(i);
600      const CbcSimpleInteger * integerObject = 
601        dynamic_cast<const  CbcSimpleInteger *> (object);
602      const OsiSimpleInteger * integerObject2 = 
603        dynamic_cast<const  OsiSimpleInteger *> (object);
604      assert(integerObject||integerObject2);
605#endif
606    double value=solution[iColumn];
607    double round = floor(value+primalTolerance);
608    if (value-round > .5) round += 1.;
609    if (round < integerTolerance && tmp[iColumn] < -1. + integerTolerance) flip_down++;
610    if (round > 1. - integerTolerance && tmp[iColumn] > 1. - integerTolerance) flip_up++;
611    if (flip_up + flip_down == 0) { 
612       for (int k = 0; k < nn; k++) {
613           if (fabs(value-round) > val[k]) {
614              nnv++;
615              for (int j = nn-2; j >= k; j--) {
616                  val[j+1] = val[j];
617                  list[j+1] = list[j];
618              } 
619              val[k] = fabs(value-round);
620              list[k] = iColumn;
621              break;
622           }
623       }
624    }
625    solution[iColumn] = round;
626  }
627
628  if (nnv > nn) nnv = nn;
629  if (iter != 0&&model_->logLevel())
630    printf("up = %5d , down = %5d", flip_up, flip_down); fflush(stdout);
631  *flip = flip_up + flip_down;
632  delete [] tmp;
633
634  if (*flip == 0 && iter != 0) {
635    if(model_->logLevel())
636      printf(" -- rand = %4d (%4d) ", nnv, nn);
637     for (i = 0; i < nnv; i++) solution[list[i]] = 1. - solution[list[i]];
638     *flip = nnv;
639  } else if (model_->logLevel()) {
640    printf(" ");
641  }
642  delete [] list; delete [] val;
643  iter++;
644   
645  const double * rowLower = solver->getRowLower();
646  const double * rowUpper = solver->getRowUpper();
647
648  int numberRows = solver->getNumRows();
649  // get row activities
650  double * rowActivity = new double[numberRows];
651  memset(rowActivity,0,numberRows*sizeof(double));
652  solver->getMatrixByCol()->times(solution,rowActivity) ;
653  double largestInfeasibility =0.0;
654  for (i=0 ; i < numberRows ; i++) {
655    largestInfeasibility = max(largestInfeasibility,
656                               rowLower[i]-rowActivity[i]);
657    largestInfeasibility = max(largestInfeasibility,
658                               rowActivity[i]-rowUpper[i]);
659  }
660  delete [] rowActivity;
661  return (largestInfeasibility>primalTolerance) ? 0 : 1;
662}
663// Set maximum Time (default off) - also sets starttime to current
664void 
665CbcHeuristicFPump::setMaximumTime(double value)
666{
667  startTime_=CoinCpuTime();
668  maximumTime_=value;
669}
670
671 
Note: See TracBrowser for help on using the repository browser.