tightenBounds.cpp
Go to the documentation of this file.
1 /* $Id: tightenBounds.cpp 1258 2018-08-28 10:23:28Z pbelotti $
2  *
3  * Name: tightenBounds.cpp
4  * Author: Pietro Belotti
5  * Purpose: bound tightening for current linear relaxation
6  *
7  * (C) Carnegie-Mellon University, 2006-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CglCutGenerator.hpp"
12 #include "CouenneCutGenerator.hpp"
13 #include "CouenneProblem.hpp"
14 #include "CouenneExprVar.hpp"
15 
16 using namespace Ipopt;
17 using namespace Couenne;
18 
20 
21 int CouenneProblem::tightenBounds (t_chg_bounds *chg_bds) const {
22 
23  int nchg = 0; //< number of bounds changed for propagation
24 
25  // update bounding box (which may depend on the original
26  // variables' box) for the variables whose bound is looser.
27 
28  // check all auxiliary variables for changes in their upper,
29  // lower bound, depending on the bound changes of the variables
30  // they depend on
31 
32  CouNumber *knownOptimum = optimum_;
33 
34  if (optimum_) {
35 
36  for (int i=nVars(); i--; knownOptimum++)
37 
38  if (*knownOptimum < Lb (i) ||
39  *knownOptimum > Ub (i)) {
40 
41  knownOptimum = NULL;
42  break;
43  }
44 
45  if (knownOptimum)
46  knownOptimum -= nVars ();
47  }
48 
49  bool dbgOutput = Jnlst () -> ProduceOutput (J_DETAILED, J_BOUNDTIGHTENING);
50 
51  if (dbgOutput) {
52  // ToDo: Pipe all output through journalist
53  Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING, " forward =====================\n ");
54  int j=0;
55  for (int i=0; i < nVars (); i++)
56  if (variables_ [i] -> Multiplicity () > 0) {
57  Jnlst()->Printf(J_VECTOR, J_BOUNDTIGHTENING,
58  "x_%03d [%+10g %+10g] ", i,
59  domain_. lb (i),
60  domain_. ub (i));
61  if (!(++j % 6)) Jnlst()->Printf(J_VECTOR, J_BOUNDTIGHTENING,"\n ");
62  }
63  if (j % 6) Jnlst()->Printf(J_VECTOR, J_BOUNDTIGHTENING,"\n");
64  }
65 
66  for (int ii = 0, j = nVars (); j--; ii++) {
67 
68  int i = numbering_ [ii];
69 
70  exprVar *var = Var (i);
71 
72  if (var -> Multiplicity () <= 0)
73  continue;
74 
75  CouNumber &lower_i = Lb (i);
76  CouNumber &upper_i = Ub (i);
77 
78  // early test to avoid a loop
79 
80  if ((fabs (upper_i) < COIN_DBL_MAX / 10) &&
81  (fabs (lower_i) < COIN_DBL_MAX / 10) &&
82  (lower_i > upper_i + COUENNE_BOUND_PREC * (1 + CoinMin (fabs (lower_i), fabs (upper_i))))) {
83  // (upper_i < - MAX_BOUND) ||
84  // (lower_i > MAX_BOUND)) {
85 
86  if (Jnlst()->ProduceOutput(J_ITERSUMMARY, J_BOUNDTIGHTENING)) {
87 
88  Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
89  "pre-check: w_%d has infeasible bounds [%.10e,%.10e]. ", i, lower_i, upper_i);
90 
91  if (dbgOutput) {
92 
93  var -> Lb () -> print (std::cout);
94  Jnlst () -> Printf (J_DETAILED, J_BOUNDTIGHTENING," --- ");
95  var -> Ub () -> print (std::cout);
96  }
97 
98  Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,"\n");
99  }
100 
101  return -1; // declare this node infeasible
102  }
103 
104  /*if ((var -> Type () == VAR) &&
105  (var -> isInteger ())) {
106  lower_i = ceil (lower_i - COUENNE_EPS);
107  upper_i = floor (upper_i + COUENNE_EPS);
108  }*/
109 
110  if (var -> Type () != AUX)
111  continue;
112 
113  // TODO: also test if any indep variable of this expression
114  // have changed. If not, skip
115 
116  CouNumber ll, uu;
117  //ll = (*(variables_ [i] -> Lb ())) (),
118  //uu = (*(variables_ [i] -> Ub ())) ();
119 
120  var -> Image () -> getBounds (ll, uu);
121 
122  if (var -> isInteger ()) {
123  if (var -> sign () != expression::AUX_LEQ) ll = ceil (ll - COUENNE_EPS);
124  if (var -> sign () != expression::AUX_GEQ) uu = floor (uu + COUENNE_EPS);
125  }
126 
127  if (var -> sign () == expression::AUX_LEQ) ll = (*(var -> Lb ())) ();
128  else if (var -> sign () == expression::AUX_GEQ) uu = (*(var -> Ub ())) ();
129 
130  if (ll - uu > COUENNE_BOUND_PREC * (1 + CoinMin (fabs (ll), fabs (uu)))) {
131 
132  //if (Jnlst()->ProduceOutput(J_ITERSUMMARY, J_BOUNDTIGHTENING)) {
133 
134  Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,
135  "w_%d has infeasible bounds [%g,%g]: ", i, ll, uu);
136 
137  if (dbgOutput) {
138  var -> Lb () -> print (std::cout);
139  Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING," --- ");
140  var -> Ub () -> print (std::cout);
141  }
142 
143  Jnlst()->Printf(J_ITERSUMMARY, J_BOUNDTIGHTENING,"\n");
144  //}
145 
146  return -1; // declare this node infeasible
147  }
148 
149  // Enter the sign of this auxiliary: if defined as w <= f(x),
150  // then the lower bound on f(x) shouldn't be propagated to
151  // w. similarly, if defined as w >= f(x), then the same should
152  // hold for the upper bound.
153 
154  if (var -> sign () == expression::AUX_LEQ) ll = -COUENNE_INFINITY;
155  if (var -> sign () == expression::AUX_GEQ) uu = COUENNE_INFINITY;
156 
157  // check if lower bound has tightened
158  if ((ll > - COUENNE_INFINITY) &&
159  (ll >= lower_i + COUENNE_EPS) &&
160  ((fabs (ll) < COUENNE_EPS) ||
161  (fabs (lower_i) < COUENNE_EPS) ||
162  (fabs (ll / (lower_i) - 1) > COUENNE_EPS)) ) {
163 
164  if (dbgOutput) {
165 
166  Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,
167  " prop L %2d [%g,(%g)] -> [%g,(%g)] (%g) ",
168  i, lower_i, upper_i, ll, uu, lower_i - ll);
169  var -> print (std::cout);
170 
171  if (Jnlst()->ProduceOutput(J_MOREDETAILED, J_BOUNDTIGHTENING)) {
172  Jnlst()->Printf(J_MOREDETAILED, J_BOUNDTIGHTENING," := ");
173  var -> Image () -> print (std::cout);
174  }
175 
176  Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,"\n");
177 
178  if (knownOptimum &&
179  ((knownOptimum [i] - lower_i) / (1 + std::max (fabs (knownOptimum [i]), fabs (lower_i))) >= COUENNE_EPS) &&
180  ((knownOptimum [i] - ll) / (1 + std::max (fabs (knownOptimum [i]), fabs (ll))) <= -COUENNE_EPS)) {
181 
182  Jnlst()->Printf(J_STRONGWARNING, J_BOUNDTIGHTENING,
183  "Couenne: propagating l_%d cuts optimum: [%g --> %g -X-> %g] :: ",
184  i, lower_i, knownOptimum [i], ll);
185  var -> Lb () -> print (std::cout);
186  Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING," --- ");
187  var -> Ub () -> print (std::cout);
188  Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,"\n");
189  }
190  }
191 
192  lower_i = ll;
193 
194  if (ll > upper_i + COUENNE_BOUND_PREC * (1. + CoinMin (fabs (ll), fabs (upper_i)))) {
195  Jnlst () -> Printf (J_ITERSUMMARY, J_BOUNDTIGHTENING,
196  "just-check: w_%d has infeasible bounds [%g,%g]. ", i, lower_i, upper_i);
197  return -1;
198  }
199 
200  chg_bds [i].setLower (t_chg_bounds::CHANGED);
201  nchg++;
202  }
203 
204  // check if upper bound has tightened
205  if ((uu < COUENNE_INFINITY) &&
206  (uu <= upper_i - COUENNE_EPS) &&
207  ((fabs (uu) < COUENNE_EPS) ||
208  (fabs (upper_i) < COUENNE_EPS) ||
209  (fabs (uu / (upper_i) - 1) > COUENNE_EPS)) ) {
210  // if ((uu < COUENNE_INFINITY) && (uu <= ub_ [i+j] - COUENNE_EPS)) {
211 
212  /*printf ("update ubound %d: %.10e <= %.10e - %.12e (%.12e)\n",
213  i+j, uu, ub_ [i+j], COUENNE_EPS, uu - ub_ [i+j]);*/
214  /*printf ("update ubound %d: %g >= %g\n",
215  i+j, uu, ub_ [i+j]);*/
216 
217  if (dbgOutput) {
218 
219  Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,
220  " prop U %2d [(%g),%g] -> [(%g),%g] (%g) ",
221  i, lower_i, upper_i, ll, uu, upper_i - uu);
222  var -> print (std::cout);
223 
224  if (Jnlst()->ProduceOutput(J_VECTOR, J_BOUNDTIGHTENING)) {
225  Jnlst()->Printf(J_VECTOR, J_BOUNDTIGHTENING," := ");
226  var -> Image () -> print (std::cout);
227  }
228 
229  Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,"\n");
230 
231  if (knownOptimum &&
232  ((knownOptimum [i] - upper_i) / (1 + std::max (fabs (knownOptimum [i]), fabs (upper_i))) <= -COUENNE_EPS) &&
233  ((knownOptimum [i] - uu) / (1 + std::max (fabs (knownOptimum [i]), fabs (uu))) >= COUENNE_EPS)) {
234 
235  Jnlst()->Printf(J_STRONGWARNING, J_BOUNDTIGHTENING,
236  "Couenne: propagating u_%d cuts optimum: [%g <-X- %g <-- %g] :: ",
237  i, uu, knownOptimum [i], upper_i);
238  var -> Lb () -> print (std::cout);
239  Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING," --- ");
240  var -> Ub () -> print (std::cout);
241  Jnlst()->Printf(J_DETAILED, J_BOUNDTIGHTENING,"\n");
242  }
243  }
244 
245  upper_i = uu;
246 
247  if (uu < lower_i - COUENNE_BOUND_PREC) {
248  Jnlst () -> Printf (J_ITERSUMMARY, J_BOUNDTIGHTENING,
249  "just-check: w_%d has infeasible bounds [%g,%g]. ", i, lower_i, upper_i);
250  return -1;
251  }
252 
253  chg_bds [i].setUpper(t_chg_bounds::CHANGED);
254  nchg++;
255  }
256 
257  // useless if assume expression::[lu]b_ etc already point to
258  // problem::[lu]b_
259  }
260 
261  if (nchg)
262  Jnlst () -> Printf (J_ITERSUMMARY, J_BOUNDTIGHTENING,
263  " forward tightening %d changes\n", nchg);
264 
265  return nchg;
266 }
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
void setLower(ChangeStatus lower)
#define COUENNE_BOUND_PREC
static char * j
Definition: OSdtoa.cpp:3622
void setUpper(ChangeStatus upper)
const Ipopt::EJournalCategory J_BOUNDTIGHTENING(Ipopt::J_USER2)
#define COUENNE_EPS
double CouNumber
main number type in Couenne
fint ll
#define COUENNE_INFINITY
variable-type operator
bool isInteger(CouNumber x)
is this number integer?