testIntFix.cpp
Go to the documentation of this file.
1 /* $Id: testIntFix.cpp 767 2011-08-26 02:20:08Z pbelotti $
2  *
3  * Name: testIntFix.cpp
4  * Author: Pietro Belotti
5  * Purpose: select rounding for integer variable based on tightening
6  *
7  * (C) Carnegie-Mellon University, 2008-09.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include "CoinHelperFunctions.hpp"
12 #include "CouenneProblem.hpp"
13 #include "CouenneProblemElem.hpp"
14 
15 using namespace Couenne;
16 
17 // test if fixing a variable yields an infeasible (or dually
18 // infeasible) problem
20  CouNumber xFrac,
21  enum fixType *fixed,
22  CouNumber *xInt,
23  CouNumber *dualL, CouNumber *dualR,
24  CouNumber *olb, CouNumber *oub,
25  bool patient) const {
26  int
27  ncols = nVars (),
28  retval = 0,
29  objind = Obj (0) -> Body () -> Index ();
30 
31  // create fictitious change structure -- all initialized at UNCHANGED by constructor
32  t_chg_bounds *f_chg = new t_chg_bounds [ncols];
33 
34  double
35  *llb = new double [ncols], *lub = new double [ncols], // new bounds when rounding down
36  *rlb = new double [ncols], *rub = new double [ncols], // up
37  dualBound = objind >= 0 ? Lb (objind) : Obj (0) -> Body () -> Value ();
38 
39  // try rounding down ///////////////////////////////////////////////////////////////////////
40 
41  Lb (index) = Ub (index) = floor (xFrac);
42 
43  // useless
44  /*for (int j = 0; j<ncols; j++) {
45  f_chg [j].setLower (t_chg_bounds::UNCHANGED);
46  f_chg [j].setUpper (t_chg_bounds::UNCHANGED);
47  }*/
48 
49  f_chg [index].setLower (t_chg_bounds::CHANGED);
50  f_chg [index].setUpper (t_chg_bounds::CHANGED);
51 
52  bool feasLeft = btCore (f_chg); // true if feasible with fake bound
53 
54  dualL [index] = dualBound;
55 
56  // save new bounds
57  CoinCopyN (Lb (), ncols, llb);
58  CoinCopyN (Ub (), ncols, lub);
59 
60  // restore initial situation
61  CoinCopyN (olb, ncols, Lb ());
62  CoinCopyN (oub, ncols, Ub ());
63 
64  // try rounding up ///////////////////////////////////////////////////////////////////////
65 
66  Lb (index) = Ub (index) = ceil (xFrac);
67 
68  for (int j = 0; j<ncols; j++) {
71  }
72 
73  f_chg [index].setLower (t_chg_bounds::CHANGED);
74  f_chg [index].setUpper (t_chg_bounds::CHANGED);
75 
76  bool feasRight = btCore (f_chg); // true if feasible with fake bound
77 
78  dualR [index] = dualBound;
79 
80  // save new bounds
81  CoinCopyN (Lb (), ncols, rlb);
82  CoinCopyN (Ub (), ncols, rub);
83 
84  // restore initial situation
85  CoinCopyN (olb, ncols, Lb ());
86  CoinCopyN (oub, ncols, Ub ());
87 
89 
90  // Three cases:
91  //
92  // 1) if at least one is infeasible, set x_i to other
93  //
94  // 2) if both are infeasible, apply normal aggressive BT:
95  // 2a) if both infeasible, node is infeasible
96  // 2b) if both feasible, store index in free++ variables
97  // 2c) if only one feasible, set rounded +/- 2
98  // ...
99  // 2z) or probably simpler if return -1 to avoid calling Ipopt
100  //
101  // 3) if both feasible, choose one based on dual bound
102 
103  if (!feasLeft)
104 
105  if (!feasRight) {
106 
107  jnlst_ -> Printf (Ipopt::J_MOREVECTOR, J_NLPHEURISTIC,
108  "test on %d -> Infeasible.\n ", index);
109  retval = -1; // case 2
110 
111  } else {
112 
113  // ceil is feasible, floor is not.
114  jnlst_ -> Printf (Ipopt::J_MOREVECTOR, J_NLPHEURISTIC,
115  "test on %d -> Right feasible, fix to %g.\n", index, ceil (xFrac));
116 
117  fixed [index] = FIXED;
118  Lb (index) = Ub (index) = olb [index] = oub [index] = xInt [index] = ceil (xFrac);
119  //printf ("0 fixed %d [%g,%g,%g]\n", i, Lb (i), Ub (i), xInt [i]);
120  retval++;
121  //printf ("+++ 1 %d\n", i);
122 
123  // tighten bounds using r[lu]b
124  for (int j=0; j<ncols; j++) if (index != j) {
125 
126  olb [j] = Lb (j) = CoinMax (Lb (j), rlb [j]);
127  oub [j] = Ub (j) = CoinMin (Ub (j), rub [j]);
128 
129  if (Lb (j) > Ub (j) + COUENNE_EPS)
130  retval = -1;
131  }
132  }
133  else if (!feasRight) {
134 
135  // floor is feasible, ceil is not.
136  jnlst_ -> Printf (Ipopt::J_MOREVECTOR, J_NLPHEURISTIC,
137  "test on %d -> Left feasible, fix to %g.\n", index, floor (xFrac));
138 
139  fixed [index] = FIXED;
140  Lb (index) = Ub (index) = olb [index] = oub [index] = xInt [index] = floor (xFrac);
141  //printf ("1 fixed %d [%g,%g,%g]\n", i, Lb (i), Ub (i), xInt [i]);
142  retval++;
143  //printf ("+++ 2 %d\n", i);
144 
145  // tighten bounds using l[lu]b
146  for (int j=0; j<ncols; j++) if (index != j) {
147 
148  olb [j] = Lb (j) = CoinMax (Lb (j), llb [j]);
149  oub [j] = Ub (j) = CoinMin (Ub (j), lub [j]);
150 
151  if (Lb (j) > Ub (j) + COUENNE_EPS) {
152  retval = -1;
153  break;
154  }
155  }
156  } else { // case 3: tighten to smallest interval containing both [llb,lub] and [rlb,rub]
157 
158  // tighten bounds using l[lu]b
159  for (int j=0; j<ncols; j++) {
160 
161  olb [j] = Lb (j) = CoinMax (Lb (j), CoinMin (llb [j], rlb [j]));
162  oub [j] = Ub (j) = CoinMin (Ub (j), CoinMax (lub [j], rub [j]));
163 
164  if (Lb (j) > Ub (j) + COUENNE_EPS) {
165  retval = -1;
166  break;
167  }
168  }
169 
170  if ((retval >= 0) && !patient) { // too much time spent here, just fix it based on dual bound
171 
172  fixed [index] = FIXED;
173 
174  Lb (index) = Ub (index) = olb [index] = oub [index] = xInt [index] =
175  ((dualL [index] < dualR [index] - COUENNE_EPS) ? floor (xFrac) :
176  (dualL [index] > dualR [index] + COUENNE_EPS) ? ceil (xFrac) :
177  ((CoinDrand48 () < 0.5) ? floor (xFrac) : ceil (xFrac)));
178 
179  jnlst_ -> Printf (Ipopt::J_MOREVECTOR, J_NLPHEURISTIC,
180  "test on %d -> Both feasible, lost patience, fixed to %g.\n",
181  index, xInt [index]);
182 
183  //printf ("1 fixed %d [%g,%g,%g]\n", i, Lb (i), Ub (i), xInt [i]);
184  retval++;
185  //printf ("+++ 2 %d\n", i);
186  } else if (retval >= 0) jnlst_ -> Printf (Ipopt::J_MOREVECTOR, J_NLPHEURISTIC,
187  "test on %d -> Both feasible, skip this turn.\n", index);
188  }
189 
190  delete [] f_chg;
191 
192  delete [] llb; delete [] lub;
193  delete [] rlb; delete [] rub;
194 
195  return retval;
196 }
int nVars() const
Total number of variables.
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
void setLower(ChangeStatus lower)
static char * j
Definition: OSdtoa.cpp:3622
void setUpper(ChangeStatus upper)
int testIntFix(int index, CouNumber xFrac, enum fixType *fixed, CouNumber *xInt, CouNumber *dualL, CouNumber *dualR, CouNumber *olb, CouNumber *oub, bool patient) const
Test fixing of an integer variable (used in getIntegerCandidate())
Definition: testIntFix.cpp:19
bool btCore(t_chg_bounds *chg_bds) const
core of the bound tightening procedure
#define COUENNE_EPS
CouNumber * Ub() const
Return vector of upper bounds.
double CouNumber
main number type in Couenne
fixType
structure to record fixed, non-fixed, and continuous variables
const Ipopt::EJournalCategory J_NLPHEURISTIC(Ipopt::J_USER5)
JnlstPtr jnlst_
SmartPointer to the Journalist.
CouenneObjective * Obj(int i) const
i-th objective
CouNumber * Lb() const
Return vector of lower bounds.