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

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

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

File size: 6.5 KB
Line 
1// Copyright (C) 2006, International Business Machines
2// Corporation and others.  All Rights Reserved.
3#if defined(_MSC_VER)
4// Turn off compiler warning about long names
5#  pragma warning(disable:4786)
6#endif
7#include <cassert>
8#include <cstdlib>
9#include <cmath>
10#include <cfloat>
11
12#include "OsiSolverInterface.hpp"
13#include "CbcModel.hpp"
14#include "CbcMessage.hpp"
15#include "CbcHeuristicRINS.hpp"
16#include "CbcBranchActual.hpp"
17#include "CbcStrategy.hpp"
18#include "CglPreProcess.hpp"
19
20// Default Constructor
21CbcHeuristicRINS::CbcHeuristicRINS() 
22  :CbcHeuristic()
23{
24  numberSolutions_=0;
25  numberSuccesses_=0;
26  numberTries_=0;
27  howOften_=100;
28  used_=NULL;
29}
30
31// Constructor with model - assumed before cuts
32
33CbcHeuristicRINS::CbcHeuristicRINS(CbcModel & model)
34  :CbcHeuristic(model)
35{
36  numberSolutions_=0;
37  numberSuccesses_=0;
38  numberTries_=0;
39  howOften_=100;
40  assert(model.solver());
41  int numberColumns = model.solver()->getNumCols();
42  used_ = new char[numberColumns];
43  memset(used_,0,numberColumns);
44}
45
46// Destructor
47CbcHeuristicRINS::~CbcHeuristicRINS ()
48{
49  delete [] used_;
50}
51
52// Clone
53CbcHeuristic *
54CbcHeuristicRINS::clone() const
55{
56  return new CbcHeuristicRINS(*this);
57}
58
59// Assignment operator
60CbcHeuristicRINS & 
61CbcHeuristicRINS::operator=( const CbcHeuristicRINS& rhs)
62{
63  if (this!=&rhs) {
64    CbcHeuristic::operator=(rhs);
65    numberSolutions_ = rhs.numberSolutions_;
66    howOften_ = rhs.howOften_;
67    numberSuccesses_ = rhs.numberSuccesses_;
68    numberTries_ = rhs.numberTries_;
69    delete [] used_;
70    if (model_&&rhs.used_) {
71      int numberColumns = model_->solver()->getNumCols();
72      used_ = new char[numberColumns];
73      memcpy(used_,rhs.used_,numberColumns);
74    } else {
75      used_=NULL;
76    }
77  }
78  return *this;
79}
80
81// Create C++ lines to get to current state
82void 
83CbcHeuristicRINS::generateCpp( FILE * fp) 
84{
85  CbcHeuristicRINS other;
86  fprintf(fp,"0#include \"CbcHeuristicRINS.hpp\"\n");
87  fprintf(fp,"3  CbcHeuristicRINS heuristicRINS(*cbcModel);\n");
88  CbcHeuristic::generateCpp(fp,"heuristicRINS");
89  if (howOften_!=other.howOften_)
90    fprintf(fp,"3  heuristicRINS.setHowOften(%d);\n",howOften_);
91  else
92    fprintf(fp,"4  heuristicRINS.setHowOften(%d);\n",howOften_);
93  fprintf(fp,"3  cbcModel->addHeuristic(&heuristicRINS);\n");
94}
95
96// Copy constructor
97CbcHeuristicRINS::CbcHeuristicRINS(const CbcHeuristicRINS & rhs)
98:
99  CbcHeuristic(rhs),
100  numberSolutions_(rhs.numberSolutions_),
101  howOften_(rhs.howOften_),
102  numberSuccesses_(rhs.numberSuccesses_),
103  numberTries_(rhs.numberTries_)
104{
105  if (model_&&rhs.used_) {
106    int numberColumns = model_->solver()->getNumCols();
107    used_ = new char[numberColumns];
108    memcpy(used_,rhs.used_,numberColumns);
109  } else {
110    used_=NULL;
111  }
112}
113// Resets stuff if model changes
114void 
115CbcHeuristicRINS::resetModel(CbcModel * model)
116{
117  //CbcHeuristic::resetModel(model);
118  delete [] used_;
119  if (model_&&used_) {
120    int numberColumns = model_->solver()->getNumCols();
121    used_ = new char[numberColumns];
122    memset(used_,0,numberColumns);
123  } else {
124    used_=NULL;
125  }
126}
127/*
128  First tries setting a variable to better value.  If feasible then
129  tries setting others.  If not feasible then tries swaps
130  Returns 1 if solution, 0 if not */
131int
132CbcHeuristicRINS::solution(double & solutionValue,
133                         double * betterSolution)
134{
135  int returnCode=0;
136  const double * bestSolution = model_->bestSolution();
137  if (!bestSolution)
138    return 0; // No solution found yet
139  if (numberSolutions_<model_->getSolutionCount()) {
140    // new solution - just add info
141    numberSolutions_=model_->getSolutionCount();
142
143    int numberIntegers = model_->numberIntegers();
144    const int * integerVariable = model_->integerVariable();
145 
146    int i;
147    for (i=0;i<numberIntegers;i++) {
148      int iColumn = integerVariable[i];
149      const OsiObject * object = model_->object(i);
150      // get original bounds
151      double originalLower;
152      double originalUpper;
153      getIntegerInformation( object,originalLower, originalUpper); 
154      double value=bestSolution[iColumn];
155      if (value<originalLower) {
156        value=originalLower;
157      } else if (value>originalUpper) {
158        value=originalUpper;
159      }
160      double nearest=floor(value+0.5);
161      // if away from lower bound mark that fact
162      if (nearest>originalLower) {
163        used_[iColumn]=1;
164      }
165    }
166  } else if ((model_->getNodeCount()%howOften_)==0&&model_->getCurrentPassNumber()==1) {
167    OsiSolverInterface * solver = model_->solver();
168
169    int numberIntegers = model_->numberIntegers();
170    const int * integerVariable = model_->integerVariable();
171 
172    const double * currentSolution = solver->getColSolution();
173    OsiSolverInterface * newSolver = model_->continuousSolver()->clone();
174    const double * colLower = newSolver->getColLower();
175    //const double * colUpper = newSolver->getColUpper();
176
177    double primalTolerance;
178    solver->getDblParam(OsiPrimalTolerance,primalTolerance);
179   
180    int i;
181    int nFix=0;
182    for (i=0;i<numberIntegers;i++) {
183      int iColumn=integerVariable[i];
184      const OsiObject * object = model_->object(i);
185      // get original bounds
186      double originalLower;
187      double originalUpper;
188      getIntegerInformation( object,originalLower, originalUpper); 
189      double valueInt=bestSolution[iColumn];
190      if (valueInt<originalLower) {
191        valueInt=originalLower;
192      } else if (valueInt>originalUpper) {
193        valueInt=originalUpper;
194      }
195      if (fabs(currentSolution[iColumn]-valueInt)<10.0*primalTolerance) {
196        double nearest=floor(valueInt+0.5);
197        newSolver->setColLower(iColumn,nearest);
198        newSolver->setColUpper(iColumn,colLower[iColumn]);
199        nFix++;
200      }
201    }
202    if (nFix>numberIntegers/5) {
203      //printf("%d integers have same value\n",nFix);
204      returnCode = smallBranchAndBound(newSolver,numberNodes_,betterSolution,solutionValue,
205                                         model_->getCutoff(),"CbcHeuristicRINS");
206      if (returnCode<0)
207        returnCode=0; // returned on size
208      if ((returnCode&1)!=0)
209        numberSuccesses_++;
210      //printf("return code %d",returnCode);
211      if ((returnCode&2)!=0) {
212        // could add cut
213        returnCode &= ~2;
214        //printf("could add cut with %d elements (if all 0-1)\n",nFix);
215      } else {
216        //printf("\n");
217      }
218      numberTries_++;
219      if ((numberTries_%10)==0&&numberSuccesses_*3<numberTries_)
220        howOften_ += howOften_/10;
221    }
222
223    delete newSolver;
224  }
225  return returnCode;
226}
227// update model
228void CbcHeuristicRINS::setModel(CbcModel * model)
229{
230  model_ = model;
231  // Get a copy of original matrix
232  assert(model_->solver());
233  delete [] used_;
234  int numberColumns = model->solver()->getNumCols();
235  used_ = new char[numberColumns];
236  memset(used_,0,numberColumns);
237}
238
239 
Note: See TracBrowser for help on using the repository browser.