CouenneComplBranchingObject.cpp
Go to the documentation of this file.
1 /* $Id: CouenneComplBranchingObject.cpp 807 2012-01-31 02:37:44Z pbelotti $
2  *
3  * Name: CouenneComplBranchingObject.cpp
4  * Authors: Pietro Belotti, Carnegie Mellon University
5  * Purpose: Branching object for auxiliary variables
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CoinHelperFunctions.hpp"
12 
13 #include "OsiRowCut.hpp"
14 
15 #include "CouenneCutGenerator.hpp"
16 #include "CouenneProblem.hpp"
17 #include "CouenneProblemElem.hpp"
18 #include "CouenneObject.hpp"
20 
21 using namespace Ipopt;
22 using namespace Couenne;
23 
24 // translate changed bound sparse array into a dense one
25 void sparse2dense (int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged);
26 
27 
34 CouenneComplBranchingObject::CouenneComplBranchingObject (OsiSolverInterface *solver,
35  const OsiObject * originalObject,
36  JnlstPtr jnlst,
38  CouenneProblem *p,
39  expression *var,
40  expression *var2,
41  int way,
42  CouNumber brpoint,
43  bool doFBBT, bool doConvCuts, int sign):
44 
45  CouenneBranchingObject (solver, originalObject, jnlst, c, p, var, way, brpoint, doFBBT, doConvCuts),
46  variable2_ (var2),
47  sign_ (sign) {
48 
49  jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING,
50  "Complem. Branch: x%-3d = 0 or x%-3d = 0\n",
51  way ? variable_ -> Index () : variable2_ -> Index ());
52 }
53 
54 
62 double CouenneComplBranchingObject::branch (OsiSolverInterface * solver) {
63 
64  // way = 0 if "x1=0" node,
65  // 1 if "x2=0" node
66 
67  int
68  way = (!branchIndex_) ? firstBranch_ : !firstBranch_,
69  index = way ? variable2_ -> Index () : variable_ -> Index ();
70 
71  jnlst_ -> Printf (J_ITERSUMMARY, J_BRANCHING, "Branching: x%-3d = 0\n",
72  //printf ("complementarity Branching: x%-3d = 0\n",
73  way ? variable2_ -> Index () : variable_ -> Index ());
74 
75  /*
76  double time = CoinCpuTime ();
77  jnlst_ -> Printf (J_VECTOR, J_BRANCHING,"[vbctool] %02d:%02d:%02d.%02d_I x%d%c=%g_[%g,%g]\n",
78  (int) (floor(time) / 3600),
79  (int) (floor(time) / 60) % 60,
80  (int) floor(time) % 60,
81  (int) ((time - floor (time)) * 100),
82  index, way ? '>' : '<', integer ? ((way ? ceil (brpt): floor (brpt))) : brpt,
83  solver -> getColLower () [index],
84  solver -> getColUpper () [index]);
85  */
86 
88 
89  int
90  ind0 = variable_ -> Index (),
91  ind1 = variable2_ -> Index ();
92 
93  if (!sign_) { // constraint x1 x2 = 0
94  solver -> setColLower (index, 0.);
95  solver -> setColUpper (index, 0.);
96  } else {
97 
98  if (sign_ < 0) // it is a x1 x2 <= 0
99  if (!way) { // branch on second orthant first
100  solver -> setColUpper (ind0, 0.);
101  solver -> setColLower (ind1, 0.);
102  } else { // branch on fourth orthant first
103  solver -> setColLower (ind0, 0.);
104  solver -> setColUpper (ind1, 0.);
105  }
106  else // it is a x1 x2 >= 0
107  if (!way) { // branch on first orthant first
108  solver -> setColLower (ind0, 0.);
109  solver -> setColLower (ind1, 0.);
110  } else { // branch on third orthant first
111  solver -> setColUpper (ind0, 0.);
112  solver -> setColUpper (ind1, 0.);
113  }
114  }
115 
117 
118  //CouenneSolverInterface *couenneSolver = dynamic_cast <CouenneSolverInterface *> (solver);
119  //CouenneProblem *p = couenneSolver -> CutGen () -> Problem ();
120 
121  int
122  nvars = problem_ -> nVars (),
123  objind = problem_ -> Obj (0) -> Body () -> Index ();
124 
125  //CouNumber &estimate = way ? upEstimate_ : downEstimate_;
126  CouNumber estimate = 0.;//way ? upEstimate_ : downEstimate_;
127 
128  bool infeasible = false;
129 
130  // only bother doing all of the below if the allocated and pushed
131  // stuff will be really used
132  if ((doFBBT_ && problem_ -> doFBBT ()) ||
133  (doConvCuts_ && simulate_ && cutGen_)) {
134 
135  problem_ -> domain () -> push (nvars,
136  solver -> getColSolution (),
137  solver -> getColLower (),
138  solver -> getColUpper ()); // have to alloc+copy
139 
140  t_chg_bounds *chg_bds = new t_chg_bounds [nvars];
141 
142  if (!sign_) {
143  chg_bds [index].setLower (t_chg_bounds::CHANGED);
144  chg_bds [index].setUpper (t_chg_bounds::CHANGED);
145  } else {
146  chg_bds [ind0].setLower (t_chg_bounds::CHANGED);
147  chg_bds [ind0].setUpper (t_chg_bounds::CHANGED);
148 
149  chg_bds [ind1].setLower (t_chg_bounds::CHANGED);
150  chg_bds [ind1].setUpper (t_chg_bounds::CHANGED);
151  }
152 
153  if ( doFBBT_ && // this branching object should do FBBT, and
154  problem_ -> doFBBT ()) { // problem allowed to do FBBT
155 
156  problem_ -> installCutOff ();
157 
158  if (!problem_ -> btCore (chg_bds)) // done FBBT and this branch is infeasible
159  infeasible = true; // ==> report it
160  else {
161 
162  const double
163  *lb = solver -> getColLower (),
164  *ub = solver -> getColUpper ();
165 
166  //CouNumber newEst = problem_ -> Lb (objind) - lb [objind];
167  estimate = CoinMax (0., objind >= 0 ? problem_ -> Lb (objind) - lb [objind] : 0.);
168 
169  //if (newEst > estimate)
170  //estimate = newEst;
171 
172  for (int i=0; i<nvars; i++) {
173  if (problem_ -> Lb (i) > lb [i]) solver -> setColLower (i, problem_ -> Lb (i));
174  if (problem_ -> Ub (i) < ub [i]) solver -> setColUpper (i, problem_ -> Ub (i));
175  }
176  }
177  }
178 
179  if (!infeasible && doConvCuts_ && simulate_ && cutGen_) {
180  // generate convexification cuts before solving new node's LP
181 
182  int nchanged, *changed = NULL;
183  OsiCuts cs;
184 
185  // sparsify structure with info on changed bounds and get convexification cuts
186  sparse2dense (nvars, chg_bds, changed, nchanged);
187  cutGen_ -> genRowCuts (*solver, cs, nchanged, changed, chg_bds);
188  free (changed);
189 
190  solver -> applyCuts (cs);
191  }
192 
193  delete [] chg_bds;
194 
195  problem_ -> domain () -> pop ();
196  }
197 
198  // next time do other branching
199  branchIndex_++;
200 
201  return (infeasible ? COIN_DBL_MAX : estimate); // estimated change in objective function
202 }
Cut Generator for linear convexifications.
CouenneProblem * problem_
Pointer to CouenneProblem (necessary to allow FBBT)
CouenneCutGenerator * cutGen_
Pointer to CouenneCutGenerator (if any); if not NULL, allows to do extra cut generation during branch...
JnlstPtr jnlst_
SmartPointer to the Journalist.
virtual double branch(OsiSolverInterface *solver=NULL)
Execute the actions required to branch, as specified by the current state of the branching object...
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
void setLower(ChangeStatus lower)
void sparse2dense(int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged)
translate sparse to dense vector (should be replaced)
&quot;Spatial&quot; branching object.
const Ipopt::EJournalCategory J_BRANCHING(Ipopt::J_USER1)
void sparse2dense(int ncols, t_chg_bounds *chg_bds, int *&changed, int &nchanged)
translate sparse to dense vector (should be replaced)
void setUpper(ChangeStatus upper)
bool doFBBT_
shall we do Feasibility based Bound Tightening (FBBT) at branching?
Class for MINLP problems with symbolic information.
static const int infeasible
Definition: Couenne.cpp:68
double CouNumber
main number type in Couenne
bool simulate_
are we currently in strong branching?
expression * variable_
The index of the variable this branching object refers to.
Expression base class.
bool doConvCuts_
shall we add convexification cuts at branching?
real c
expression * variable2_
use CouenneBranchingObject::variable_ as the first variable to set to 0, and this one as the second ...
int sign_
-1 if object is for xi * xj &lt;= 0 +1 if object is for xi * xj &lt;= 0 0 if object is for xi * xj = 0 (cla...