source: branches/devel/Cbc/src/CbcHeuristicRINS.cpp @ 539

Last change on this file since 539 was 502, checked in by forrest, 13 years ago

mostly for rins

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