BonOaFeasChecker.cpp
Go to the documentation of this file.
1 // (C) Copyright International Business Machines 2006-2011
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 : 12/26/2006
9 
10 #include "BonOaFeasChecker.hpp"
11 #include "BonminConfig.h"
12 
13 #include "OsiAuxInfo.hpp"
14 #include "BonSolverHelp.hpp"
15 
16 namespace Bonmin
17 {
18  static const char * txt_id = "check integer sol.";
19 
22  OaDecompositionBase(b, false, true),
23  cut_count_(0)
24  {
25  int ival;
26  b.options()->GetEnumValue("feas_check_cut_types", ival, b.prefix());
27  type_ = CutsTypes(ival);
28  b.options()->GetEnumValue("feas_check_discard_policy", ival, b.prefix());
29  pol_ = CutsPolicies(ival);
30  b.options()->GetIntegerValue("generate_benders_after_so_many_oa", ival, b.prefix());
31  maximum_oa_cuts_ = static_cast<unsigned int>(ival);
32  }
34  {}
35 
37  double
39  BabInfo * babInfo, double &cutoff,const CglTreeInfo & info) const
40  {
41  bool isInteger = true;
42  bool feasible = 1;
43 
44  OsiSolverInterface * lp = lpManip.si();
45  OsiBranchingInformation branch_info(lp,false);
46  //int numcols = lp->getNumCols();
47  double milpBound = -COIN_DBL_MAX;
48  int numberPasses = 0;
49  double * nlpSol = NULL;
50  int numberCutsBefore = cs.sizeRowCuts();
51 
52  while (isInteger && feasible ) {
53  numberPasses++;
54 
55  //setup the nlp
56 
57  //Fix the variable which have to be fixed, after having saved the bounds
58  double * colsol = const_cast<double *>(lp->getColSolution());
59  branch_info.solution_ = colsol;
61 
62 
63  //Now solve the NLP get the cuts, and intall them in the local LP
65  if (post_nlp_solve(babInfo, cutoff)) {
66  //nlp solved and feasible
67  // Update the cutoff
68  double ub = nlp_->getObjValue();
69  cutoff = ub > 0 ? ub *(1 - parameters_.cbcCutoffIncrement_) : ub*(1 + parameters_.cbcCutoffIncrement_);
70  // Update the lp solver cutoff
71  lp->setDblParam(OsiDualObjectiveLimit, cutoff);
72  }
73  // Get the cuts outer approximation at the current point
74 
75  nlpSol = const_cast<double *>(nlp_->getColSolution());
76 
77  const double * toCut = (parameter().addOnlyViolated_)?
78  colsol:NULL;
79  if(cut_count_ <= maximum_oa_cuts_ && type_ == OA)
80  nlp_->getOuterApproximation(cs, nlpSol, 1, toCut,
81  true);
82  else {//if (type_ == Benders)
83  nlp_->getBendersCut(cs, parameter().global_);
84  }
85  if(pol_ == DetectCycles)
87 
88  int numberCuts = cs.sizeRowCuts() - numberCutsBefore;
89  cut_count_ += numberCuts;
90  if (numberCuts > 0)
91  installCuts(*lp, cs, numberCuts);
92 
93  lp->resolve();
94  double objvalue = lp->getObjValue();
95  //milpBound = max(milpBound, lp->getObjValue());
96  feasible = (lp->isProvenOptimal() &&
97  !lp->isDualObjectiveLimitReached() && (objvalue<cutoff)) ;
98  //if value of integers are unchanged then we have to get out
99  bool changed = true;//if lp is infeasible we don't have to check anything
100  isInteger = 0;
101  // if(!fixed)//fathom on bounds
102  // milpBound = 1e200;
103  if (feasible) {
105  0.1,
106  nlp_->getColSolution(), lp->getColSolution());
107  }
108  if (changed) {
109  branch_info.solution_ = lp->getColSolution();
110  isInteger = integerFeasible(*lp,branch_info, parameters_.cbcIntegerTolerance_,
112  }
113  else {
114  isInteger = 0;
115  // if(!fixed)//fathom on bounds
116  milpBound = 1e200;
117  }
118 #ifdef OA_DEBUG
119  printf("Obj value after cuts %g, %d rows\n",lp->getObjValue(),
120  numberCuts) ;
121 #endif
122  }
123  int num_cuts_now = cs.sizeRowCuts();
124  if(pol_ == KeepAll){
125  for(int i = numberCutsBefore ; i < num_cuts_now ; i++){
126  cs.rowCut(i).setEffectiveness(99.9e99);
127  }
128  }
129 
130 #ifdef OA_DEBUG
131  debug_.printEndOfProcedureDebugMessage(cs, true, cutoff, milpBound, isInteger, feasible, std::cout);
132  std::cout<<"milpBound found: "<<milpBound<<std::endl;
133 #endif
134  return milpBound;
135  }
136 
137 
139  void
141  {
142  roptions->SetRegisteringCategory("Feasibility checker using OA cuts", RegisteredOptions::BonminCategory);
143  roptions->AddStringOption2("feas_check_cut_types", "Choose the type of cuts generated when an integer feasible solution is found",
144  "outer-approx",
145  "outer-approx", "Generate a set of Outer Approximations cuts.",
146  "Benders", "Generate a single Benders cut.",
147  "If it seems too much memory is used should try Benders to use less");
148  roptions->setOptionExtraInfo("feas_check_cut_types", 19);
149 
150 
151  roptions->AddStringOption3("feas_check_discard_policy", "How cuts from feasibility checker are discarded",
152  "detect-cycles",
153  "detect-cycles", "Detect if a cycle occurs and only in this case force not to discard.",
154  "keep-all", "Force cuts from feasibility checker not to be discarded (memory hungry but sometimes better).",
155  "treated-as-normal", "Cuts from memory checker can be discarded as any other cuts (code may cycle then)",
156  "Normally to avoid cycle cuts from feasibility checker should not be discarded in the node where they are generated. "
157  "However Cbc sometimes does it if no care is taken which can lead to an infinite loop in Bonmin (usually on simple problems). "
158  "To avoid this one can instruct Cbc to never discard a cut but if we do that for all cuts it can lead to memory problems. "
159  "The default policy here is to detect cycles and only then impose to Cbc to keep the cut. "
160  "The two other alternative are to instruct Cbc to keep all cuts or to just ignore the problem and hope for the best");
161  roptions->setOptionExtraInfo("feas_check_discard_policy", 19);
162 
163  roptions->AddLowerBoundedIntegerOption("generate_benders_after_so_many_oa", "Specify that after so many oa cuts have been generated Benders cuts should be generated instead.",
164  0, 5000,
165  "It seems that sometimes generating too many oa cuts slows down the optimization compared to Benders due to the size of the LP. "
166  "With this option we specify that after so many OA cuts have been generated we should switch to Benders cuts.");
167  roptions->setOptionExtraInfo("generate_benders_after_so_many_oa", 19);
168  }
169 
170 }/* End namespace Bonmin. */
Small class to manipulatee various things in an OsiSolverInterface and restore them.
void getOuterApproximation(OsiCuts &cs, int getObj, const double *x2, bool global)
Get the outer approximation constraints at the current optimal point.
OsiCuts savedCuts_
Saved cuts: in some cases when using OA to check feasible solution algorithm may loop because Cbc rem...
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.
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.
CutsTypes
See documentation for feas_check_cut_types option.
CutsPolicies pol_
Policy for keeping cuts.
double cbcIntegerTolerance_
integer tolerance (has to be the same as Cbc&#39;s)
OaFeasibilityChecker(BabSetupBase &b)
New usefull constructor.
virtual double getObjValue() const
Get objective function value (can&#39;t use default)
OsiObject ** objects_
Some objects the feasiblitiy of which to verify.
int nObjects_
Number of objects.*/.
virtual const double * getColSolution() const
Get pointer to array[getNumCols()] of primal solution vector.
A class to have all elements necessary to setup a branch-and-bound.
void installCuts(OsiSolverInterface &si, const OsiCuts &cs, int numberCuts)
Install cuts in solver.
unsigned int maximum_oa_cuts_
maximum number of OA cuts.
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.
void getBendersCut(OsiCuts &cs, bool global)
Get a benders cut from solution.
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.
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Register OA options.
double cbcCutoffIncrement_
cutoff min increase (has to be intialized trhough Cbc)
CutsTypes type_
Type of cuts.
void fixIntegers(OsiSolverInterface &si, const OsiBranchingInformation &info, double integer_tolerance, OsiObject **objects, int nObjects)
Fix integer variables in si to their values in colsol.
OsiSolverInterface * si()
Get pointer to solver interface.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
static const char * txt_id
Base class for OA algorithms.
unsigned int cut_count_
Count the total number of cuts generated.
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.
CutsPolicies
See documentation for feas_check_discard_policy option.
Bonmin class for passing info between components of branch-and-cuts.
Definition: BonBabInfos.hpp:19
bool post_nlp_solve(BabInfo *babInfo, double cutoff) const
Solve the nlp and do output.
bool isInteger(CouNumber x)
is this number integer?