BonOACutGenerator2.cpp
Go to the documentation of this file.
1 // (C) Copyright Carnegie Mellon University 2005, 2006
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // Authors :
6 // P. Bonami, Carnegie Mellon University
7 //
8 // Date : 05/26/2005
9 
10 #include "BonOACutGenerator2.hpp"
11 #include "BonminConfig.h"
12 
13 #include "OsiClpSolverInterface.hpp"
14 
15 #include "CbcModel.hpp"
16 #include "BonCbcLpStrategy.hpp"
17 #ifdef COIN_HAS_CPX
18 #include "OsiCpxSolverInterface.hpp"
19 #endif
20 #include "OsiAuxInfo.hpp"
21 #include "BonSolverHelp.hpp"
22 
23 #include <climits>
24 
25 namespace Bonmin
26 {
27  static const char * txt_id = "OA decomposition";
28 
29 
32  OaDecompositionBase(b, true, false)
33  {
34  std::string bonmin="bonmin.";
35  std::string prefix = (b.prefix() == bonmin) ? "" : b.prefix();
36  prefix += "oa_decomposition.";
37  subMip_ = new SubMipSolver(b, prefix);
38  double oaTime;
39  b.options()->GetNumericValue("time_limit",oaTime,prefix);
40  parameter().maxLocalSearch_ = INT_MAX;
41  b.options()->GetIntegerValue("solution_limit", parameter().maxSols_,prefix);
43  std::min(b.getDoubleParameter(BabSetupBase::MaxTime), oaTime);
46  }
48  {
49  delete subMip_;
50  }
51 
53  bool
55  {
58  CoinCpuTime() - timeBegin_ < parameters_.maxLocalSearchTime_);
59  }
61  double
63  solverManip &lpManip,
64  BabInfo * babInfo,
65  double & cutoff, const CglTreeInfo & info) const
66  {
67 
68  double lastPeriodicLog = CoinCpuTime();
69 
70  //const int numcols = nlp_->getNumCols();
71  double gap_tol = this->parameter().gap_tol_;
72 
73  bool isInteger = false;
74 
75  subMip_->setLpSolver(lpManip.si());
76  OsiSolverInterface * lp = subMip_->solver();
77  lp->resolve();
78 
79  if(IsValid(nlp_->linearizer())){
80  nlp_->linearizer()->get_refined_oa(cs);
81  installCuts(*lp, cs, cs.sizeRowCuts());
82  }
83  lp->resolve();
84 
85  OsiBranchingInformation branch_info(lp, false);
86  bool milpOptimal = 1;
87 
88 
89  double milpBound = -COIN_DBL_MAX;
90  //bool milpFeasible = 1;
91  bool feasible = 1;
92 
94  parameters_.maxLocalSearchTime_ + timeBegin_ - CoinCpuTime());
95 
96  milpBound = std::max(milpBound, subMip_->lowBound());
97  milpOptimal = subMip_->optimal();
98 
99  feasible = milpBound < cutoff;
100  //milpFeasible = feasible;
101  isInteger = (subMip_->getLastSolution() != NULL);
102  nLocalSearch_++;
103 
104  if (milpOptimal)
105  handler_->message(SOLVED_LOCAL_SEARCH, messages_)<<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
106  else
107  {
108  handler_->message(LOCAL_SEARCH_ABORT, messages_)<<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
109  }
110 
111  int nodeCount = subMip_->nodeCount();
112 
113  int numberPasses = 0;
114 
115 #ifdef OA_DEBUG
116  bool foundSolution = 0;
117 #endif
118  double * nlpSol = NULL;
119  double ub = cutoff;
120  double gap = 1;
121  while (isInteger && feasible) {
122  numberPasses++;
123  //after a prescribed elapsed time give some information to user
124  double time = CoinCpuTime();
125  if (time - lastPeriodicLog > parameters_.logFrequency_) {
127  <<time - timeBegin_<<numberPasses<<cutoff
128  <<milpBound
129  <<CoinMessageEol;
130  lastPeriodicLog = CoinCpuTime();
131  }
132 
133 
134  //setup the nlp
135  int numberCutsBefore = cs.sizeRowCuts();
136 
137  //Fix the variable which have to be fixed, after having saved the bounds
138  const double * colsol =
140  branch_info.solution_ = colsol;
141 
143 
144  nlp_->resolve(txt_id);
145  if (post_nlp_solve(babInfo, cutoff)) {
146  //nlp solved and feasible
147  // Update the cutoff
148  ub = std::min(nlp_->getObjValue(), ub);
149  cutoff = ub > 0 ? ub *(1 - parameters_.cbcCutoffIncrement_) : ub*(1 + parameters_.cbcCutoffIncrement_);
150  assert(cutoff < ub);
151  // Update the lp solver cutoff
152  lp->setDblParam(OsiDualObjectiveLimit, cutoff);
153  numSols_++;
154  }
155 
156  nlpSol = const_cast<double *>(nlp_->getColSolution());
157 
158  // Get the cuts outer approximation at the current point
160  nlp_->getOuterApproximation(cs, nlpSol, 1, colsol,
161  parameter().global_);
162  }
163  else {
164  nlp_->getOuterApproximation(cs, nlpSol, 1, NULL,
165  parameter().global_);
166  }
167 
168  int numberCuts = cs.sizeRowCuts() - numberCutsBefore;
169  assert(numberCuts);
170  installCuts(*lp, cs, numberCuts);
171 
172  lp->resolve();
173 
174  double objvalue = lp->getObjValue();
175  //milpBound = max(milpBound, lp->getObjValue());
176  feasible = (lp->isProvenOptimal() &&
177  !lp->isDualObjectiveLimitReached() && (objvalue<cutoff)) ;
178  //if value of integers are unchanged then we have to get out
179  bool changed = !feasible;//if lp is infeasible we don't have to check anything
180  branch_info.solution_ = lp->getColSolution();
181  if (!changed)
184  nlp_->getColSolution(), lp->getColSolution());
185  if (changed) {
186 
187  isInteger = integerFeasible(*lp, branch_info, parameters_.cbcIntegerTolerance_,
189  }
190  else {
191  isInteger = 0;
192  // if(!fixed)//fathom on bounds
193  milpBound = 1e200;
194  }
195 #ifdef OA_DEBUG
196  printf("Obj value after cuts %g %d rows\n",lp->getObjValue(),
197  numberCuts) ;
198 #endif
199  //check time
200  if (CoinCpuTime() - timeBegin_ > parameters_.maxLocalSearchTime_)
201  break;
202 
203  if(ub!=0)
204  gap = (ub - milpBound)/fabs(ub);
205  else
206  gap = -milpBound/(1e-10);
207  if (gap < gap_tol){
208  milpBound = 1e50;
209  feasible = 0;
210  }
211  //do we perform a new local search ?
212  if (feasible &&
215 
216  if(ub!=0)
217  gap = (ub - milpBound)/fabs(ub);
218  else
219  gap = -milpBound/(1e-10);
220  if (gap < gap_tol){
221  milpBound = 1e50;
222  feasible = 0;
223  }
224  nLocalSearch_++;
225 
227  parameters_.maxLocalSearchTime_ + timeBegin_ - CoinCpuTime());
228 
229  milpBound = std::max(milpBound, subMip_->lowBound());
230 
231  if (subMip_->optimal())
232  handler_->message(SOLVED_LOCAL_SEARCH, messages_)<<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
233  else
234  handler_->message(LOCAL_SEARCH_ABORT, messages_)<<subMip_->nodeCount()<<subMip_->iterationCount()<<CoinMessageEol;
235 
236  nodeCount += subMip_->nodeCount();
237 
238  colsol = const_cast<double *> (subMip_->getLastSolution());
239  isInteger = (colsol != 0);
240 
241  feasible = (milpBound < cutoff);
242 
243  if (feasible && isInteger) {
244  bool changed = false;
246  0.1,
247  nlp_->getColSolution(), colsol);
248  //solution problem is solved
249  if (!changed) {
250  feasible = 0;
251  milpBound = 1e50;
252  }
253  //milpFeasible = feasible;
254  }
255  if (subMip_->optimal())
256  milpOptimal = 1;
257  else {
258  milpOptimal = 0;
259  }
260  if (milpBound < cutoff)
261  handler_->message(UPDATE_LB, messages_)<<milpBound<<CoinCpuTime() - timeBegin_<<CoinMessageEol;
262  else {
263  milpBound = 1e50;
264  feasible = 0;
265  }
266  }
267 
268  }
269 
270  if(milpBound >= cutoff){
271  handler_->message(OASUCCESS, messages_)<<"OA "<<CoinCpuTime() - timeBegin_
272  <<ub<<milpBound<<CoinMessageEol;
273  }
274  else {
275  handler_->message(OAABORT, messages_)<<"OA "<<CoinCpuTime() - timeBegin_
276  <<ub<<milpBound<<CoinMessageEol;
277  }
278  handler_->message(OA_STATS, messages_)<<numberPasses<<nodeCount
279  <<CoinMessageEol;
280 #ifdef OA_DEBUG
281  debug_.printEndOfProcedureDebugMessage(cs, foundSolution, cutoff, milpBound, isInteger, feasible, std::cout);
282 #endif
283  return milpBound;
284  }
285 
287  void
289  {
290  roptions->SetRegisteringCategory("Outer Approximation Decomposition (B-OA)", RegisteredOptions::BonminCategory);
291  roptions->AddStringOption2("oa_decomposition", "If yes do initial OA decomposition",
292  "no",
293  "no","",
294  "yes","",
295  "");
296  roptions->setOptionExtraInfo("oa_decomposition",19);
297 
298  roptions->SetRegisteringCategory("Output and Loglevel", RegisteredOptions::BonminCategory);
299  roptions->AddBoundedIntegerOption("oa_log_level",
300  "specify OA iterations log level.",
301  0,2,1,
302  "Set the level of output of OA decomposition solver : "
303  "0 - none, 1 - normal, 2 - verbose"
304  );
305  roptions->setOptionExtraInfo("oa_log_level", 25);
306 
307  roptions->AddLowerBoundedNumberOption("oa_log_frequency",
308  "display an update on lower and upper bounds in OA every n seconds",
309  0.,1.,100.,
310  "");
311  roptions->setOptionExtraInfo("oa_log_frequency", 25);
312  }
313 }/* End namespace Bonmin. */
314 
int getIntParameter(const IntParameter &p) const
Return value of integer parameter.
int maxSols_
maximum number of solutions
Small class to manipulatee various things in an OsiSolverInterface and restore them.
int nLocalSearch_
number of local searches performed
void getOuterApproximation(OsiCuts &cs, int getObj, const double *x2, bool global)
Get the outer approximation constraints at the current optimal point.
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
bool addOnlyViolated_
Add only violated OA inequalities.
double maxLocalSearchTime_
maximum time for local searches
bool IsValid(const OSSmartPtr< U > &smart_ptr)
Definition: OSSmartPtr.hpp:465
double cbcIntegerTolerance_
integer tolerance (has to be the same as Cbc&#39;s)
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Register OA options.
virtual double performOa(OsiCuts &cs, solverManip &lpManip, BabInfo *babInfo, double &cutoff, const CglTreeInfo &info) const
virtual method which performs the OA algorithm by modifying lp and nlp.
virtual bool doLocalSearch(BabInfo *babInfo) const
virutal method to decide if local search is performed
virtual double getObjValue() const
Get objective function value (can&#39;t use default)
OsiObject ** objects_
Some objects the feasiblitiy of which to verify.
const double * getLastSolution()
get the solution found in last local search (return NULL if no solution).
CoinMessageHandler * handler_
messages handler.
double gap_tol_
setting for gap tolerance.
int nObjects_
Number of objects.*/.
virtual const double * getColSolution() const
Get pointer to array[getNumCols()] of primal solution vector.
void fint fint fint real fint real real real real real real real real real * e
A very simple class to provide a common interface for solving MIPs with Cplex and Cbc...
A class to have all elements necessary to setup a branch-and-bound.
limit on number of integer feasible solution.
OACutGenerator2(BabSetupBase &b)
Constructor with basic setup.
void installCuts(OsiSolverInterface &si, const OsiCuts &cs, int numberCuts)
Install cuts in solver.
bool isDifferentOnIntegers(OsiSolverInterface &si, OsiObject **objects, int nObjects, double integer_tolerance, const double *colsol, const double *otherSol)
Check if two solutions are the same on integer variables.
double timeBegin_
time of construction
void fint fint fint real fint real real real real real real real real real fint real fint * lp
virtual void resolve()
Resolve the continuous relaxation after problem modification.
Parameters parameters_
Parameters.
int numSols_
number of solutions found by OA_decomposition.
void solve(double cutoff, int loglevel, double maxTime)
double cbcCutoffIncrement_
cutoff min increase (has to be intialized trhough Cbc)
OsiSolverInterface * solver()
int subMilpLogLevel_
sub milp log level.
bool optimal()
returns optimality status.
void fixIntegers(OsiSolverInterface &si, const OsiBranchingInformation &info, double integer_tolerance, OsiObject **objects, int nObjects)
Fix integer variables in si to their values in colsol.
double lowBound()
Returns lower bound.
double logFrequency_
Frequency of log.
CoinMessages messages_
Messages for OA.
int maxLocalSearch_
Total max number of local searches.
int iterationCount()
Returns number of simplex iterations in last solve.
OsiSolverInterface * si()
Get pointer to solver interface.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
double getDoubleParameter(const DoubleParameter &p) const
Return value of double parameter.
static const char * txt_id
Base class for OA algorithms.
static char prefix[100]
Definition: BM_lp.cpp:26
bool integerFeasible(OsiSolverInterface &si, const OsiBranchingInformation &info, double integer_tolerance, OsiObject **objects, int nObjects)
Check for integer feasibility of a solution return 1 if it is.
OsiTMINLPInterface * nlp_
Pointer to nlp interface.
return b
Definition: OSdtoa.cpp:1719
const char * prefix() const
Get prefix to use for options.
void setLpSolver(OsiSolverInterface *lp)
Assign lp solver.
Bonmin class for passing info between components of branch-and-cuts.
Definition: BonBabInfos.hpp:19
int nodeCount()
Returns number of nodes in last solve.
bool post_nlp_solve(BabInfo *babInfo, double cutoff) const
Solve the nlp and do output.
bool isInteger(CouNumber x)
is this number integer?