11 #include "CglCutGenerator.hpp"
17 using namespace Ipopt;
18 using namespace Couenne;
42 csi -> setDblParam (OsiDualObjectiveLimit, COIN_DBL_MAX);
43 csi -> setDblParam (OsiPrimalObjectiveLimit, (sense==1) ? bound : -bound);
53 if (csi -> isProvenOptimal ()) {
55 double opt = csi -> getObjValue ();
58 {
if (opt > bound +
OBBT_EPS) {bound = (isint ? ceil (opt -
COUENNE_EPS) : opt);
return true;}}
59 else {
if ((opt=-opt) < bound -
OBBT_EPS) {bound = (isint ? floor (opt +
COUENNE_EPS) : opt);
return true;}}
68 int CouenneProblem::obbt_iter (OsiSolverInterface *csi,
70 const CoinWarmStart *warmstart,
92 for (
int i=nVars(); i--; knownOptimum++)
94 if (*knownOptimum < Lb (i) ||
95 *knownOptimum > Ub (i)) {
102 knownOptimum -= nVars ();
105 std::set <int> deplist;
108 bool issimple =
false;
113 objind = Obj (0) -> Body () -> Index (),
114 ncols = csi -> getNumCols (),
117 if ((var -> Type () ==
AUX) &&
118 ((deplistsize = var -> Image () -> DepList (deplist,
STOP_AT_AUX)) <= 1)) {
122 CouNumber value = (*(var -> Image ())) ();
124 if (csi -> getColLower () [index] < value -
COUENNE_EPS) {
125 csi -> setColLower (index, value);
126 chg_bds [index].
setLowerBits(t_chg_bounds::CHANGED | t_chg_bounds::EXACT);
130 if (csi -> getColUpper () [index] > value +
COUENNE_EPS) {
131 csi -> setColUpper (index, value);
132 chg_bds [index].
setUpperBits(t_chg_bounds::CHANGED | t_chg_bounds::EXACT);
141 int indInd = *(deplist.begin ());
147 ((((chg_bds [indInd].
lower() & t_chg_bounds::EXACT) &&
148 (chg_bds [indInd].upper() & t_chg_bounds::EXACT)) ||
151 (var -> Image () -> Linearity () <=
LINEAR)) &&
152 (var -> sign () == expression::AUX_EQ)) {
157 var -> Image () -> getBounds (lb, ub);
159 if (lb < Lb (index)) lb = Lb (index);
160 if (ub > Ub (index)) ub = Ub (index);
167 if (lb > csi -> getColLower () [index] +
COUENNE_EPS) {
168 csi -> setColLower (index, lb);
170 chg_bds [index].
setLowerBits(t_chg_bounds::CHANGED | t_chg_bounds::EXACT);
171 }
else chg_bds [index].
setLowerBits(t_chg_bounds::EXACT);
173 if (ub < csi -> getColUpper () [index] -
COUENNE_EPS) {
174 csi -> setColUpper (index, ub);
176 chg_bds [index].
setUpperBits(t_chg_bounds::CHANGED | t_chg_bounds::EXACT);
177 }
else chg_bds [index].
setUpperBits(t_chg_bounds::EXACT);
184 ((Var (index) -> Type () ==
VAR) ||
185 (Var (index) -> Multiplicity () > 0)) &&
190 || ((sense == 1) && !(chg_bds [index].lower() & t_chg_bounds::EXACT))
194 bool isInt = (Var (index) ->
isInteger ());
196 objcoe [index] = sense;
198 csi -> setObjective (objcoe);
199 csi -> setObjSense (1);
203 for (
int iv=0; iv<csi->getNumCols (); iv++) {
204 if (fabs (csi -> getColLower () [iv]) > 1e7) csi -> setColLower (iv, -1e14);
205 if (fabs (csi -> getColUpper () [iv]) > 1e7) csi -> setColUpper (iv, 1e14);
230 csi -> setWarmStart (warmstart);
256 bool has_updated =
false;
266 "#### OBBT cuts optimum at x%d: lb = %g, opt = %g, new lb = %g\n",
267 index, Lb (index), knownOptimum [index], bound);
271 "#### OBBT cuts optimum at x%d: ub = %g, opt = %g, new ub = %g\n",
272 index, Ub (index), knownOptimum [index], bound);
276 if (sense == 1) {
if (bound > Lb (index)) Lb (index) = bound;}
277 else {
if (bound < Ub (index)) Ub (index) = bound;}
282 if (csi -> getColLower () [index] < bound -
COUENNE_EPS) {
284 index, csi -> getColLower () [index], bound);
285 csi -> setColLower (index, bound);
286 chg_bds [index].
setLowerBits(t_chg_bounds::CHANGED | t_chg_bounds::EXACT);
287 }
else chg_bds [index].
setLowerBits(t_chg_bounds::EXACT);
289 if (csi -> getColUpper () [index] > bound +
COUENNE_EPS) {
291 index, csi -> getColUpper () [index], bound);
292 csi -> setColUpper (index, bound);
293 chg_bds [index].
setUpperBits(t_chg_bounds::CHANGED | t_chg_bounds::EXACT);
294 }
else chg_bds [index].
setUpperBits(t_chg_bounds::EXACT);
310 for (
int j=0;
j<ncols;
j++)
311 if ((
j!=index) && (
j!=objind)) {
319 if (!(chg_bds [
j].lower & EXACT)) {
322 if (!(chg_bds [
j].upper & EXACT)) {
332 " OBBT: x_%d: [%g, %g]\n", index,
333 csi -> getColLower () [index],
334 csi -> getColUpper () [index]);
339 if (doFBBT_ && !(btCore (chg_bds))) {
341 "node is infeasible after post-OBBT tightening\n");
351 const double *sol = csi -> getColSolution ();
353 for (
int j=0;
j<ncols;
j++)
354 if ((
j!=index) && (
j!=objind)) {
392 Jnlst () -> Printf (J_ITERSUMMARY,
J_BOUNDTIGHTENING,
"OBBT: tightened ", nImprov);
393 Var (index) -> print ();
status of lower/upper bound of a variable, to be checked/modified in bound tightening ...
const char & lower() const
static bool obbt_updateBound(OsiSolverInterface *csi, int sense, CouNumber &bound, bool isint)
1: minimize, -1: maximize
const Ipopt::EJournalCategory J_BOUNDTIGHTENING(Ipopt::J_USER2)
double CouNumber
main number type in Couenne
int obbt_supplement(const OsiSolverInterface *csi, int index, int sense)
void setUpperBits(char upper)
void setLowerBits(char lower)
Bonmin class for passing info between components of branch-and-cuts.
bool isInteger(CouNumber x)
is this number integer?