BonLpBranchingSolver.cpp
Go to the documentation of this file.
1 // Copyright (C) 2006, 2007 International Business Machines
2 // Corporation and others. All Rights Reserved.
3 
4 #include "CoinPragma.hpp"
6 #include "OsiClpSolverInterface.hpp"
7 #include <vector>
8 
9 namespace Bonmin
10 {
11 
13  StrongBranchingSolver(b->nonlinearSolver()),
14  lin_(NULL),
15  warm_(NULL),
16  ecp_(NULL)
17  {
18  Ipopt::SmartPtr<TNLPSolver> tnlp_solver =
19  static_cast<TNLPSolver *> (b->nonlinearSolver()->solver());
20  Ipopt::SmartPtr<Ipopt::OptionsList> options = tnlp_solver->options();
21 
22  options->GetIntegerValue("ecp_max_rounds_strong",
24  b->nonlinearSolver()->prefix());
25  options->GetNumericValue("ecp_abs_tol_strong",
27  b->nonlinearSolver()->prefix());
28  options->GetNumericValue("ecp_rel_tol_strong",
30  b->nonlinearSolver()->prefix());
31  int dummy;
32  options->GetEnumValue("lp_strong_warmstart_method",
33  dummy,
34  b->nonlinearSolver()->prefix());
36  }
37 
40  lin_(NULL),
41  warm_(NULL),
42  ecp_(NULL),
43  maxCuttingPlaneIterations_(rhs.maxCuttingPlaneIterations_),
44  abs_ecp_tol_(rhs.abs_ecp_tol_),
45  rel_ecp_tol_(rhs.rel_ecp_tol_),
46  warm_start_mode_(rhs.warm_start_mode_)
47  {}
48 
51  {
52  if (this != &rhs) {
54  }
59  // I assume that no LP solver information is ever copied
60  delete lin_;
61  delete warm_;
62  delete ecp_;
63  lin_ = NULL;
64  warm_ = NULL;
65  ecp_ = NULL;
66  return *this;
67  }
68 
70  {
71  delete lin_;
72  delete warm_;
73  delete ecp_;
74  }
75 
78  {
79  lin_ = new OsiClpSolverInterface();
80  tminlp_interface->extractLinearRelaxation(*lin_, tminlp_interface->getColSolution(),
81  true);
82  double cutoff = -DBL_MAX;
83  tminlp_interface->getDblParam(OsiDualObjectiveLimit, cutoff);
84  lin_->setDblParam(OsiDualObjectiveLimit, cutoff);
85  //printf("Cutoff %g # ecp iteration %i\n",cutoff, maxCuttingPlaneIterations_);
86  lin_->messageHandler()->setLogLevel(0);
87  lin_->resolve();
88  warm_ = lin_->getWarmStart();
89  //if (maxCuttingPlaneIterations_)
90  // ecp_ = new EcpCuts(tminlp_interface, maxCuttingPlaneIterations_,
91  // abs_ecp_tol_, rel_ecp_tol_, -1.);
92  }
93 
96  {
97  // Free memory
98  delete lin_;
99  delete warm_;
100  delete ecp_;
101  lin_ = NULL;
102  warm_ = NULL;
103  ecp_ = NULL;
104  }
105 
108  {
110 
111  // updated the bounds of the linear solver
112  std::vector<int> diff_low_bnd_index;
113  std::vector<double> diff_low_bnd_value;
114  std::vector<int> diff_up_bnd_index;
115  std::vector<double> diff_up_bnd_value;
116 
117  // Get the bounds. We assume that the bounds in the linear solver
118  // are always the original ones
119  const int numCols = tminlp_interface->getNumCols();
120  const double* colLow_orig = lin_->getColLower();
121  const double* colUp_orig = lin_->getColUpper();
122  const double* colLow = tminlp_interface->getColLower();
123  const double* colUp = tminlp_interface->getColUpper();
124 
125  OsiSolverInterface * lin = lin_;
126  // eventualy clone lin_
127  if(warm_start_mode_ == Clone){
128  lin = lin_->clone();
129 // std::cout<<"Cloning it"<<std::endl;
130  }
131  // Set the bounds on the LP solver according to the changes in
132  // tminlp_interface
133  for (int i=0; i<numCols; i++) {
134  const double& lo = colLow[i];
135  if (colLow_orig[i] < lo) {
136  if(warm_start_mode_ == Basis){
137  diff_low_bnd_value.push_back(colLow_orig[i]);
138  diff_low_bnd_index.push_back(i);
139  }
140  lin->setColLower(i,lo);
141  }
142  const double& up = colUp[i];
143  if (colUp_orig[i] > up) {
144  if(warm_start_mode_ == Basis){
145  diff_up_bnd_index.push_back(i);
146  diff_up_bnd_value.push_back(colUp_orig[i]);
147  }
148  lin->setColUpper(i,lo);
149  }
150  }
151 
152  if(warm_start_mode_ == Basis){
153  lin->setWarmStart(warm_);
154  }
155 
156  lin->resolve();
157 
158  double obj = lin->getObjValue();
159  bool go_on = true;
160  if (lin->isProvenPrimalInfeasible() ||
161  lin->isDualObjectiveLimitReached()) {
162  retstatus = TNLPSolver::provenInfeasible;
163  go_on = false;
164  }
165  else if (lin->isIterationLimitReached()) {
166  retstatus = TNLPSolver::iterationLimit;
167  go_on = false;
168  }
169  else {
170  if (maxCuttingPlaneIterations_ > 0 && go_on) {
171  double violation;
172  obj = ecp_->doEcpRounds(*lin, true, &violation);
173  if (obj == COIN_DBL_MAX) {
174  retstatus = TNLPSolver::provenInfeasible;
175  }
176  else if (violation <= 1e-8) {
177  retstatus = TNLPSolver::solvedOptimal;
178  }
179  }
180  }
181  tminlp_interface->problem()->set_obj_value(obj);
182  tminlp_interface->problem()->Set_x_sol(numCols, lin_->getColSolution());
183 
184  //restore the original bounds
185  if(warm_start_mode_ == Basis){
186  for (unsigned int i = 0; i < diff_low_bnd_index.size(); i++) {
187  lin_->setColLower(diff_low_bnd_index[i],diff_low_bnd_value[i]);
188  }
189  for (unsigned int i = 0; i < diff_up_bnd_index.size(); i++) {
190  lin_->setColUpper(diff_up_bnd_index[i],diff_up_bnd_value[i]);
191  }
192  }
193  else {
194  delete lin;
195  }
196  return retstatus;
197  }
198 
199  void
201  {
202  roptions->SetRegisteringCategory("ECP based strong branching",RegisteredOptions::UndocumentedCategory);
203  roptions->AddLowerBoundedIntegerOption
204  ("ecp_max_rounds_strong",
205  "Set the maximal number of rounds of ECP cuts in strong branching.",
206  0,0,
207  "");
208  roptions->setOptionExtraInfo("ecp_max_rounds_strong",63);
209  roptions->AddLowerBoundedNumberOption
210  ("ecp_abs_tol_strong",
211  "Set the absolute termination tolerance for ECP rounds in strong branching.",
212  0,false,1e-6,
213  "");
214  roptions->setOptionExtraInfo("ecp_abs_tol_strong",63);
215  roptions->AddLowerBoundedNumberOption
216  ("ecp_rel_tol_strong",
217  "Set the relative termination tolerance for ECP rounds in strong branching.",
218  0,false,1e-1,
219  "");
220  roptions->setOptionExtraInfo("ecp_rel_tol_strong",63);
221  roptions->AddStringOption2
222  ("lp_strong_warmstart_method",
223  "Choose method to use for warm starting lp in strong branching",
224  "Basis",
225  "Basis", "Use optimal basis of node",
226  "Clone", "Clone optimal problem of node",
227  "(Advanced stuff)");
228  roptions->setOptionExtraInfo("lp_strong_warmstart_method",63);
229  }
230 
231 }
WarmStartMethod warm_start_mode_
Way problems are warm started.
This class is the base class for a solver that can be used in BonOsiSolverInterface to perform the st...
virtual const double * getColLower() const
Get pointer to array[getNumCols()] of column lower bounds.
const TMINLP2TNLP * problem() const
get pointer to the TMINLP2TNLP adapter
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
LpBranchingSolver & operator=(const LpBranchingSolver &rhs)
Assignment operator.
void Set_x_sol(Ipopt::Index n, const Ipopt::Number *x_sol)
Set the contiuous solution.
CoinWarmStart * warm_
Warm start object for linear solver.
void set_obj_value(Ipopt::Number value)
Manually set objective value.
This is a generic class for calling an NLP solver to solve a TNLP.
LpBranchingSolver()
Default Constructor.
double abs_ecp_tol_
absolute tolerance for ECP cuts
virtual int getNumCols() const
Get number of columns.
const Bonmin::TNLPSolver * solver() const
int up
Definition: OSdtoa.cpp:1817
virtual const double * getColSolution() const
Get pointer to array[getNumCols()] of primal solution vector.
int maxCuttingPlaneIterations_
Number of maximal ECP cuts.
void fint fint fint real fint real real real real real real real real real * e
A class to have all elements necessary to setup a branch-and-bound.
double doEcpRounds(OsiSolverInterface &si, bool leaveSiUnchanged, double *violation=NULL)
Definition: BonEcpCuts.cpp:29
virtual ~LpBranchingSolver()
Destructor.
Implementation of BonChooseVariable for curvature-based braching.
ReturnStatus
Standard return statuses for a solver.
OsiSolverInterface * lin_
Linear solver.
const char * prefix() const
Default Constructor.
StrongBranchingSolver & operator=(const StrongBranchingSolver &rhs)
Assignment operator.
virtual const double * getColUpper() const
Get pointer to array[getNumCols()] of column upper bounds.
OsiTMINLPInterface * nonlinearSolver()
Pointer to the non-linear solver used.
EcpCuts * ecp_
Ecp cut generate.
virtual void unmarkHotStart(OsiTMINLPInterface *tminlp_interface)
Called after all strong branching solves in a node.
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
virtual void extractLinearRelaxation(OsiSolverInterface &si, const double *x, bool getObj=1)
Extract a linear relaxation of the MINLP.
return b
Definition: OSdtoa.cpp:1719
double rel_ecp_tol_
relative tolerance for ECP cuts
virtual void markHotStart(OsiTMINLPInterface *tminlp_interface)
Called to initialize solver before a bunch of strong branching solves.
virtual TNLPSolver::ReturnStatus solveFromHotStart(OsiTMINLPInterface *tminlp_interface)
Called to solve the current TMINLP (with changed bound information)
bool getDblParam(OsiDblParam key, double &value) const