Scippy

SCIP

Solving Constraint Integer Programs

cons_varbound.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_varbound.c
17  * @brief Constraint handler for variable bound constraints \f$lhs \le x + c y \le rhs\f$.
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Michael Winkler
21  * @author Gerald Gamrath
22  * @author Stefan Heinz
23  *
24  * This constraint handler handles a special type of linear constraints, namely variable bound constraints.
25  * A variable bound constraint has the form
26  * \f[
27  * lhs \leq x + c y \leq rhs
28  * \f]
29  * with coefficient \f$c \in Q\f$, \f$lhs\in Q \cup \{-\infty\}\f$, \f$rhs\in Q \cup \{\infty\}\f$,
30  * and decision variables \f$x\f$ (non-binary) and \f$y\f$ (binary or integer).
31  *
32  * @note Although x must be non-binary when the constraint is created, it can happen that x is upgraded to a binary
33  * variable, e.g. due to aggregations or bound changes in presolving.
34  */
35 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36 
37 #include <assert.h>
38 #include <string.h>
39 #include <limits.h>
40 #include <ctype.h>
41 
42 #include "scip/cons_varbound.h"
43 #include "scip/cons_linear.h"
44 #include "scip/cons_setppc.h"
45 
46 
47 /**@name Constraint handler properties
48  *
49  * @{
50  */
51 
52 /* constraint handler properties */
53 #define CONSHDLR_NAME "varbound"
54 #define CONSHDLR_DESC "variable bounds lhs <= x + c*y <= rhs, x non-binary, y non-continuous"
55 #define CONSHDLR_SEPAPRIORITY +900000 /**< priority of the constraint handler for separation */
56 #define CONSHDLR_ENFOPRIORITY -500000 /**< priority of the constraint handler for constraint enforcing */
57 #define CONSHDLR_CHECKPRIORITY -500000 /**< priority of the constraint handler for checking feasibility */
58 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
59 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
60 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
61  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
62 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
63 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
64 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
65 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
66 
67 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_MEDIUM)
68 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
69 
70 #define EVENTHDLR_NAME "varbound"
71 #define EVENTHDLR_DESC "bound change event handler for variable bound constraints"
72 
73 #define LINCONSUPGD_PRIORITY +50000 /**< priority of the constraint handler for upgrading of linear constraints */
74 
75 /**@} */
76 
77 /**@name Default parameter values
78  *
79  * @{
80  */
81 
82 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
83 #define DEFAULT_MAXLPCOEF 1e+09 /**< maximum coefficient in varbound constraint to be added as a row into LP */
84 #define DEFAULT_USEBDWIDENING TRUE /**< should bound widening be used to initialize conflict analysis? */
85 
86 
87 #define MAXSCALEDCOEF 1000LL /**< maximal coefficient value after scaling */
88 
89 /**@} */
90 
91 /** variable bound constraint data */
92 struct SCIP_ConsData
93 {
94  SCIP_Real vbdcoef; /**< coefficient c of bounding variable y */
95  SCIP_Real lhs; /**< left hand side of variable bound inequality */
96  SCIP_Real rhs; /**< right hand side of variable bound inequality */
97  SCIP_VAR* var; /**< variable x that has variable bound */
98  SCIP_VAR* vbdvar; /**< binary, integer or implicit integer bounding variable y */
99  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
100  unsigned int presolved:1; /**< is the variable bound constraint already presolved? */
101  unsigned int varboundsadded:1; /**< are the globally valid variable bounds added? */
102  unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
103  unsigned int tightened:1; /**< were the vbdcoef and all sides already tightened? */
104 };
105 
106 /** constraint handler data */
107 struct SCIP_ConshdlrData
108 {
109  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
110  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
111  SCIP_Real maxlpcoef; /**< maximum coefficient in varbound constraint to be added as a row into LP */
112  SCIP_Bool usebdwidening; /**< should bound widening be used to in conflict analysis? */
113 };
114 
115 /** Propagation rules */
116 enum Proprule
117 {
118  PROPRULE_1, /**< left hand side and bounds on y -> lower bound on x */
119  PROPRULE_2, /**< left hand side and upper bound on x -> bound on y */
120  PROPRULE_3, /**< right hand side and bounds on y -> upper bound on x */
121  PROPRULE_4 /**< right hand side and lower bound on x -> bound on y */
122 };
123 typedef enum Proprule PROPRULE;
125 
126 /**@name Local methods
127  *
128  */
129 
130 /** compares two varbound constraints cons1: \f$ lhs1 \le x1 + c1 y1 \le rhs1 \f$ and cons2: \f$ lhs2 \le x2 + c2 y2 \le rhs2 \f$
131  * w.r.t. the indices of the contained variables
132  *
133  * returns -1 if:
134  * - the index of x1 is smaller than the index of x2 or
135  * - x1 = x2 and the index of y1 is smaller than the index of y2 or
136  * - x1 = x2 and y1 = y2 and cons2 was recently changed, but cons1 not
137  *
138  * returns 0 if x1 = x2, y1 = y2, and the changed status of both constraints is the same
139  *
140  * and returns +1 otherwise
141  */
142 static
143 SCIP_DECL_SORTPTRCOMP(consVarboundComp)
144 {
145  SCIP_CONSDATA* consdata1;
146  SCIP_CONSDATA* consdata2;
147 
148  assert(elem1 != NULL);
149  assert(elem2 != NULL);
150 
151  consdata1 = SCIPconsGetData((SCIP_CONS*) elem1);
152  consdata2 = SCIPconsGetData((SCIP_CONS*) elem2);
153 
154  assert(consdata1 != NULL);
155  assert(consdata2 != NULL);
156 
157  /* comparison is done over 3 ordered criteria:
158  * (i) variable index of variable 1
159  * (ii) variable index of variable 2.
160  * (iii) changed status
161  */
162  if( SCIPvarGetIndex(consdata1->var) < SCIPvarGetIndex(consdata2->var)
163  || (SCIPvarGetIndex(consdata1->var) == SCIPvarGetIndex(consdata2->var)
164  && SCIPvarGetIndex(consdata1->vbdvar) < SCIPvarGetIndex(consdata2->vbdvar))
165  || (SCIPvarGetIndex(consdata1->var) == SCIPvarGetIndex(consdata2->var)
166  && SCIPvarGetIndex(consdata1->vbdvar) == SCIPvarGetIndex(consdata2->vbdvar)
167  && !consdata1->changed && consdata2->changed) )
168  return -1;
169  else if( SCIPvarGetIndex(consdata1->var) == SCIPvarGetIndex(consdata2->var)
170  && SCIPvarGetIndex(consdata1->vbdvar) == SCIPvarGetIndex(consdata2->vbdvar)
171  && (consdata1->changed == consdata2->changed) )
172  return 0;
173  else
174  return +1;
175 }
176 
177 /** creates constraint handler data for varbound constraint handler */
178 static
180  SCIP* scip, /**< SCIP data structure */
181  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
182  SCIP_EVENTHDLR* eventhdlr /**< event handler */
183  )
184 {
185  assert(scip != NULL);
186  assert(conshdlrdata != NULL);
187 
188  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
189 
190  /* set event handler for bound change events */
191  (*conshdlrdata)->eventhdlr = eventhdlr;
192 
193  return SCIP_OKAY;
194 }
195 
196 /** frees constraint handler data for varbound constraint handler */
197 static
198 void conshdlrdataFree(
199  SCIP* scip, /**< SCIP data structure */
200  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
201  )
202 {
203  assert(scip != NULL);
204  assert(conshdlrdata != NULL);
205  assert(*conshdlrdata != NULL);
206 
207  SCIPfreeBlockMemory(scip, conshdlrdata);
208 }
209 
210 /** catches events for variables
211  *
212  * @todo if lhs or rhs is infinite, catch only changes of the bound that could lead to propagation
213  */
214 static
216  SCIP* scip, /**< SCIP data structure */
217  SCIP_CONS* cons, /**< variable bound constraint */
218  SCIP_EVENTHDLR* eventhdlr /**< event handler */
219  )
220 {
221  SCIP_CONSDATA* consdata;
222  assert(cons != NULL);
223  assert(eventhdlr != NULL);
224  consdata = SCIPconsGetData(cons);
225  assert(consdata != NULL);
226 
227  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->var, SCIP_EVENTTYPE_BOUNDTIGHTENED | SCIP_EVENTTYPE_VARFIXED, eventhdlr, (SCIP_EVENTDATA*)cons, NULL) );
228  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vbdvar, SCIP_EVENTTYPE_BOUNDTIGHTENED | SCIP_EVENTTYPE_VARFIXED, eventhdlr, (SCIP_EVENTDATA*)cons, NULL) );
229 
230  return SCIP_OKAY;
231 }
232 
233 /** drops events for variables */
234 static
236  SCIP* scip, /**< SCIP data structure */
237  SCIP_CONS* cons, /**< variable bound constraint */
238  SCIP_EVENTHDLR* eventhdlr /**< event handler */
239  )
240 {
241  SCIP_CONSDATA* consdata;
242  assert(cons != NULL);
243  assert(eventhdlr != NULL);
244  consdata = SCIPconsGetData(cons);
245  assert(consdata != NULL);
246 
247  SCIP_CALL( SCIPdropVarEvent(scip, consdata->var, SCIP_EVENTTYPE_BOUNDTIGHTENED | SCIP_EVENTTYPE_VARFIXED, eventhdlr, (SCIP_EVENTDATA*)cons, -1) );
248  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vbdvar, SCIP_EVENTTYPE_BOUNDTIGHTENED | SCIP_EVENTTYPE_VARFIXED, eventhdlr, (SCIP_EVENTDATA*)cons, -1) );
249 
250  return SCIP_OKAY;
251 }
252 
253 /** creates a variable bound constraint data object */
254 static
256  SCIP* scip, /**< SCIP data structure */
257  SCIP_CONSDATA** consdata, /**< pointer to store the variable bound constraint data */
258  SCIP_VAR* var, /**< variable x that has variable bound */
259  SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
260  SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
261  SCIP_Real lhs, /**< left hand side of variable bound inequality */
262  SCIP_Real rhs /**< right hand side of variable bound inequality */
263  )
264 {
265  assert(consdata != NULL);
266  assert(SCIPvarGetType(vbdvar) != SCIP_VARTYPE_CONTINUOUS);
267 
268  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
269 
270  if( SCIPisInfinity(scip, rhs) )
271  rhs = SCIPinfinity(scip);
272  else if( SCIPisInfinity(scip, -rhs) )
273  rhs = -SCIPinfinity(scip);
274 
275  if( SCIPisInfinity(scip, -lhs) )
276  lhs = -SCIPinfinity(scip);
277  else if( SCIPisInfinity(scip, lhs) )
278  lhs = SCIPinfinity(scip);
279 
280  if( SCIPisGT(scip, lhs, rhs) )
281  {
282  SCIPerrorMessage("left hand side of varbound constraint greater than right hand side\n");
283  SCIPerrorMessage(" -> lhs=%g, rhs=%g\n", lhs, rhs);
284  return SCIP_INVALIDDATA;
285  }
286 
287  if( SCIPisZero(scip, vbdcoef) )
288  {
289  SCIPerrorMessage("varbound coefficient must be different to zero.\n");
290  return SCIP_INVALIDDATA;
291  }
292 
293  if( SCIPisInfinity(scip, vbdcoef) )
294  vbdcoef = SCIPinfinity(scip);
295  else if( SCIPisInfinity(scip, -vbdcoef) )
296  vbdcoef = -SCIPinfinity(scip);
297 
298  (*consdata)->var = var;
299  (*consdata)->vbdvar = vbdvar;
300  (*consdata)->vbdcoef = vbdcoef;
301  (*consdata)->lhs = lhs;
302  (*consdata)->rhs = rhs;
303  (*consdata)->row = NULL;
304  (*consdata)->presolved = FALSE;
305  (*consdata)->varboundsadded = FALSE;
306  (*consdata)->changed = TRUE;
307  (*consdata)->tightened = FALSE;
308 
309  /* if we are in the transformed problem, get transformed variables, add variable bound information, and catch events */
310  if( SCIPisTransformed(scip) )
311  {
312  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->var, &(*consdata)->var) );
313  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->vbdvar, &(*consdata)->vbdvar) );
314 
315 #ifndef NDEBUG
316  assert(SCIPvarGetStatus(SCIPvarGetProbvar((*consdata)->var)) != SCIP_VARSTATUS_MULTAGGR);
317  assert(SCIPvarGetStatus(SCIPvarGetProbvar((*consdata)->vbdvar)) != SCIP_VARSTATUS_MULTAGGR);
318 #endif
319  }
320 
321  /* capture variables */
322  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->var) );
323  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vbdvar) );
324 
325  return SCIP_OKAY;
326 }
327 
328 /** frees a variable bound constraint data */
329 static
331  SCIP* scip, /**< SCIP data structure */
332  SCIP_CONSDATA** consdata /**< pointer to the variable bound constraint */
333  )
334 {
335  assert(consdata != NULL);
336  assert(*consdata != NULL);
337 
338  /* release the row */
339  if( (*consdata)->row != NULL )
340  {
341  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
342  }
343 
344  /* release variables */
345  SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->var) );
346  SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->vbdvar) );
347 
348  SCIPfreeBlockMemory(scip, consdata);
349 
350  return SCIP_OKAY;
351 }
352 
353 /** creates LP row corresponding to variable bound constraint */
354 static
356  SCIP* scip, /**< SCIP data structure */
357  SCIP_CONS* cons /**< variable bound constraint */
358  )
359 {
360  SCIP_CONSDATA* consdata;
361 
362  consdata = SCIPconsGetData(cons);
363  assert(consdata != NULL);
364  assert(consdata->row == NULL);
365 
366  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, SCIPconsGetHdlr(cons), SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
368  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->var, 1.0) );
369  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->vbdvar, consdata->vbdcoef) );
370 
371  return SCIP_OKAY;
372 }
373 
374 /** adds linear relaxation of variable bound constraint to the LP */
375 static
377  SCIP* scip, /**< SCIP data structure */
378  SCIP_CONS* cons, /**< variable bound constraint */
379  SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected */
380  )
381 {
382  SCIP_CONSHDLR* conshdlr;
383  SCIP_CONSHDLRDATA* conshdlrdata;
384  SCIP_CONSDATA* consdata;
385 
386  consdata = SCIPconsGetData(cons);
387  assert(consdata != NULL);
388 
389  /* find the variable bound constraint handler */
390  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
391  if( conshdlr == NULL )
392  {
393  SCIPerrorMessage("variable bound constraint handler not found\n");
394  return SCIP_PLUGINNOTFOUND;
395  }
396 
397  conshdlrdata = SCIPconshdlrGetData(conshdlr);
398  assert(conshdlrdata != NULL);
399 
400  assert(SCIPvarGetType(consdata->vbdvar) != SCIP_VARTYPE_CONTINUOUS);
401 
402  /* check whether the coefficient is too large to put the row into the LP */
403  if( SCIPisGT(scip, REALABS(consdata->vbdcoef), conshdlrdata->maxlpcoef) )
404  return SCIP_OKAY;
405 
406  if( consdata->row == NULL )
407  {
408  SCIP_CALL( createRelaxation(scip, cons) );
409  }
410  assert(consdata->row != NULL);
411 
412  if( !SCIProwIsInLP(consdata->row) )
413  {
414  SCIPdebugMsg(scip, "adding relaxation of variable bound constraint <%s>: ", SCIPconsGetName(cons));
415  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
416  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, infeasible) );
417  }
418 
419  return SCIP_OKAY;
420 }
421 
422 /** returns whether the given solution is feasible for the given variable bound constraint */
423 static
425  SCIP* scip, /**< SCIP data structure */
426  SCIP_CONS* cons, /**< variable bound constraint */
427  SCIP_SOL* sol, /**< solution to check, NULL for current solution */
428  SCIP_Bool checklprows /**< Do constraints represented by rows in the current LP have to be checked? */
429  )
430 {
431  SCIP_CONSDATA* consdata;
432  SCIP_Real solval;
433  SCIP_Real absviol;
434  SCIP_Real relviol;
435 
436  consdata = SCIPconsGetData(cons);
437  assert(consdata != NULL);
438 
439  SCIPdebugMsg(scip, "checking variable bound constraint <%s> for feasibility of solution %p (lprows=%u)\n",
440  SCIPconsGetName(cons), (void*)sol, checklprows);
441 
442  solval = SCIPgetSolVal(scip, sol, consdata->var);
443 
444  if( SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vbdvar)) && (!SCIPisFeasLE(scip, solval, consdata->rhs) || !SCIPisFeasGE(scip, solval, consdata->lhs)) )
445  return FALSE;
446 
447 
448  if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
449  {
450  SCIP_Real sum;
451  SCIP_Real lhsrelviol;
452  SCIP_Real rhsrelviol;
453 
454  sum = solval + consdata->vbdcoef * SCIPgetSolVal(scip, sol, consdata->vbdvar);
455 
456  /* calculate constraint violation and update it in solution */
457  absviol = MAX(consdata->lhs - sum, sum - consdata->rhs);
458  lhsrelviol = SCIPrelDiff(consdata->lhs, sum);
459  rhsrelviol = SCIPrelDiff(sum, consdata->rhs);
460  relviol = MAX(lhsrelviol, rhsrelviol);
461  if( sol != NULL )
462  SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
463 
464  return (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasGE(scip, sum, consdata->lhs))
465  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasLE(scip, sum, consdata->rhs));
466  }
467  else
468  return TRUE;
469 }
470 
471 
472 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
473  * propagation rule (see propagateCons()):
474  * (1) left hand side and bounds on y -> lower bound on x
475  * (2) left hand side and upper bound on x -> bound on y
476  * (3) right hand side and bounds on y -> upper bound on x
477  * (4) right hand side and lower bound on x -> bound on y
478  */
479 static
481  SCIP* scip, /**< SCIP data structure */
482  SCIP_CONS* cons, /**< constraint that inferred the bound change */
483  SCIP_VAR* infervar, /**< variable that was deduced */
484  PROPRULE proprule, /**< propagation rule that deduced the bound change */
485  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
486  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
487  SCIP_Real inferbd, /**< inference bound which needs to be explained */
488  SCIP_Bool usebdwidening /**< should bound widening be used to in conflict analysis? */
489  )
490 {
491  SCIP_CONSDATA* consdata;
492  SCIP_VAR* vbdvar;
493  SCIP_VAR* var;
494  SCIP_Real vbdcoef;
495 
496  consdata = SCIPconsGetData(cons);
497  assert(consdata != NULL);
498  assert(!SCIPisZero(scip, consdata->vbdcoef));
499 
500  var = consdata->var;
501  assert(var != NULL);
502 
503  vbdvar = consdata->vbdvar;
504  assert(vbdvar != NULL);
505 
506  vbdcoef = consdata->vbdcoef;
507  assert(!SCIPisZero(scip, vbdcoef));
508 
509  switch( proprule )
510  {
511  case PROPRULE_1:
512  /* lhs <= x + c*y: left hand side and bounds on y -> lower bound on x */
513  assert(infervar == var);
514  assert(boundtype == SCIP_BOUNDTYPE_LOWER);
515  assert(!SCIPisInfinity(scip, -consdata->lhs));
516 
517  if( usebdwidening )
518  {
519  SCIP_Real relaxedbd;
520 
521  /* For integer variables, we can reduce the inferbound by 1 - z * eps, because this will be adjusted
522  * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
523  * too small and too large vbdcoef values.
524  * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
525  * arithmetics, so we explicitly check this here.
526  */
527  if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
528  && REALABS(consdata->lhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
529  relaxedbd = (consdata->lhs - (inferbd - 1.0 + 2.0* SCIPfeastol(scip))) / vbdcoef;
530  else
531  relaxedbd = (consdata->lhs - inferbd) / vbdcoef;
532 
533  /* check the computed relaxed lower/upper bound is a proper reason for the inference bound which has to be explained */
534  assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarLb(scip, var, consdata->lhs - relaxedbd * vbdcoef)));
535 
536  if( vbdcoef > 0.0 )
537  {
538  /* decrease the computed relaxed upper bound by an epsilon; this ensures that we get the actual
539  * inference bound due to the integrality condition of the variable bound variable
540  */
541  relaxedbd -= SCIPfeastol(scip);
542  SCIP_CALL( SCIPaddConflictRelaxedUb(scip, vbdvar, bdchgidx, relaxedbd) );
543  }
544  else
545  {
546  /* increase the computed relaxed lower bound by an epsilon; this ensures that we get the actual inference
547  * bound due to the integrality condition of the variable bound variable
548  */
549  relaxedbd += SCIPfeastol(scip);
550  SCIP_CALL( SCIPaddConflictRelaxedLb(scip, vbdvar, bdchgidx, relaxedbd) );
551  }
552  }
553  else
554  {
555  if( vbdcoef > 0.0 )
556  {
557  SCIP_CALL( SCIPaddConflictUb(scip, vbdvar, bdchgidx) );
558  }
559  else
560  {
561  SCIP_CALL( SCIPaddConflictLb(scip, vbdvar, bdchgidx) );
562  }
563  }
564 
565  break;
566 
567  case PROPRULE_2:
568  /* lhs <= x + c*y: left hand side and upper bound on x -> bound on y */
569  assert(infervar == vbdvar);
570  assert(SCIPvarGetType(vbdvar) != SCIP_VARTYPE_CONTINUOUS);
571  assert(!SCIPisInfinity(scip, -consdata->lhs));
572 
573  if( usebdwidening )
574  {
575  SCIP_Real relaxedub;
576 
577  /* compute the relaxed upper bound of the variable which would be sufficient to reach one less (greater) than the
578  * inference bound
579  */
580  if( vbdcoef > 0.0 )
581  {
582  /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
583  * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
584  * too small and too large vbdcoef values.
585  * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
586  * arithmetics, so we explicitly check this here.
587  */
588  if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
589  && REALABS(consdata->rhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
590  relaxedub = consdata->lhs - (inferbd - 1.0 + 2.0 * SCIPfeastol(scip)) * vbdcoef;
591  else
592  relaxedub = consdata->lhs - inferbd * vbdcoef;
593 
594  /* check the computed relaxed upper bound is a proper reason for the inference bound which has to be explained */
595  assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarLb(scip, vbdvar, (consdata->lhs - relaxedub) / vbdcoef)));
596  }
597  else
598  {
599  /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
600  * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
601  * too small and too large vbdcoef values.
602  * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
603  * arithmetics, so we explicitly check this here.
604  */
605  if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
606  && REALABS(consdata->lhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
607  relaxedub = consdata->lhs - (inferbd + 1.0 - 2.0 * SCIPfeastol(scip)) * vbdcoef;
608  else
609  relaxedub = consdata->lhs - inferbd * vbdcoef;
610 
611  /* check the computed relaxed upper bound is a proper reason for the inference bound which has to be explained */
612  assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarUb(scip, vbdvar, (consdata->lhs - relaxedub) / vbdcoef)));
613  }
614 
615  /* decrease the computed relaxed upper bound by an epsilon; this ensures that we get the actual inference bound due
616  * to the integrality condition of the variable bound variable
617  */
618  relaxedub -= SCIPfeastol(scip);
619 
620  SCIP_CALL( SCIPaddConflictRelaxedUb(scip, var, bdchgidx, relaxedub) );
621  }
622  else
623  {
624  SCIP_CALL( SCIPaddConflictUb(scip, var, bdchgidx) );
625  }
626 
627  break;
628 
629  case PROPRULE_3:
630  /* x + c*y <= rhs: right hand side and bounds on y -> upper bound on x */
631  assert(infervar == var);
632  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
633  assert(!SCIPisInfinity(scip, consdata->rhs));
634 
635  if( usebdwidening )
636  {
637  SCIP_Real relaxedbd;
638 
639  /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
640  * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
641  * too small and too large vbdcoef values.
642  * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
643  * arithmetics, so we explicitly check this here.
644  */
645  if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
646  && REALABS(consdata->rhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
647  relaxedbd = (consdata->rhs - (inferbd + 1.0 - 2.0 * SCIPfeastol(scip))) / vbdcoef;
648  else
649  relaxedbd = (consdata->rhs - inferbd) / vbdcoef;
650 
651  /* check the computed relaxed lower/upper bound is a proper reason for the inference bound which has to be explained */
652  assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarUb(scip, var, consdata->rhs - relaxedbd * vbdcoef)));
653 
654  if( vbdcoef > 0.0 )
655  {
656  /* increase the computed relaxed lower bound by an epsilon; this ensures that we get the actual inference bound due
657  * to the integrality condition of the variable bound variable
658  */
659  relaxedbd += SCIPfeastol(scip);
660  SCIP_CALL( SCIPaddConflictRelaxedLb(scip, vbdvar, bdchgidx, relaxedbd) );
661  }
662  else
663  {
664  /* decrease the computed relaxed upper bound by an epsilon; this ensures that we get the actual inference bound due
665  * to the integrality condition of the variable bound variable
666  */
667  relaxedbd -= SCIPfeastol(scip);
668  SCIP_CALL( SCIPaddConflictRelaxedUb(scip, vbdvar, bdchgidx, relaxedbd) );
669  }
670  }
671  else
672  {
673  if( vbdcoef > 0.0 )
674  {
675  SCIP_CALL( SCIPaddConflictLb(scip, vbdvar, bdchgidx) );
676  }
677  else
678  {
679  SCIP_CALL( SCIPaddConflictUb(scip, vbdvar, bdchgidx) );
680  }
681  }
682 
683  break;
684 
685  case PROPRULE_4:
686  /* x + c*y <= rhs: right hand side and lower bound on x -> bound on y */
687  assert(infervar == vbdvar);
688  assert(SCIPvarGetType(vbdvar) != SCIP_VARTYPE_CONTINUOUS);
689  assert(!SCIPisInfinity(scip, consdata->rhs));
690 
691  if( usebdwidening )
692  {
693  SCIP_Real relaxedlb;
694 
695  /* compute the relaxed lower bound of the variable which would be sufficient to reach one greater (less) than the
696  * inference bound
697  */
698  if( vbdcoef > 0.0 )
699  {
700  /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
701  * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
702  * too small and too large vbdcoef values.
703  * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
704  * arithmetics, so we explicitly check this here.
705  */
706  if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
707  && REALABS(consdata->rhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
708  relaxedlb = consdata->rhs - (inferbd + 1.0 - 2.0 * SCIPfeastol(scip)) * vbdcoef;
709  else
710  relaxedlb = consdata->rhs - inferbd * vbdcoef;
711 
712  /* check the computed relaxed lower bound is a proper reason for the inference bound which has to be explained */
713  assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarUb(scip, vbdvar, (consdata->rhs - relaxedlb) / vbdcoef)));
714  }
715  else
716  {
717  /* For integer variables, we can reduce the inferbound by 1-z*eps, because this will be adjusted
718  * to the bound we need; however, we need to choose z large enough to prevent numerical troubles due to
719  * too small and too large vbdcoef values.
720  * If inferbound has a large value, adding z*eps might be lost due to fixed precision floating point
721  * arithmetics, so we explicitly check this here.
722  */
723  if( SCIPvarIsIntegral(var) && inferbd < SCIPgetHugeValue(scip) * SCIPfeastol(scip)
724  && REALABS(consdata->lhs) < SCIPgetHugeValue(scip) * SCIPfeastol(scip) )
725  relaxedlb = consdata->rhs - (inferbd - 1.0 + 2.0 * SCIPfeastol(scip)) * vbdcoef;
726  else
727  relaxedlb = consdata->rhs - inferbd * vbdcoef;
728 
729  /* check the computed relaxed lower bound is a proper reason for the inference bound which has to be explained */
730  assert(SCIPisEQ(scip, inferbd, SCIPadjustedVarLb(scip, vbdvar, (consdata->rhs - relaxedlb) / vbdcoef)));
731  }
732 
733  /* increase the computed relaxed lower bound by an epsilon; this ensures that we get the actual inference bound due
734  * to the integrality condition of the variable bound variable
735  */
736  relaxedlb += SCIPfeastol(scip);
737 
738  SCIP_CALL( SCIPaddConflictRelaxedLb(scip, var, bdchgidx, relaxedlb) );
739  }
740  else
741  {
742  SCIP_CALL( SCIPaddConflictLb(scip, var, bdchgidx) );
743  }
744 
745  break;
746 
747  default:
748  SCIPerrorMessage("invalid inference information %d in variable bound constraint <%s>\n", proprule, SCIPconsGetName(cons));
749  return SCIP_INVALIDDATA;
750  }
751 
752  return SCIP_OKAY;
753 }
754 
755 /** analyze infeasibility */
756 static
758  SCIP* scip, /**< SCIP data structure */
759  SCIP_CONS* cons, /**< variable bound constraint */
760  SCIP_VAR* infervar, /**< variable that was deduced */
761  SCIP_Real inferbd, /**< bound which led to infeasibility */
762  PROPRULE proprule, /**< propagation rule that deduced the bound change */
763  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
764  SCIP_Bool usebdwidening /**< should bound widening be used to in conflict analysis? */
765  )
766 {
767  /* conflict analysis can only be applied in solving stage and if it is applicable */
769  return SCIP_OKAY;
770 
771  /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
773 
774  /* add the bound which got violated */
775  if( boundtype == SCIP_BOUNDTYPE_LOWER )
776  {
777  if( usebdwidening )
778  {
779  SCIP_Real relaxedub;
780 
781  /* adjust lower bound */
782  inferbd = SCIPadjustedVarLb(scip, infervar, inferbd);
783 
784  /* compute a relaxed upper bound which would be sufficient to be still infeasible */
785  if( SCIPvarIsIntegral(infervar) )
786  relaxedub = inferbd - 1.0;
787  else
788  {
789  SCIP_CONSDATA* consdata;
790  SCIP_Real abscoef;
791 
792  consdata = SCIPconsGetData(cons);
793  assert(consdata != NULL);
794 
795  /* vbdvar can never be of non-integral type */
796  assert(infervar == consdata->var);
797 
798  abscoef = REALABS(consdata->vbdcoef);
799 
800  /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
801  * is big enough, therefore we multiply here with the vbdcoef
802  *
803  * @note it does not matter if we deceed the current local upper bound, because SCIPaddConflictRelaxedUb()
804  * is correcting the bound afterwards
805  */
806  relaxedub = inferbd - 2*SCIPfeastol(scip) * MAX(1, abscoef);
807  }
808 
809  /* try to relax inference variable upper bound such that the infeasibility is still given */
810  SCIP_CALL( SCIPaddConflictRelaxedUb(scip, infervar, NULL, relaxedub) );
811 
812  /* collect the upper bound which is reported to the conflict analysis */
813  inferbd = SCIPgetConflictVarUb(scip, infervar);
814 
815  /* adjust inference bound with respect to the upper bound reported to the conflict analysis */
816  if( SCIPvarIsIntegral(infervar) )
817  inferbd = inferbd + 1.0;
818  else
819  {
820  SCIP_CONSDATA* consdata;
821  SCIP_Real abscoef;
822 
823  consdata = SCIPconsGetData(cons);
824  assert(consdata != NULL);
825 
826  /* vbdvar can never be of non-integral type */
827  assert(infervar == consdata->var);
828 
829  abscoef = REALABS(consdata->vbdcoef);
830 
831  /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
832  * is big enough, therefore we multiply here with the vbdcoef
833  */
834  inferbd = inferbd + 2*SCIPfeastol(scip) * MAX(1, abscoef);
835  }
836  }
837  else
838  {
839  SCIP_CALL( SCIPaddConflictUb(scip, infervar, NULL) );
840  }
841  }
842  else
843  {
844  if( usebdwidening )
845  {
846  SCIP_Real relaxedlb;
847 
848  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
849 
850  /* adjust upper bound */
851  inferbd = SCIPadjustedVarUb(scip, infervar, inferbd);
852 
853  /* compute a relaxed lower bound which would be sufficient to be still infeasible */
854  if( SCIPvarIsIntegral(infervar) )
855  relaxedlb = inferbd + 1.0;
856  else
857  {
858  SCIP_CONSDATA* consdata;
859  SCIP_Real abscoef;
860 
861  consdata = SCIPconsGetData(cons);
862  assert(consdata != NULL);
863 
864  /* vbdvar can never be of non-integral type */
865  assert(infervar == consdata->var);
866 
867  abscoef = REALABS(consdata->vbdcoef);
868 
869  /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
870  * is big enough, therefore we multiply here with the vbdcoef
871  *
872  * @note it does not matter if we exceed the current local lower bound, because SCIPaddConflictRelaxedLb()
873  * is correcting the bound afterwards
874  */
875  relaxedlb = inferbd + 2*SCIPfeastol(scip) * MAX(1, abscoef);
876  }
877 
878  /* try to relax inference variable upper bound such that the infeasibility is still given */
879  SCIP_CALL( SCIPaddConflictRelaxedLb(scip, infervar, NULL, relaxedlb) );
880 
881  /* collect the lower bound which is reported to the conflict analysis */
882  inferbd = SCIPgetConflictVarLb(scip, infervar);
883 
884  /* adjust inference bound with respect to the lower bound reported to the conflict analysis */
885  if( SCIPvarIsIntegral(infervar) )
886  inferbd = inferbd - 1.0;
887  else
888  {
889  SCIP_CONSDATA* consdata;
890  SCIP_Real abscoef;
891 
892  consdata = SCIPconsGetData(cons);
893  assert(consdata != NULL);
894 
895  /* vbdvar can never be of non-integral type */
896  assert(infervar == consdata->var);
897 
898  abscoef = REALABS(consdata->vbdcoef);
899 
900  /* due to resolving a the propagation and dividing by the vbdcoef we need to make sure the the relaxed bound
901  * is big enough, therefore we multiply here with the vbdcoef
902  */
903  inferbd = inferbd - 2*SCIPfeastol(scip) * MAX(1, abscoef);
904  }
905  }
906  else
907  {
908  SCIP_CALL( SCIPaddConflictLb(scip, infervar, NULL) );
909  }
910  }
911 
912  /* add the reason for the violated of the bound */
913  SCIP_CALL( resolvePropagation(scip, cons, infervar, proprule, boundtype, NULL, inferbd, usebdwidening) );
914 
915  /* analyze the conflict */
916  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
917 
918  return SCIP_OKAY;
919 }
920 
921 /** separates the given variable bound constraint */
922 static
924  SCIP* scip, /**< SCIP data structure */
925  SCIP_CONS* cons, /**< variable bound constraint */
926  SCIP_Bool usebdwidening, /**< should bound widening be used to in conflict analysis? */
927  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
928  SCIP_RESULT* result /**< pointer to store the result of the separation call */
929  )
930 {
931  SCIP_CONSHDLR* conshdlr;
932  SCIP_CONSDATA* consdata;
933  SCIP_VAR* vbdvar;
934  SCIP_VAR* var;
935  SCIP_Real vbdcoef;
936  SCIP_Real feasibility;
937 
938  assert(cons != NULL);
939  assert(result != NULL);
940 
941  consdata = SCIPconsGetData(cons);
942  assert(consdata != NULL);
943 
944  /* find the variable bound constraint handler */
945  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
946  if( conshdlr == NULL )
947  {
948  SCIPerrorMessage("variable bound constraint handler not found\n");
949  return SCIP_PLUGINNOTFOUND;
950  }
951 
952  SCIPdebugMsg(scip, "separating variable bound constraint <%s>\n", SCIPconsGetName(cons));
953 
954  var = consdata->var;
955  vbdvar = consdata->vbdvar;
956  vbdcoef = consdata->vbdcoef;
957  assert(SCIPvarGetType(vbdvar) != SCIP_VARTYPE_CONTINUOUS);
958 
959  if( SCIPvarGetLbLocal(vbdvar) + 0.5 > SCIPvarGetUbLocal(vbdvar) )
960  {
961  assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(vbdvar), SCIPvarGetUbLocal(vbdvar)));
962 
963  if( !SCIPisInfinity(scip, -consdata->lhs) )
964  {
965  SCIP_Real newlb;
966  SCIP_Bool cutoff;
967  SCIP_Bool tightened;
968 
969  newlb = consdata->lhs - vbdcoef * SCIPvarGetLbLocal(vbdvar);
970 
971  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, (int)PROPRULE_1, TRUE,
972  &cutoff, &tightened) );
973 
974  if( cutoff )
975  {
976  assert(SCIPisGT(scip, newlb, SCIPvarGetUbLocal(var)));
977 
978  /* analyze infeasibility */
979  SCIP_CALL( analyzeConflict(scip, cons, var, newlb, PROPRULE_1, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
980  *result = SCIP_CUTOFF;
981 
982  return SCIP_OKAY;
983  }
984  else if( tightened )
985  {
986  *result = SCIP_REDUCEDDOM;
987  }
988  }
989 
990  if( !SCIPisInfinity(scip, consdata->rhs) )
991  {
992  SCIP_Real newub;
993  SCIP_Bool cutoff;
994  SCIP_Bool tightened;
995 
996  newub = consdata->rhs - vbdcoef * SCIPvarGetLbLocal(vbdvar);
997 
998  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, (int)PROPRULE_3, TRUE,
999  &cutoff, &tightened) );
1000 
1001  if( cutoff )
1002  {
1003  assert(SCIPisLT(scip, newub, SCIPvarGetLbLocal(var)));
1004 
1005  /* analyze infeasibility */
1006  SCIP_CALL( analyzeConflict(scip, cons, var, newub, PROPRULE_3, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1007  *result = SCIP_CUTOFF;
1008 
1009  return SCIP_OKAY;
1010  }
1011  else if( tightened )
1012  {
1013  *result = SCIP_REDUCEDDOM;
1014  }
1015  }
1016  }
1017 
1018  /* if we already changed a bound or the coefficient is too large to put the row into the LP, stop here */
1019  if( *result == SCIP_REDUCEDDOM )
1020  return SCIP_OKAY;
1021 
1022  /* check constraint for feasibility and create row if constraint is violated */
1023  if( !checkCons(scip, cons, sol, (sol != NULL)) )
1024  {
1025  /* create LP relaxation if not yet existing */
1026  if( consdata->row == NULL )
1027  {
1028  SCIP_CALL( createRelaxation(scip, cons) );
1029  }
1030  assert(consdata->row != NULL);
1031 
1032  /* check non-LP rows for feasibility and add them as cut, if violated */
1033  if( !SCIProwIsInLP(consdata->row) )
1034  {
1035  feasibility = SCIPgetRowSolFeasibility(scip, consdata->row, sol);
1036  if( SCIPisFeasNegative(scip, feasibility) )
1037  {
1038  SCIP_Bool infeasible;
1039 
1040  SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, &infeasible) );
1041  if ( infeasible )
1042  *result = SCIP_CUTOFF;
1043  else
1044  *result = SCIP_SEPARATED;
1045  }
1046  }
1047  }
1048 
1049  return SCIP_OKAY;
1050 }
1051 
1052 /** sets left hand side of varbound constraint */
1053 static
1055  SCIP* scip, /**< SCIP data structure */
1056  SCIP_CONS* cons, /**< linear constraint */
1057  SCIP_Real lhs /**< new left hand side */
1058  )
1059 {
1060  SCIP_CONSDATA* consdata;
1061 
1062  assert(scip != NULL);
1063  assert(cons != NULL);
1064  assert(!SCIPisInfinity(scip, lhs));
1065 
1066  /* adjust value to not be smaller than -inf */
1067  if( SCIPisInfinity(scip, -lhs) )
1068  lhs = -SCIPinfinity(scip);
1069 
1070  consdata = SCIPconsGetData(cons);
1071  assert(consdata != NULL);
1072  assert(consdata->var != NULL && consdata->vbdvar != NULL);
1073  assert(!SCIPisInfinity(scip, consdata->lhs));
1074 
1075  /* check whether the side is not changed */
1076  if( SCIPisEQ(scip, consdata->lhs, lhs) )
1077  return SCIP_OKAY;
1078 
1079  assert(consdata->row == NULL);
1080 
1081  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
1082  if( SCIPisEQ(scip, lhs, consdata->rhs) )
1083  consdata->rhs = lhs;
1084 
1085  /* if necessary, update the rounding locks of variables */
1086  if( SCIPconsIsLocked(cons) )
1087  {
1088  assert(SCIPconsIsTransformed(cons));
1089 
1090  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
1091  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
1092  {
1093  SCIP_CALL( SCIPlockVarCons(scip, consdata->var, cons, TRUE, FALSE) );
1094 
1095  if( SCIPisPositive(scip, consdata->vbdcoef) )
1096  {
1097  SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1098  }
1099  else
1100  {
1101  SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1102  }
1103  }
1104  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
1105  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
1106  {
1107  SCIP_CALL( SCIPunlockVarCons(scip, consdata->var, cons, TRUE, FALSE) );
1108  if( SCIPisPositive(scip, consdata->vbdcoef) )
1109  {
1110  SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1111  }
1112  else
1113  {
1114  SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1115  }
1116  }
1117  }
1118 
1119  /* if left hand side got tighter, we want to do additional presolving on this constraint */
1120  if( SCIPisLT(scip, consdata->lhs, lhs) )
1121  {
1122  consdata->varboundsadded = FALSE;
1123  consdata->tightened = FALSE;
1124 
1125  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
1126  }
1127 
1128  consdata->presolved = FALSE;
1129  consdata->lhs = lhs;
1130  consdata->changed = TRUE;
1131 
1132  return SCIP_OKAY;
1133 }
1134 
1135 /** sets right hand side of varbound constraint */
1136 static
1138  SCIP* scip, /**< SCIP data structure */
1139  SCIP_CONS* cons, /**< linear constraint */
1140  SCIP_Real rhs /**< new right hand side */
1141  )
1142 {
1143  SCIP_CONSDATA* consdata;
1144 
1145  assert(scip != NULL);
1146  assert(cons != NULL);
1147  assert(!SCIPisInfinity(scip, -rhs));
1148 
1149  /* adjust value to not be larger than inf */
1150  if( SCIPisInfinity(scip, rhs) )
1151  rhs = SCIPinfinity(scip);
1152 
1153  consdata = SCIPconsGetData(cons);
1154  assert(consdata != NULL);
1155  assert(consdata->var != NULL && consdata->vbdvar != NULL);
1156  assert(!SCIPisInfinity(scip, -consdata->rhs));
1157 
1158  /* check whether the side is not changed */
1159  if( SCIPisEQ(scip, consdata->rhs, rhs) )
1160  return SCIP_OKAY;
1161 
1162  assert(consdata->row == NULL);
1163 
1164  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
1165  if( SCIPisEQ(scip, rhs, consdata->lhs) )
1166  consdata->lhs = rhs;
1167 
1168  /* if necessary, update the rounding locks of variables */
1169  if( SCIPconsIsLocked(cons) )
1170  {
1171  assert(SCIPconsIsTransformed(cons));
1172 
1173  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
1174  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
1175  {
1176  SCIP_CALL( SCIPlockVarCons(scip, consdata->var, cons, FALSE, TRUE) );
1177 
1178  if( SCIPisPositive(scip, consdata->vbdcoef) )
1179  {
1180  SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1181  }
1182  else
1183  {
1184  SCIP_CALL( SCIPlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1185  }
1186  }
1187  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
1188  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
1189  {
1190  SCIP_CALL( SCIPunlockVarCons(scip, consdata->var, cons, FALSE, TRUE) );
1191  if( SCIPisPositive(scip, consdata->vbdcoef) )
1192  {
1193  SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, FALSE, TRUE) );
1194  }
1195  else
1196  {
1197  SCIP_CALL( SCIPunlockVarCons(scip, consdata->vbdvar, cons, TRUE, FALSE) );
1198  }
1199  }
1200  }
1201 
1202  /* if right hand side got tighter, we want to do additional presolving on this constraint */
1203  if( SCIPisGT(scip, consdata->rhs, rhs) )
1204  {
1205  consdata->varboundsadded = FALSE;
1206  consdata->tightened = FALSE;
1207 
1208  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
1209  }
1210 
1211  consdata->presolved = FALSE;
1212  consdata->rhs = rhs;
1213  consdata->changed = TRUE;
1214 
1215  return SCIP_OKAY;
1216 }
1217 
1218 /** propagation method for variable bound constraint */
1219 static
1221  SCIP* scip, /**< SCIP data structure */
1222  SCIP_CONS* cons, /**< variable bound constraint */
1223  SCIP_Bool usebdwidening, /**< should bound widening be used to in conflict analysis? */
1224  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
1225  int* nchgbds, /**< pointer to count number of bound changes */
1226  int* nchgsides, /**< pointer to count number of side changes */
1227  int* ndelconss /**< pointer to count number of deleted constraints, or NULL */
1228  )
1229 {
1230  SCIP_CONSDATA* consdata;
1231  SCIP_Real xlb;
1232  SCIP_Real xub;
1233  SCIP_Real ylb;
1234  SCIP_Real yub;
1235  SCIP_Real newlb;
1236  SCIP_Real newub;
1237  SCIP_Bool tightened;
1238  SCIP_Bool tightenedround;
1239 
1240  assert(cutoff != NULL);
1241  assert(nchgbds != NULL);
1242 
1243  consdata = SCIPconsGetData(cons);
1244  assert(consdata != NULL);
1245 
1246  SCIPdebugMsg(scip, "propagating variable bound constraint <%s>: %.15g <= <%s>[%.9g, %.9g] + %.15g<%s>[%.9g, %.9g] <= %.15g\n",
1247  SCIPconsGetName(cons), consdata->lhs, SCIPvarGetName(consdata->var), SCIPvarGetLbLocal(consdata->var),
1248  SCIPvarGetUbLocal(consdata->var), consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
1249  SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), consdata->rhs);
1250 
1251  *cutoff = FALSE;
1252 
1253  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
1254  if( !SCIPinRepropagation(scip) )
1255  {
1256  SCIP_CALL( SCIPincConsAge(scip, cons) );
1257  }
1258 
1259  /* get current bounds of variables */
1260  xlb = SCIPvarGetLbLocal(consdata->var);
1261  xub = SCIPvarGetUbLocal(consdata->var);
1262  ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1263  yub = SCIPvarGetUbLocal(consdata->vbdvar);
1264 
1265  /* it can happen that constraint is of form lhs <= x <= rhs */
1266  if( SCIPisZero(scip, consdata->vbdcoef) && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1267  {
1268  SCIP_Bool infeasible;
1269  SCIP_Bool fixed;
1270 
1271  SCIP_CALL( SCIPfixVar(scip, consdata->var, consdata->lhs, &infeasible, &fixed) );
1272 
1273  if( infeasible )
1274  {
1275  SCIPdebugMsg(scip, "> constraint <%s> is infeasible.\n", SCIPconsGetName(cons));
1276  *cutoff = TRUE;
1277  return SCIP_OKAY;
1278  }
1279  }
1280 
1281  /* tighten bounds of variables as long as possible */
1282  do
1283  {
1284  tightenedround = FALSE;
1285 
1286  /* propagate left hand side inequality: lhs <= x + c*y */
1287  if( !SCIPisInfinity(scip, -consdata->lhs) )
1288  {
1289  assert(!(*cutoff));
1290 
1291  /* propagate bounds on x:
1292  * (1) left hand side and bounds on y -> lower bound on x
1293  */
1294  if( SCIPvarGetStatus(consdata->var) != SCIP_VARSTATUS_MULTAGGR ) /* cannot change bounds of multaggr vars */
1295  {
1296  if( consdata->vbdcoef > 0.0 )
1297  {
1298  if( !SCIPisInfinity(scip, yub) )
1299  newlb = SCIPadjustedVarLb(scip, consdata->var, consdata->lhs - consdata->vbdcoef * yub);
1300  else
1301  newlb = -SCIPinfinity(scip);
1302  }
1303  else
1304  {
1305  if( !SCIPisInfinity(scip, -ylb) )
1306  newlb = SCIPadjustedVarLb(scip, consdata->var, consdata->lhs - consdata->vbdcoef * ylb);
1307  else
1308  newlb = -SCIPinfinity(scip);
1309  }
1310 
1311  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->var, newlb, cons, (int)PROPRULE_1, yub < ylb + 0.5, cutoff, &tightened) );
1312 
1313  if( *cutoff )
1314  {
1315  SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, newlb, xub);
1316  assert( SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->var)) );
1317 
1318  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1319 
1320  /* analyze infeasibility */
1321  SCIP_CALL( analyzeConflict(scip, cons, consdata->var, newlb, PROPRULE_1, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1322  break;
1323  }
1324 
1325  if( tightened )
1326  {
1327  SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, newlb, xub);
1328  tightenedround = TRUE;
1329  (*nchgbds)++;
1330  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1331  }
1332  xlb = SCIPvarGetLbLocal(consdata->var);
1333  }
1334 
1335  assert(!*cutoff);
1336 
1337  /* propagate bounds on y:
1338  * (2) left hand side and upper bound on x -> bound on y
1339  */
1340  if( SCIPvarGetStatus(consdata->vbdvar) != SCIP_VARSTATUS_MULTAGGR && !SCIPisInfinity(scip, xub) ) /* cannot change bounds of multaggr vars */
1341  {
1342  if( consdata->vbdcoef > 0.0 )
1343  {
1344  newlb = SCIPadjustedVarLb(scip, consdata->vbdvar, (consdata->lhs - xub)/consdata->vbdcoef);
1345  if( newlb > ylb + 0.5 )
1346  {
1347  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vbdvar, newlb, cons, (int)PROPRULE_2, FALSE, cutoff, &tightened) );
1348 
1349  if( *cutoff )
1350  {
1351  SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1352  assert( SCIPisInfinity(scip, newlb) || SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->vbdvar)) );
1353 
1354  /* analyze infeasibility */
1355  SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newlb, PROPRULE_2, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1356  break;
1357  }
1358 
1359  if( tightened )
1360  {
1361  SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1362  tightenedround = TRUE;
1363  (*nchgbds)++;
1364  }
1365  ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1366  }
1367  }
1368  else
1369  {
1370  newub = SCIPadjustedVarUb(scip, consdata->vbdvar, (consdata->lhs - xub)/consdata->vbdcoef);
1371  if( newub < yub - 0.5 )
1372  {
1373  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vbdvar, newub, cons, (int)PROPRULE_2, FALSE, cutoff, &tightened) );
1374 
1375  if( *cutoff )
1376  {
1377  SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1378  assert( SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->vbdvar)) );
1379 
1380  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1381 
1382  /* analyze infeasibility */
1383  SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newub, PROPRULE_2, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1384  break;
1385  }
1386 
1387  if( tightened )
1388  {
1389  SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1390  tightenedround = TRUE;
1391  (*nchgbds)++;
1392  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1393  }
1394  yub = SCIPvarGetUbLocal(consdata->vbdvar);
1395  }
1396  }
1397  }
1398  }
1399 
1400  assert(!*cutoff);
1401 
1402  /* propagate right hand side inequality: x + c*y <= rhs */
1403  if( !SCIPisInfinity(scip, consdata->rhs) )
1404  {
1405  /* propagate bounds on x:
1406  * (3) right hand side and bounds on y -> upper bound on x
1407  */
1408  if( SCIPvarGetStatus(consdata->var) != SCIP_VARSTATUS_MULTAGGR ) /* cannot change bounds of multaggr vars */
1409  {
1410  if( consdata->vbdcoef > 0.0 )
1411  {
1412  if( !SCIPisInfinity(scip, -ylb) )
1413  newub = SCIPadjustedVarUb(scip, consdata->var, consdata->rhs - consdata->vbdcoef * ylb);
1414  else
1415  newub = SCIPinfinity(scip);
1416  }
1417  else
1418  {
1419  if( !SCIPisInfinity(scip, yub) )
1420  newub = SCIPadjustedVarUb(scip, consdata->var, consdata->rhs - consdata->vbdcoef * yub);
1421  else
1422  newub = SCIPinfinity(scip);
1423  }
1424 
1425  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->var, newub, cons, (int)PROPRULE_3, yub < ylb + 0.5, cutoff, &tightened) );
1426 
1427  if( *cutoff )
1428  {
1429  SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, xlb, newub);
1430  assert( SCIPisInfinity(scip, -newub) || SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->var)) );
1431 
1432  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1433 
1434  /* analyze infeasibility */
1435  SCIP_CALL( analyzeConflict(scip, cons, consdata->var, newub, PROPRULE_3, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1436  break;
1437  }
1438 
1439  if( tightened )
1440  {
1441  SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->var), xlb, xub, xlb, newub);
1442  tightenedround = TRUE;
1443  (*nchgbds)++;
1444  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1445  }
1446  xub = SCIPvarGetUbLocal(consdata->var);
1447  }
1448 
1449  assert(!*cutoff);
1450 
1451  /* propagate bounds on y:
1452  * (4) right hand side and lower bound on x -> bound on y
1453  */
1454  if( SCIPvarGetStatus(consdata->vbdvar) != SCIP_VARSTATUS_MULTAGGR && !SCIPisInfinity(scip, -xlb) ) /* cannot change bounds of multaggr vars */
1455  {
1456  if( consdata->vbdcoef > 0.0 )
1457  {
1458  newub = SCIPadjustedVarUb(scip, consdata->vbdvar, (consdata->rhs - xlb)/consdata->vbdcoef);
1459  if( newub < yub - 0.5 )
1460  {
1461  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vbdvar, newub, cons, (int)PROPRULE_4, FALSE, cutoff, &tightened) );
1462 
1463  if( *cutoff )
1464  {
1465  SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1466  assert(SCIPisLT(scip, newub, SCIPvarGetLbLocal(consdata->vbdvar)));
1467 
1468  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1469 
1470  /* analyze infeasibility */
1471  SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newub, PROPRULE_4, SCIP_BOUNDTYPE_UPPER, usebdwidening) );
1472  break;
1473  }
1474 
1475  if( tightened )
1476  {
1477  SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, ylb, newub);
1478  tightenedround = TRUE;
1479  (*nchgbds)++;
1480  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1481  }
1482  yub = SCIPvarGetUbLocal(consdata->vbdvar);
1483  }
1484  }
1485  else
1486  {
1487  newlb = SCIPadjustedVarLb(scip, consdata->vbdvar, (consdata->rhs - xlb)/consdata->vbdcoef);
1488  if( newlb > ylb + 0.5 )
1489  {
1490  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vbdvar, newlb, cons, (int)PROPRULE_4, FALSE, cutoff, &tightened) );
1491 
1492  if( *cutoff )
1493  {
1494  SCIPdebugMsg(scip, "cutoff while tightening <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1495  assert(SCIPisGT(scip, newlb, SCIPvarGetUbLocal(consdata->vbdvar)));
1496 
1497  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1498 
1499  /* analyze infeasibility */
1500  SCIP_CALL( analyzeConflict(scip, cons, consdata->vbdvar, newlb, PROPRULE_4, SCIP_BOUNDTYPE_LOWER, usebdwidening) );
1501  break;
1502  }
1503 
1504  if( tightened )
1505  {
1506  SCIPdebugMsg(scip, " -> tighten <%s>[%.15g,%.15g] -> [%.15g,%.15g]\n", SCIPvarGetName(consdata->vbdvar), ylb, yub, newlb, yub);
1507  tightenedround = TRUE;
1508  (*nchgbds)++;
1509  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1510  }
1511  ylb = SCIPvarGetLbLocal(consdata->vbdvar);
1512  }
1513  }
1514  }
1515  }
1516  assert(!(*cutoff));
1517  }
1518  while( tightenedround );
1519 
1520  /* check for redundant sides */
1521  if( !(*cutoff) && SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING && !SCIPinProbing(scip) )
1522  {
1523  /* check left hand side for redundancy */
1524  if( !SCIPisInfinity(scip, -consdata->lhs) &&
1525  ((consdata->vbdcoef > 0.0 && SCIPisFeasGE(scip, xlb + consdata->vbdcoef * ylb, consdata->lhs))
1526  || (consdata->vbdcoef < 0.0 && SCIPisFeasGE(scip, xlb + consdata->vbdcoef * yub, consdata->lhs))) )
1527  {
1528  SCIPdebugMsg(scip, "left hand side of variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
1529 
1530  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
1531  ++(*nchgsides);
1532  }
1533 
1534  /* check right hand side for redundancy */
1535  if( !SCIPisInfinity(scip, consdata->rhs) &&
1536  ((consdata->vbdcoef > 0.0 && SCIPisFeasLE(scip, xub + consdata->vbdcoef * yub, consdata->rhs))
1537  || (consdata->vbdcoef < 0.0 && SCIPisFeasLE(scip, xub + consdata->vbdcoef * ylb, consdata->rhs))) )
1538  {
1539  SCIPdebugMsg(scip, "right hand side of variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
1540 
1541  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
1542  ++(*nchgsides);
1543  }
1544  }
1545  /* check varbound constraint for redundancy */
1546  if( !(*cutoff) && (SCIPisInfinity(scip, -consdata->lhs)
1547  || (consdata->vbdcoef > 0.0 && SCIPisFeasGE(scip, xlb + consdata->vbdcoef * ylb, consdata->lhs))
1548  || (consdata->vbdcoef < 0.0 && SCIPisFeasGE(scip, xlb + consdata->vbdcoef * yub, consdata->lhs)))
1549  && (SCIPisInfinity(scip, consdata->rhs)
1550  || (consdata->vbdcoef > 0.0 && SCIPisFeasLE(scip, xub + consdata->vbdcoef * yub, consdata->rhs))
1551  || (consdata->vbdcoef < 0.0 && SCIPisFeasLE(scip, xub + consdata->vbdcoef * ylb, consdata->rhs))) )
1552  {
1553  SCIPdebugMsg(scip, "variable bound constraint <%s> is redundant: <%s>[%.15g,%.15g], <%s>[%.15g,%.15g]\n",
1554  SCIPconsGetName(cons),
1555  SCIPvarGetName(consdata->var), SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var),
1556  SCIPvarGetName(consdata->vbdvar), SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar));
1557  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1558 
1559  /* this did not seem to help but should be tested again, there might also still be a bug in there */
1560 #ifdef SCIP_DISABLED_CODE
1561  /* local duality fixing of variables in the constraint */
1562  if( !SCIPisNegative(scip, SCIPvarGetObj(consdata->vbdvar)) && SCIPvarGetNLocksDown(consdata->vbdvar) == 1
1563  && !SCIPisInfinity(scip, -SCIPvarGetLbLocal(consdata->vbdvar))
1564  && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar))
1565  && ((consdata->vbdcoef > 0.0 && !SCIPisInfinity(scip, -consdata->lhs))
1566  || (consdata->vbdcoef < 0.0 && !SCIPisInfinity(scip, consdata->rhs))) )
1567  {
1568  SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->vbdvar),
1569  SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), SCIPvarGetLbLocal(consdata->vbdvar));
1570  SCIP_CALL( SCIPchgVarUb(scip, consdata->vbdvar, SCIPvarGetLbLocal(consdata->vbdvar)) );
1571  }
1572  else if( !SCIPisPositive(scip, SCIPvarGetObj(consdata->vbdvar)) && SCIPvarGetNLocksUp(consdata->vbdvar) == 1
1573  && !SCIPisInfinity(scip, SCIPvarGetUbLocal(consdata->vbdvar))
1574  && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar))
1575  && ((consdata->vbdcoef < 0.0 && !SCIPisInfinity(scip, -consdata->lhs))
1576  || (consdata->vbdcoef > 0.0 && !SCIPisInfinity(scip, consdata->rhs))) )
1577  {
1578  SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->vbdvar),
1579  SCIPvarGetLbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar), SCIPvarGetUbLocal(consdata->vbdvar));
1580  SCIP_CALL( SCIPchgVarLb(scip, consdata->vbdvar, SCIPvarGetUbLocal(consdata->vbdvar)) );
1581  }
1582  if( !SCIPisNegative(scip, SCIPvarGetObj(consdata->var)) && SCIPvarGetNLocksDown(consdata->var) == 1
1583  && !SCIPisInfinity(scip, -SCIPvarGetLbLocal(consdata->var))
1584  && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var))
1585  && !SCIPisInfinity(scip, -consdata->lhs) )
1586  {
1587  SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->var),
1588  SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var), SCIPvarGetLbLocal(consdata->var));
1589  SCIP_CALL( SCIPchgVarUb(scip, consdata->var, SCIPvarGetLbLocal(consdata->var)) );
1590  }
1591  else if( !SCIPisPositive(scip, SCIPvarGetObj(consdata->var)) && SCIPvarGetNLocksUp(consdata->var) == 1
1592  && !SCIPisInfinity(scip, SCIPvarGetUbLocal(consdata->var))
1593  && SCIPisFeasLT(scip, SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var))
1594  && !SCIPisInfinity(scip, consdata->rhs) )
1595  {
1596  SCIPdebugMsg(scip, " --> fixing <%s>[%.15g,%.15g] to %.15g\n", SCIPvarGetName(consdata->var),
1597  SCIPvarGetLbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var), SCIPvarGetUbLocal(consdata->var));
1598  SCIP_CALL( SCIPchgVarLb(scip, consdata->var, SCIPvarGetUbLocal(consdata->var)) );
1599  }
1600 #endif
1601  if( ndelconss != NULL )
1602  (*ndelconss)++;
1603  }
1604 
1605  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
1606 
1607  return SCIP_OKAY;
1608 }
1609 
1610 /* check whether one constraints side is redundant to another constraints side by calculating extreme values for
1611  * variables
1612  */
1613 static
1614 void checkRedundancySide(
1615  SCIP* scip, /**< SCIP data structure */
1616  SCIP_VAR* var, /**< variable x that has variable bound */
1617  SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
1618  SCIP_Real coef0, /**< coefficient c0 of bounding variable y for constraint 0 */
1619  SCIP_Real coef1, /**< coefficient c1 of bounding variable y for constraint 1 */
1620  SCIP_Real side0, /**< one side of variable bound inequality for constraint 0 */
1621  SCIP_Real side1, /**< one side of variable bound inequality for constraint 1 */
1622  SCIP_Bool* sideequal, /**< pointer to store if both constraints have the same redundancy on the
1623  * given side */
1624  SCIP_Bool* cons0sidered, /**< pointer to store if side of constraint 0 is redundant */
1625  SCIP_Bool* cons1sidered, /**< pointer to store if side of constraint 1 is redundant */
1626  SCIP_Bool islhs /**< do we check the left or the right hand side */
1627  )
1628 {
1629  SCIP_Real lbvar;
1630  SCIP_Real ubvar;
1631  SCIP_Real lbvbdvar;
1632  SCIP_Real ubvbdvar;
1633  SCIP_Real boundxlb1;
1634  SCIP_Real boundxlb2;
1635  SCIP_Real boundylb1;
1636  SCIP_Real boundylb2;
1637  SCIP_Real boundxub1;
1638  SCIP_Real boundxub2;
1639  SCIP_Real boundyub1;
1640  SCIP_Real boundyub2;
1641  SCIP_Real boundvaluex1;
1642  SCIP_Real boundvaluex2;
1643  SCIP_Real boundvaluey1;
1644  SCIP_Real boundvaluey2;
1645  SCIP_Real valuex1;
1646  SCIP_Real valuex2;
1647  SCIP_Real valuey1;
1648  SCIP_Real valuey2;
1649  SCIP_Bool* redundant0;
1650  SCIP_Bool* redundant1;
1651  SCIP_Real eps = SCIPepsilon(scip);
1652 
1653  assert(scip != NULL);
1654  assert(var != NULL);
1655  assert(vbdvar != NULL);
1656  assert(sideequal != NULL);
1657  assert(cons0sidered != NULL);
1658  assert(cons1sidered != NULL);
1659 
1660  *cons0sidered = SCIPisInfinity(scip, REALABS(side0));
1661  *cons1sidered = SCIPisInfinity(scip, REALABS(side1));
1662  *sideequal = FALSE;
1663 
1664  if( islhs )
1665  {
1666  redundant0 = cons1sidered;
1667  redundant1 = cons0sidered;
1668  }
1669  else
1670  {
1671  redundant0 = cons0sidered;
1672  redundant1 = cons1sidered;
1673  }
1674 
1675  lbvar = SCIPvarGetLbGlobal(var);
1676  ubvar = SCIPvarGetUbGlobal(var);
1677  lbvbdvar = SCIPvarGetLbGlobal(vbdvar);
1678  ubvbdvar = SCIPvarGetUbGlobal(vbdvar);
1679 
1680  /* if both constraint have this side */
1681  if( !*redundant0 && !*redundant1 )
1682  {
1683  /* calculate extreme values, which are reached by setting the other variable to their lower/upper bound */
1684  boundxlb1 = side0 - lbvbdvar*coef0;
1685  boundxlb2 = side1 - lbvbdvar*coef1;
1686  boundylb1 = (side0 - lbvar)/coef0;
1687  boundylb2 = (side1 - lbvar)/coef1;
1688 
1689  boundxub1 = side0 - ubvbdvar*coef0;
1690  boundxub2 = side1 - ubvbdvar*coef1;
1691  boundyub1 = (side0 - ubvar)/coef0;
1692  boundyub2 = (side1 - ubvar)/coef1;
1693 
1694  if( islhs )
1695  {
1696  boundvaluex1 = MAX(boundxlb1, boundxlb2);
1697  boundvaluex2 = MAX(boundxub1, boundxub2);
1698  }
1699  else
1700  {
1701  boundvaluex1 = MIN(boundxlb1, boundxlb2);
1702  boundvaluex2 = MIN(boundxub1, boundxub2);
1703  }
1704 
1705  /* calculate important values for variables */
1706  if( SCIPisPositive(scip, coef0) )
1707  {
1708  valuex1 = MIN(boundvaluex1, ubvar);
1709  valuex1 = MAX(valuex1, lbvar);
1710  valuex2 = MAX(boundvaluex2, lbvar);
1711  valuex2 = MIN(valuex2, ubvar);
1712 
1713  /* if variable is of integral type make values integral too */
1715  {
1716  if( !SCIPisFeasIntegral(scip, valuex1) )
1717  valuex1 = SCIPfeasFloor(scip, valuex1);
1718  if( !SCIPisFeasIntegral(scip, valuex2) )
1719  valuex2 = SCIPfeasCeil(scip, valuex2);
1720  }
1721  }
1722  else
1723  {
1724  valuex1 = MAX(boundvaluex1, lbvar);
1725  valuex1 = MIN(valuex1, ubvar);
1726  valuex2 = MIN(boundvaluex2, ubvar);
1727  valuex2 = MAX(valuex2, lbvar);
1728 
1729  /* if variable is of integral type make values integral too */
1731  {
1732  if( !SCIPisFeasIntegral(scip, valuex1) )
1733  valuex1 = SCIPfeasCeil(scip, valuex1);
1734  if( !SCIPisFeasIntegral(scip, valuex2) )
1735  valuex2 = SCIPfeasFloor(scip, valuex2);
1736  }
1737  }
1738 
1739  /* calculate resulting values of variable y by setting x to valuex1 */
1740  valuey1 = (side0 - valuex1)/coef0;
1741  valuey2 = (side1 - valuex1)/coef1;
1742 
1743  /* determine redundancy of one constraints side */
1744  if( valuey1 - valuey2 <= eps )
1745  *sideequal = TRUE;
1746  else if( SCIPisPositive(scip, coef0) )
1747  {
1748  if( valuey1 < valuey2 )
1749  *redundant1 = TRUE;
1750  else
1751  *redundant0 = TRUE;
1752  }
1753  else
1754  {
1755  if( valuey1 < valuey2 )
1756  *redundant0 = TRUE;
1757  else
1758  *redundant1 = TRUE;
1759  }
1760 
1761  /* calculate resulting values of variable y by setting x to valuex2 */
1762  valuey1 = (side0 - valuex2)/coef0;
1763  valuey2 = (side1 - valuex2)/coef1;
1764 
1765  /* determine redundancy of one constraints side by checking for the first valuex2 */
1766  if( SCIPisPositive(scip, coef0) )
1767  {
1768  /* if both constraints are weaker than the other on one value, we have no redundancy */
1769  if( (*redundant1 && valuey1 > valuey2) || (*redundant0 && valuey1 < valuey2) )
1770  {
1771  *sideequal = FALSE;
1772  *redundant0 = FALSE;
1773  *redundant1 = FALSE;
1774  return;
1775  }
1776  else if( *sideequal )
1777  {
1778  if( valuey1 + eps < valuey2 )
1779  {
1780  *sideequal = FALSE;
1781  *redundant1 = TRUE;
1782  }
1783  else if( valuey1 + eps > valuey2 )
1784  {
1785  *sideequal = FALSE;
1786  *redundant0 = TRUE;
1787  }
1788  }
1789  }
1790  else
1791  {
1792  /* if both constraints are weaker than the other one on one value, we have no redundancy */
1793  if( (*redundant1 && valuey1 < valuey2) || (*redundant0 && valuey1 > valuey2) )
1794  {
1795  *sideequal = FALSE;
1796  *redundant0 = FALSE;
1797  *redundant1 = FALSE;
1798  return;
1799  }
1800  else if( *sideequal )
1801  {
1802  if( valuey1 + eps < valuey2 )
1803  {
1804  *sideequal = FALSE;
1805  *redundant0 = TRUE;
1806  }
1807  else if( valuey1 + eps > valuey2 )
1808  {
1809  *sideequal = FALSE;
1810  *redundant1 = TRUE;
1811  }
1812  }
1813  }
1814  assert(*sideequal || *redundant0 || *redundant1);
1815 
1816  /* calculate feasibility domain values for variable y concerning these both constraints */
1817  if( SCIPisPositive(scip, coef0) )
1818  {
1819  if( islhs )
1820  {
1821  boundvaluey1 = MAX(boundylb1, boundylb2);
1822  boundvaluey2 = MAX(boundyub1, boundyub2);
1823  }
1824  else
1825  {
1826  boundvaluey1 = MIN(boundylb1, boundylb2);
1827  boundvaluey2 = MIN(boundyub1, boundyub2);
1828  }
1829 
1830  valuey1 = MIN(boundvaluey1, ubvbdvar);
1831  valuey1 = MAX(valuey1, lbvbdvar);
1832  valuey2 = MAX(boundvaluey2, lbvbdvar);
1833  valuey2 = MIN(valuey2, ubvbdvar);
1834 
1835  if( !SCIPisFeasIntegral(scip, valuey1) )
1836  valuey1 = SCIPfeasFloor(scip, valuey1);
1837  if( !SCIPisFeasIntegral(scip, valuey2) )
1838  valuey2 = SCIPfeasCeil(scip, valuey2);
1839  }
1840  else
1841  {
1842  if( islhs )
1843  {
1844  boundvaluey1 = MIN(boundylb1, boundylb2);
1845  boundvaluey2 = MIN(boundyub1, boundyub2);
1846  }
1847  else
1848  {
1849  boundvaluey1 = MAX(boundylb1, boundylb2);
1850  boundvaluey2 = MAX(boundyub1, boundyub2);
1851  }
1852 
1853  valuey1 = MAX(boundvaluey1, lbvbdvar);
1854  valuey1 = MIN(valuey1, ubvbdvar);
1855  valuey2 = MIN(boundvaluey2, ubvbdvar);
1856  valuey2 = MAX(valuey2, lbvbdvar);
1857 
1858  /* if variable is of integral type make values integral too */
1859  if( !SCIPisFeasIntegral(scip, valuey1) )
1860  valuey1 = SCIPfeasCeil(scip, valuey1);
1861  if( !SCIPisFeasIntegral(scip, valuey2) )
1862  valuey2 = SCIPfeasFloor(scip, valuey2);
1863  }
1864 
1865  /* calculate resulting values of variable x by setting y to valuey1 */
1866  valuex1 = side0 - valuey1*coef0;
1867  valuex2 = side1 - valuey1*coef1;
1868 
1869  /* determine redundancy of one constraints side by checking for the first valuey1 */
1870  if( (*redundant1 && valuex1 > valuex2) || (*redundant0 && valuex1 < valuex2) )
1871  {
1872  *sideequal = FALSE;
1873  *redundant0 = FALSE;
1874  *redundant1 = FALSE;
1875  return;
1876  }
1877  if( *sideequal )
1878  {
1879  if( valuex1 + eps < valuex2 )
1880  {
1881  *sideequal = FALSE;
1882  *redundant1 = TRUE;
1883  }
1884  else if( valuex1 + eps > valuex2 )
1885  {
1886  *sideequal = FALSE;
1887  *redundant0 = TRUE;
1888  }
1889  }
1890 
1891  /* calculate resulting values of variable x by setting y to valuey2 */
1892  valuex1 = side0 - valuey2*coef0;
1893  valuex2 = side1 - valuey2*coef1;
1894 
1895  /* determine redundancy of one constraints side by checking for the first valuey1 */
1896  if( (*redundant1 && valuex1 > valuex2) || (*redundant0 && valuex1 < valuex2) )
1897  {
1898  *sideequal = FALSE;
1899  *redundant0 = FALSE;
1900  *redundant1 = FALSE;
1901  return;
1902  }
1903  if( *sideequal )
1904  {
1905  if( valuex1 + eps < valuex2 )
1906  {
1907  *sideequal = FALSE;
1908  *redundant1 = TRUE;
1909  }
1910  else if( valuex1 + eps > valuex2 )
1911  {
1912  *sideequal = FALSE;
1913  *redundant0 = TRUE;
1914  }
1915  }
1916  assert(*redundant0 || *redundant1 || *sideequal);
1917  }
1918 }
1919 
1920 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
1921  *
1922  * we will order all constraint to have constraints with same variables next to each other to speed up presolving
1923  *
1924  * consider two constraints like lhs1 <= x + b1*y <= rhs1 and lhs2 <= x + b2*y <= rhs2
1925  * we are doing the following presolving steps:
1926  *
1927  * if( b1 == b2 )
1928  * newlhs = MAX(lhs1, lhs2)
1929  * newrhs = MIN(rhs1, rhs2)
1930  * updateSides
1931  * delete one constraint
1932  * else if( ((b1 > 0) == (b2 > 0)) && (lhs1 != -inf && lhs2 != -inf) || (rhs1 != inf && rhs2 != inf) )
1933  *
1934  * (i.e. both constraint have either a valid lhs or a valid rhs and infinity is on the same side and the
1935  * coeffcients have the same size )
1936  *
1937  * if( y is binary )
1938  * if( lhs1 != -inf )
1939  * newlhs = MAX(lhs1, lhs2)
1940  * newb = newlhs - MAX(lhs1 - b1, lhs2 - b2)
1941  * else
1942  * newrhs = MIN(lhs1, lhs2)
1943  * newb = newrhs - MIN(rhs1 - b1, rhs2 - b2)
1944  * updateSidesAndCoef
1945  * delete one constraint
1946  * else
1947  * we calculate possible values for both variables and check which constraint is tighter
1948  * else
1949  * nothing possible
1950  *
1951  * We also try to tighten bounds in the case of two constraints lhs1 <= x + b1*y <= rhs1 and lhs2 <= y + b2*x <= rhs2.
1952  * Eliminiating one variable and inserting into the second yields the following bounds:
1953  * If b2 > 0:
1954  * (1 - b1 * b2) * y >= lhs2 - b2 * rhs1
1955  * (1 - b1 * b2) * y <= rhs2 - b2 * lhs1
1956  * If b2 < 0:
1957  * (1 - b1 * b2) * y >= lhs2 - b2 * lhs1
1958  * (1 - b1 * b2) * y <= rhs2 - b2 * rhs1
1959  * The case of x is similar.
1960  */
1961 static
1963  SCIP* scip, /**< SCIP data structure */
1964  SCIP_CONS** conss, /**< constraint set */
1965  int nconss, /**< number of constraints in constraint set */
1966  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
1967  int* nchgbds, /**< pointer to count number of bound changes */
1968  int* ndelconss, /**< pointer to count number of deleted constraints */
1969  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
1970  int* nchgsides /**< pointer to count number of changed left/right hand sides */
1971  )
1972 {
1973  SCIP_CONS** sortedconss;
1974  int c;
1975  int s;
1976 
1977  assert(scip != NULL);
1978  assert(conss != NULL);
1979  assert(cutoff != NULL);
1980  assert(nchgbds != NULL);
1981  assert(ndelconss != NULL);
1982  assert(nchgcoefs != NULL);
1983  assert(nchgsides != NULL);
1984 
1985  /* create our temporary working array */
1986  SCIP_CALL( SCIPduplicateBufferArray(scip, &sortedconss, conss, nconss) );
1987 
1988  /* sort all constraints, so that all constraints with same variables stand next to each other */
1989  SCIPsortPtr((void**)sortedconss, consVarboundComp, nconss);
1990 
1991  /* check all constraints for redundancy */
1992  for( c = nconss - 1; c > 0 && !(*cutoff); --c )
1993  {
1994  SCIP_CONS* cons0;
1995  SCIP_CONSDATA* consdata0;
1996 
1997  cons0 = sortedconss[c];
1998 
1999  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
2000  continue;
2001 
2002  consdata0 = SCIPconsGetData(cons0);
2003  assert(consdata0 != NULL);
2004  assert(consdata0->var != NULL);
2005  assert(consdata0->vbdvar != NULL);
2006 
2007  /* do not check for already redundant constraints */
2008  assert(!SCIPisZero(scip, consdata0->vbdcoef));
2009  assert(!SCIPisInfinity(scip, -consdata0->lhs) || !SCIPisInfinity(scip, consdata0->rhs));
2010 
2011  if( !consdata0->changed )
2012  continue;
2013 
2014  consdata0->changed = FALSE;
2015 
2016  for( s = c - 1; s >= 0; --s )
2017  {
2018  SCIP_CONS* cons1;
2019  SCIP_CONSDATA* consdata1;
2020  SCIP_Real lhs;
2021  SCIP_Real rhs;
2022  SCIP_Real coef;
2023  SCIP_Bool deletecons1;
2024 
2025  cons1 = sortedconss[s];
2026 
2027  if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
2028  continue;
2029 
2030  consdata1 = SCIPconsGetData(cons1);
2031  assert(consdata1 != NULL);
2032  assert(consdata1->var != NULL);
2033  assert(consdata1->vbdvar != NULL);
2034 
2035  /* do not check for already redundant constraints */
2036  assert(!SCIPisZero(scip, consdata1->vbdcoef));
2037  assert(!SCIPisInfinity(scip, -consdata1->lhs) || !SCIPisInfinity(scip, consdata1->rhs));
2038 
2039  lhs = consdata0->lhs;
2040  rhs = consdata0->rhs;
2041  coef = consdata0->vbdcoef;
2042 
2043  /* check for propagation in the case: lhs1 <= x + b1*y <= rhs1 and lhs2 <= y + b2*x <= rhs2. */
2044  if ( consdata0->var == consdata1->vbdvar && consdata0->vbdvar == consdata1->var &&
2045  !SCIPisFeasZero(scip, 1.0 - coef * consdata1->vbdcoef) )
2046  {
2047  SCIP_Bool tightened = FALSE;
2048  SCIP_Real bnd = SCIP_UNKNOWN;
2049  SCIP_Real scalar;
2050  SCIP_Real newbnd;
2051 
2052  scalar = (1.0 - coef * consdata1->vbdcoef);
2053 
2054  assert( ! SCIPisInfinity(scip, REALABS(scalar)) );
2055  assert( ! SCIPisZero(scip, consdata0->vbdcoef) );
2056  assert( ! SCIPisZero(scip, consdata1->vbdcoef) );
2057 
2058  /* lower bounds for consdata0->var */
2059  if ( ! SCIPisInfinity(scip, -lhs) )
2060  {
2061  if ( SCIPisPositive(scip, coef) )
2062  {
2063  if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2064  bnd = (lhs - coef * consdata1->rhs)/scalar;
2065  }
2066  else
2067  {
2068  assert( SCIPisNegative(scip, coef) );
2069  if ( ! SCIPisInfinity(scip, consdata1->lhs) )
2070  bnd = (lhs - coef * consdata1->lhs)/scalar;
2071  }
2072 
2073  if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2074  {
2075  if ( SCIPisFeasPositive(scip, scalar) )
2076  {
2077  newbnd = SCIPadjustedVarLb(scip, consdata0->var, bnd);
2078  SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2079  if ( tightened )
2080  {
2081  SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2082  SCIPvarGetName(consdata0->var), SCIPvarGetLbGlobal(consdata0->var));
2083  (*nchgbds)++;
2084  }
2085  }
2086  else if ( SCIPisFeasNegative(scip, scalar) )
2087  {
2088  newbnd = SCIPadjustedVarUb(scip, consdata0->var, bnd);
2089  SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2090  if ( tightened )
2091  {
2092  SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2093  SCIPvarGetName(consdata0->var), SCIPvarGetUbGlobal(consdata0->var));
2094  (*nchgbds)++;
2095  }
2096  }
2097  }
2098  }
2099 
2100  /* upper bound for consdata0>var */
2101  if ( ! SCIPisInfinity(scip, rhs) )
2102  {
2103  bnd = SCIP_UNKNOWN;
2104  if ( SCIPisPositive(scip, coef) )
2105  {
2106  if ( ! SCIPisInfinity(scip, consdata1->lhs) )
2107  bnd = (rhs - coef * consdata1->lhs)/scalar;
2108  }
2109  else
2110  {
2111  assert( SCIPisNegative(scip, coef) );
2112  if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2113  bnd = (rhs - coef * consdata1->rhs)/scalar;
2114  }
2115 
2116  if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2117  {
2118  if ( SCIPisFeasPositive(scip, scalar) )
2119  {
2120  newbnd = SCIPadjustedVarUb(scip, consdata0->var, bnd);
2121  SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2122  if ( tightened )
2123  {
2124  SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2125  SCIPvarGetName(consdata0->var), SCIPvarGetUbGlobal(consdata0->var));
2126  (*nchgbds)++;
2127  }
2128  }
2129  else if ( SCIPisFeasNegative(scip, scalar) )
2130  {
2131  newbnd = SCIPadjustedVarLb(scip, consdata0->var, bnd);
2132  SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, newbnd, FALSE, cutoff, &tightened) );
2133  if ( tightened )
2134  {
2135  SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2136  SCIPvarGetName(consdata0->var), SCIPvarGetLbGlobal(consdata0->var));
2137  (*nchgbds)++;
2138  }
2139  }
2140  }
2141  }
2142 
2143 
2144  /* lower bounds for consdata1->var */
2145  if ( ! SCIPisInfinity(scip, -consdata1->lhs) )
2146  {
2147  bnd = SCIP_UNKNOWN;
2148  if ( SCIPisPositive(scip, consdata1->vbdcoef) )
2149  {
2150  if ( ! SCIPisInfinity(scip, rhs) )
2151  bnd = (consdata1->lhs - consdata1->vbdcoef * rhs)/scalar;
2152  }
2153  else
2154  {
2155  assert( SCIPisNegative(scip, consdata1->vbdcoef) );
2156  if ( ! SCIPisInfinity(scip, lhs) )
2157  bnd = (consdata1->lhs - consdata1->vbdcoef * lhs)/scalar;
2158  }
2159 
2160  if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2161  {
2162  if ( SCIPisFeasPositive(scip, scalar) )
2163  {
2164  newbnd = SCIPadjustedVarLb(scip, consdata1->var, bnd);
2165  SCIP_CALL( SCIPtightenVarLb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2166  if ( tightened )
2167  {
2168  SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2169  SCIPvarGetName(consdata1->var), SCIPvarGetLbGlobal(consdata1->var));
2170  (*nchgbds)++;
2171  }
2172  }
2173  else if ( SCIPisFeasNegative(scip, scalar) )
2174  {
2175  newbnd = SCIPadjustedVarUb(scip, consdata1->var, bnd);
2176  SCIP_CALL( SCIPtightenVarUb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2177  if ( tightened )
2178  {
2179  SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2180  SCIPvarGetName(consdata1->var), SCIPvarGetUbGlobal(consdata1->var));
2181  (*nchgbds)++;
2182  }
2183  }
2184  }
2185  }
2186 
2187  /* upper bound for consdata1->var */
2188  if ( ! SCIPisInfinity(scip, consdata1->rhs) )
2189  {
2190  bnd = SCIP_UNKNOWN;
2191  if ( SCIPisPositive(scip, consdata1->vbdcoef) )
2192  {
2193  if ( ! SCIPisInfinity(scip, lhs) )
2194  bnd = (consdata1->rhs - consdata1->vbdcoef * lhs)/scalar;
2195  }
2196  else
2197  {
2198  assert( SCIPisNegative(scip, consdata1->vbdcoef) );
2199  if ( ! SCIPisInfinity(scip, rhs) )
2200  bnd = (consdata1->rhs - consdata1->vbdcoef * rhs)/scalar;
2201  }
2202 
2203  if ( bnd != SCIP_UNKNOWN ) /*lint !e777*/
2204  {
2205  if ( SCIPisFeasPositive(scip, scalar) )
2206  {
2207  newbnd = SCIPadjustedVarUb(scip, consdata1->var, bnd);
2208  SCIP_CALL( SCIPtightenVarUb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2209  if ( tightened )
2210  {
2211  SCIPdebugMsg(scip, "<%s>, <%s> -> tightened upper bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2212  SCIPvarGetName(consdata1->var), SCIPvarGetUbGlobal(consdata1->var));
2213  (*nchgbds)++;
2214  }
2215  }
2216  else if ( SCIPisFeasNegative(scip, scalar) )
2217  {
2218  newbnd = SCIPadjustedVarLb(scip, consdata1->var, bnd);
2219  SCIP_CALL( SCIPtightenVarLb(scip, consdata1->var, newbnd, FALSE, cutoff, &tightened) );
2220  if ( tightened )
2221  {
2222  SCIPdebugMsg(scip, "<%s>, <%s> -> tightened lower bound: <%s> >= %.15g\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1),
2223  SCIPvarGetName(consdata1->var), SCIPvarGetLbGlobal(consdata1->var));
2224  (*nchgbds)++;
2225  }
2226  }
2227  }
2228  }
2229  }
2230 
2231  /* check for equal variables */
2232  if( consdata0->var != consdata1->var || consdata0->vbdvar != consdata1->vbdvar )
2233  break;
2234 
2235  /* mark constraint1 for deletion if possible */
2236  deletecons1 = TRUE;
2237 
2238  /* the coefficients of both constraints are equal */
2239  if( SCIPisEQ(scip, coef, consdata1->vbdcoef) )
2240  {
2241  lhs = MAX(consdata1->lhs, lhs);
2242  rhs = MIN(consdata1->rhs, rhs);
2243  }
2244  /* now only one side and in both constraints the same side should be infinity and the vbdvar should be binary
2245  * then we neither do not need to have the same side nor the same coefficient
2246  */
2247  else if( SCIPvarIsBinary(consdata0->vbdvar)
2248  && (SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs))
2249  && (SCIPisInfinity(scip, -consdata1->lhs) || SCIPisInfinity(scip, consdata1->rhs))
2250  && (SCIPisInfinity(scip, -lhs) == SCIPisInfinity(scip, -consdata1->lhs)) )
2251  {
2252  /* lhs <= x + b*y <= +inf */
2253  if( !SCIPisInfinity(scip, -lhs) )
2254  {
2255  lhs = MAX(consdata1->lhs, lhs);
2256  coef = lhs - MAX(consdata1->lhs - consdata1->vbdcoef, consdata0->lhs - coef);
2257  }
2258  /* -inf <= x + b*y <= rhs */
2259  else
2260  {
2261  rhs = MIN(consdata1->rhs, rhs);
2262  coef = rhs - MIN(consdata1->rhs - consdata1->vbdcoef, consdata0->rhs - coef);
2263  }
2264 
2265  SCIP_CALL( SCIPmarkConsPropagate(scip, cons0) );
2266  }
2267  else if( SCIPisPositive(scip, coef) == SCIPisPositive(scip, consdata1->vbdcoef)
2268  && ((!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, -consdata1->lhs))
2269  || (!SCIPisInfinity(scip, rhs) && !SCIPisInfinity(scip, consdata1->rhs))) )
2270  {
2271  SCIP_Bool cons0lhsred;
2272  SCIP_Bool cons0rhsred;
2273  SCIP_Bool cons1lhsred;
2274  SCIP_Bool cons1rhsred;
2275  SCIP_Bool lhsequal;
2276  SCIP_Bool rhsequal;
2277 
2278  assert(!SCIPisInfinity(scip, lhs));
2279  assert(!SCIPisInfinity(scip, consdata1->lhs));
2280  assert(!SCIPisInfinity(scip, -rhs));
2281  assert(!SCIPisInfinity(scip, -consdata1->rhs));
2282 
2283  /* check if a left hand side of one constraints is redundant */
2284  checkRedundancySide(scip, consdata0->var, consdata0->vbdvar, coef, consdata1->vbdcoef, lhs, consdata1->lhs, &lhsequal, &cons0lhsred, &cons1lhsred, TRUE);
2285 
2286  /* check if a right hand side of one constraints is redundant */
2287  checkRedundancySide(scip, consdata0->var, consdata0->vbdvar, coef, consdata1->vbdcoef, rhs, consdata1->rhs, &rhsequal, &cons0rhsred, &cons1rhsred, FALSE);
2288 
2289  /* if cons0 is redundant, update cons1 and delete cons0 */
2290  if( (lhsequal || cons0lhsred) && (rhsequal || cons0rhsred) )
2291  {
2292  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2293  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
2294 
2295  SCIPdebugMsg(scip, "constraint: ");
2296  SCIPdebugPrintCons(scip, cons0, NULL);
2297  SCIPdebugMsg(scip, "is redundant to constraint: ");
2298  SCIPdebugPrintCons(scip, cons1, NULL);
2299 
2300  SCIP_CALL( SCIPdelCons(scip, cons0) );
2301  ++(*ndelconss);
2302 
2303  /* get next cons0 */
2304  break;
2305  }
2306  /* if cons1 is redundant, update cons0 and delete cons1 */
2307  else if( cons1lhsred && cons1rhsred )
2308  {
2309  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2310  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2311 
2312  SCIPdebugMsg(scip, "constraint: ");
2313  SCIPdebugPrintCons(scip, cons1, NULL);
2314  SCIPdebugMsg(scip, "is redundant to constraint: ");
2315  SCIPdebugPrintCons(scip, cons0, NULL);
2316 
2317  SCIP_CALL( SCIPdelCons(scip, cons1) );
2318  ++(*ndelconss);
2319 
2320  /* get next cons1 */
2321  continue;
2322  }
2323  /* if left hand side of cons0 is redundant set it to -infinity */
2324  else if( (lhsequal || cons0lhsred) && !SCIPisInfinity(scip, -lhs) )
2325  {
2326  lhs = -SCIPinfinity(scip);
2327 
2328  /* if right hand side of cons1 is redundant too, set it to infinity */
2329  if( cons1rhsred && !SCIPisInfinity(scip, consdata1->rhs) )
2330  {
2331  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
2332  ++(*nchgsides);
2333 
2334  SCIPdebugMsg(scip, "deleted rhs of constraint: ");
2335  SCIPdebugPrintCons(scip, cons1, NULL);
2336  SCIPdebugMsg(scip, "due to constraint: ");
2337  SCIPdebugPrintCons(scip, cons0, NULL);
2338  }
2339 
2340  /* later on we cannot not want to delete cons1 */
2341  deletecons1 = FALSE;
2342  }
2343  /* if right hand side of cons0 is redundant set it to infinity */
2344  else if( (rhsequal || cons0rhsred) && !SCIPisInfinity(scip, rhs) )
2345  {
2346  rhs = SCIPinfinity(scip);
2347 
2348  /* if left hand side of cons1 is redundant too, set it to -infinity */
2349  if( cons1lhsred && !SCIPisInfinity(scip, -consdata1->lhs) )
2350  {
2351  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
2352  ++(*nchgsides);
2353 
2354  SCIPdebugMsg(scip, "deleted lhs of constraint: ");
2355  SCIPdebugPrintCons(scip, cons1, NULL);
2356  SCIPdebugMsg(scip, "due to constraint: ");
2357  SCIPdebugPrintCons(scip, cons0, NULL);
2358  }
2359 
2360  /* later on we cannot not want to delete cons1 */
2361  deletecons1 = FALSE;
2362  }
2363  /* if left hand side of cons1 is redundant set it to -infinity */
2364  else if( cons1lhsred && !SCIPisInfinity(scip, -consdata1->lhs) )
2365  {
2366  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
2367  ++(*nchgsides);
2368 
2369  SCIPdebugMsg(scip, "deleted lhs of constraint: ");
2370  SCIPdebugPrintCons(scip, cons1, NULL);
2371  SCIPdebugMsg(scip, "due to constraint: ");
2372  SCIPdebugPrintCons(scip, cons0, NULL);
2373 
2374  continue;
2375  }
2376  /* if right hand side of cons1 is redundant set it to infinity */
2377  else if( cons1rhsred && !SCIPisInfinity(scip, consdata1->rhs) )
2378  {
2379  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
2380  ++(*nchgsides);
2381 
2382  SCIPdebugMsg(scip, "deleted rhs of constraint: ");
2383  SCIPdebugPrintCons(scip, cons1, NULL);
2384  SCIPdebugMsg(scip, "due to constraint: ");
2385  SCIPdebugPrintCons(scip, cons0, NULL);
2386 
2387  continue;
2388  }
2389  else /* nothing was redundant */
2390  continue;
2391  }
2392  else
2393  {
2394  /* there is no redundancy in both constraints with same variables */
2395  continue;
2396  }
2397 
2398  if( SCIPisFeasLT(scip, rhs, lhs) )
2399  {
2400  SCIPdebugMsg(scip, "constraint <%s> and <%s> lead to infeasibility due to their sides\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
2401  *cutoff = TRUE;
2402  break;
2403  }
2404 
2405  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
2406  if( lhs > rhs )
2407  {
2408  rhs = (lhs + rhs)/2;
2409  lhs = rhs;
2410  }
2411 
2412  /* we decide to let constraint cons0 stay, so update data structure consdata0 */
2413 
2414  /* update coefficient of cons0 */
2415 
2416  /* special case if new coefficient becomes zero, both constraints are redundant but we may tighten the bounds */
2417  if( SCIPisZero(scip, coef) )
2418  {
2419  SCIP_Bool infeasible;
2420  SCIP_Bool tightened;
2421 
2422  SCIPdebugMsg(scip, "constraint: ");
2423  SCIPdebugPrintCons(scip, cons1, NULL);
2424  SCIPdebugMsg(scip, "and constraint: ");
2425  SCIPdebugPrintCons(scip, cons0, NULL);
2426  SCIPdebugMsg(scip, "are both redundant and lead to bounding of <%s> in [%g, %g]\n", SCIPvarGetName(consdata0->var), lhs, rhs);
2427 
2428  /* delete cons1 */
2429  SCIP_CALL( SCIPdelCons(scip, cons1) );
2430  ++(*ndelconss);
2431 
2432  /* update upper bound if possible
2433  *
2434  * @note we need to force the bound change since we are deleting the constraint afterwards
2435  */
2436  SCIP_CALL( SCIPtightenVarUb(scip, consdata0->var, rhs, TRUE, &infeasible, &tightened) );
2437  assert(!infeasible);
2438  if( tightened )
2439  ++(*nchgbds);
2440 
2441  /* update lower bound if possible
2442  *
2443  * @note we need to force the bound change since we are deleting the constraint afterwards
2444  */
2445  SCIP_CALL( SCIPtightenVarLb(scip, consdata0->var, lhs, TRUE, &infeasible, &tightened) );
2446  assert(!infeasible);
2447  if( tightened )
2448  ++(*nchgbds);
2449 
2450  /* delete cons0 */
2451  SCIP_CALL( SCIPdelCons(scip, cons0) );
2452  ++(*ndelconss);
2453 
2454  /* get next cons0 */
2455  break;
2456  }
2457 
2458  SCIPdebugMsg(scip, "constraint: ");
2459  SCIPdebugPrintCons(scip, cons1, NULL);
2460  SCIPdebugMsg(scip, "and constraint: ");
2461  SCIPdebugPrintCons(scip, cons0, NULL);
2462 
2463  /* if sign of coefficient switches, update the rounding locks of the variable */
2464  if( SCIPconsIsLocked(cons0) && consdata0->vbdcoef * coef < 0.0 )
2465  {
2466  assert(SCIPconsIsTransformed(cons0));
2467 
2468  /* remove rounding locks for variable with old coefficient and install rounding locks for variable with new
2469  * coefficient
2470  */
2471  if( SCIPisPositive(scip, consdata0->vbdcoef) )
2472  {
2473  SCIP_CALL( SCIPunlockVarCons(scip, consdata0->vbdvar, cons0,
2474  !SCIPisInfinity(scip, -consdata0->lhs), !SCIPisInfinity(scip, consdata0->rhs)) );
2475  SCIP_CALL( SCIPlockVarCons(scip, consdata0->vbdvar, cons0,
2476  !SCIPisInfinity(scip, consdata0->rhs), !SCIPisInfinity(scip, -consdata0->lhs)) );
2477  }
2478  else
2479  {
2480  SCIP_CALL( SCIPunlockVarCons(scip, consdata0->vbdvar, cons0,
2481  !SCIPisInfinity(scip, consdata0->rhs), !SCIPisInfinity(scip, -consdata0->lhs)) );
2482  SCIP_CALL( SCIPlockVarCons(scip, consdata0->vbdvar, cons0,
2483  !SCIPisInfinity(scip, -consdata0->lhs), !SCIPisInfinity(scip, consdata0->rhs)) );
2484  }
2485  }
2486 
2487  /* now change the coefficient */
2488  if( !SCIPisEQ(scip, consdata0->vbdcoef, coef) )
2489  {
2490  ++(*nchgcoefs);
2491 
2492  /* mark to add new varbound information */
2493  consdata0->varboundsadded = FALSE;
2494  consdata0->tightened = FALSE;
2495  consdata0->presolved = FALSE;
2496  consdata0->changed = FALSE;
2497 
2498  consdata0->vbdcoef = coef;
2499 
2500  SCIP_CALL( SCIPmarkConsPropagate(scip, cons0) );
2501  }
2502 
2503  /* update lhs and rhs of cons0 */
2504  if( !SCIPisEQ(scip, consdata0->lhs, lhs) )
2505  {
2506  SCIP_CALL( chgLhs(scip, cons0, lhs) );
2507  ++(*nchgsides);
2508  }
2509  if( !SCIPisEQ(scip, consdata0->rhs, rhs) )
2510  {
2511  SCIP_CALL( chgRhs(scip, cons0, rhs) );
2512  ++(*nchgsides);
2513  }
2514 
2515  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
2516  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
2517 
2518  SCIPdebugMsg(scip, "lead to new constraint: ");
2519  SCIPdebugPrintCons(scip, cons0, NULL);
2520 
2521  /* if cons1 is still marked for deletion, delete it */
2522  if( deletecons1 )
2523  {
2524  /* delete cons1 */
2525  SCIP_CALL( SCIPdelCons(scip, cons1) );
2526  ++(*ndelconss);
2527  }
2528 
2529  assert(SCIPconsIsActive(cons0));
2530  }
2531  }
2532 
2533  /* free temporary memory */
2534  SCIPfreeBufferArray(scip, &sortedconss);
2535 
2536  return SCIP_OKAY;
2537 }
2538 
2539 /** for all varbound constraints with two integer variables make the coefficients integral */
2540 static
2542  SCIP* scip, /**< SCIP data structure */
2543  SCIP_CONS** conss, /**< constraint set */
2544  int nconss, /**< number of constraints in constraint set */
2545  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
2546  int* nchgsides /**< pointer to count number of changed left/right hand sides */
2547  )
2548 {
2549  SCIP_CONSDATA* consdata;
2550  int c;
2551 
2552  assert(scip != NULL);
2553  assert(conss != NULL || nconss == 0);
2554  assert(nchgcoefs != NULL);
2555  assert(nchgsides != NULL);
2556 
2557  /* if we cannot find any constraint for prettifying, stop */
2558  if( SCIPgetNIntVars(scip) + SCIPgetNImplVars(scip) < 1 )
2559  return SCIP_OKAY;
2560 
2561  for( c = nconss - 1; c >= 0; --c )
2562  {
2563  assert(conss != NULL);
2564 
2565  if( SCIPconsIsDeleted(conss[c]) )
2566  continue;
2567 
2568  consdata = SCIPconsGetData(conss[c]);
2569  assert(consdata != NULL);
2570 
2571  /* check for integer variables and one coefficient with an absolute value smaller than 1 */
2572  /* @note: we allow that the variable type of the bounded variable can be smaller than the variable type of the
2573  * bounding variable
2574  */
2575  if( (SCIPvarGetType(consdata->var) == SCIP_VARTYPE_BINARY || SCIPvarGetType(consdata->var) == SCIP_VARTYPE_INTEGER
2576  || SCIPvarGetType(consdata->var) == SCIP_VARTYPE_IMPLINT)
2577  && (SCIPvarGetType(consdata->vbdvar) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(consdata->vbdvar) == SCIP_VARTYPE_IMPLINT)
2578  && SCIPisLT(scip, REALABS(consdata->vbdcoef), 1.0) )
2579  {
2580  SCIP_Real epsilon;
2581  SCIP_Longint nominator;
2582  SCIP_Longint denominator;
2583  SCIP_Longint maxmult;
2584  SCIP_Bool success;
2585 
2586  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
2587  maxmult = (SCIP_Longint)(SCIPfeastol(scip)/epsilon + SCIPfeastol(scip));
2588  maxmult = MIN(maxmult, MAXSCALEDCOEF);
2589 
2590  success = SCIPrealToRational(consdata->vbdcoef, -epsilon, epsilon , maxmult, &nominator, &denominator);
2591 
2592  if( success )
2593  {
2594  /* it is possible that the dominator is a multiple of the nominator */
2595  if( SCIPisIntegral(scip, (SCIP_Real) denominator / (SCIP_Real) nominator) )
2596  {
2597  denominator /= nominator;
2598  nominator = 1;
2599  }
2600 
2601  success = success && (denominator <= maxmult);
2602 
2603  /* scale the constraint denominator/nominator */
2604  if( success && ABS(denominator) > 1 && nominator == 1)
2605  {
2606  SCIP_VAR* swapvar;
2607 
2608  /* print constraint before scaling */
2609  SCIPdebugPrintCons(scip, conss[c], NULL);
2610 
2611  assert(SCIPisEQ(scip, consdata->vbdcoef * denominator, 1.0));
2612 
2613  /* need to switch sides if coefficient is smaller then 0 */
2614  if( consdata->vbdcoef < 0 )
2615  {
2616  assert(denominator < 0);
2617 
2618  /* compute new sides */
2619 
2620  /* only right hand side exists */
2621  if( SCIPisInfinity(scip, -consdata->lhs) )
2622  {
2623  consdata->lhs = consdata->rhs * denominator;
2624  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs));
2625 
2626  consdata->rhs = SCIPinfinity(scip);
2627  }
2628  /* only left hand side exists */
2629  else if( SCIPisInfinity(scip, consdata->rhs) )
2630  {
2631  consdata->rhs = consdata->lhs * denominator;
2632  assert(!SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs));
2633 
2634  consdata->lhs = -SCIPinfinity(scip);
2635  }
2636  /* both sides exist */
2637  else
2638  {
2639  SCIP_Real tmp;
2640 
2641  tmp = consdata->lhs;
2642  consdata->lhs = consdata->rhs * denominator;
2643  consdata->rhs = tmp * denominator;
2644  consdata->tightened = FALSE;
2645 
2646  assert(!SCIPisInfinity(scip, consdata->lhs) && !SCIPisInfinity(scip, -consdata->lhs));
2647  assert(SCIPisGE(scip, consdata->rhs, consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
2648  }
2649  *nchgsides += 2;
2650  }
2651  /* coefficient > 0 */
2652  else
2653  {
2654  assert(denominator > 0);
2655 
2656  /* compute new left hand side */
2657  if( !SCIPisInfinity(scip, -consdata->lhs) )
2658  {
2659  consdata->lhs *= denominator;
2660  assert(!SCIPisInfinity(scip, consdata->lhs) && !SCIPisInfinity(scip, -consdata->lhs));
2661  ++(*nchgsides);
2662  }
2663 
2664  /* compute new right hand side */
2665  if( !SCIPisInfinity(scip, consdata->rhs) )
2666  {
2667  consdata->rhs *= denominator;
2668  assert(!SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs));
2669  ++(*nchgsides);
2670  }
2671 
2672  assert(SCIPisGE(scip, consdata->rhs, consdata->lhs));
2673  }
2674 
2675  /* swap both variables */
2676  swapvar = consdata->var;
2677  consdata->var = consdata->vbdvar;
2678  consdata->vbdvar = swapvar;
2679 
2680  /* swap coefficient */
2681  consdata->vbdcoef = (SCIP_Real)denominator;
2682  ++(*nchgcoefs);
2683 
2684  /* mark to add new varbound information */
2685  consdata->varboundsadded = FALSE;
2686  consdata->tightened = FALSE;
2687 
2688  /* print constraint after scaling */
2689  SCIPdebugMsg(scip, "transformed into:");
2690  SCIPdebugPrintCons(scip, conss[c], NULL);
2691  }
2692  }
2693  }
2694  }
2695 
2696  return SCIP_OKAY;
2697 }
2698 
2699 /** replaces fixed and aggregated variables in variable bound constraint by active problem variables */
2700 static
2702  SCIP* scip, /**< SCIP data structure */
2703  SCIP_CONS* cons, /**< variable bound constraint */
2704  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
2705  SCIP_Bool* cutoff, /**< pointer to store whether an infeasibility was detected */
2706  int* nchgbds, /**< pointer to count number of bound changes */
2707  int* ndelconss, /**< pointer to count number of deleted constraints */
2708  int* naddconss /**< pointer to count number of added constraints */
2709  )
2710 {
2711  SCIP_CONSDATA* consdata;
2712  SCIP_VAR* var;
2713  SCIP_Real varscalar;
2714  SCIP_Real varconstant;
2715  SCIP_VAR* vbdvar;
2716  SCIP_Real vbdvarscalar;
2717  SCIP_Real vbdvarconstant;
2718  SCIP_Bool varschanged;
2719  SCIP_Bool redundant;
2720 
2721  assert(scip != NULL);
2722  assert(cons != NULL);
2723  assert(cutoff != NULL);
2724  assert(nchgbds != NULL);
2725  assert(ndelconss != NULL);
2726  assert(naddconss != NULL);
2727 
2728  *cutoff = FALSE;
2729  redundant = FALSE;
2730 
2731  /* the variable bound constraint is: lhs <= x + c*y <= rhs */
2732  consdata = SCIPconsGetData(cons);
2733  assert(consdata != NULL);
2734 
2735  /* get active problem variables of x and y */
2736  var = consdata->var;
2737  varscalar = 1.0;
2738  varconstant = 0.0;
2739  SCIP_CALL( SCIPgetProbvarSum(scip, &var, &varscalar, &varconstant) );
2740  vbdvar = consdata->vbdvar;
2741  vbdvarscalar = 1.0;
2742  vbdvarconstant = 0.0;
2743  SCIP_CALL( SCIPgetProbvarSum(scip, &vbdvar, &vbdvarscalar, &vbdvarconstant) );
2744  varschanged = (var != consdata->var || vbdvar != consdata->vbdvar);
2745 
2746  /* if the variables are equal, the variable bound constraint reduces to standard bounds on the single variable */
2747  if( var == vbdvar && SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
2748  {
2749  SCIP_Real scalar;
2750  SCIP_Real constant;
2751 
2752  SCIPdebugMsg(scip, "variable bound constraint <%s> has equal variable and vbd variable <%s>\n",
2753  SCIPconsGetName(cons), SCIPvarGetName(var));
2754 
2755  /* lhs <= a1*z + b1 + c(a2*z + b2) <= rhs
2756  * <=> lhs <= (a1 + c*a2)z + (b1 + c*b2) <= rhs
2757  */
2758  scalar = varscalar + consdata->vbdcoef * vbdvarscalar;
2759  constant = varconstant + consdata->vbdcoef * vbdvarconstant;
2760  if( SCIPisZero(scip, scalar) )
2761  {
2762  /* no variable is left: the constraint is redundant or infeasible */
2763  if( SCIPisFeasLT(scip, constant, consdata->lhs) || SCIPisFeasGT(scip, constant, consdata->rhs) )
2764  *cutoff = TRUE;
2765  }
2766  else if( scalar > 0.0 )
2767  {
2768  if( !SCIPisInfinity(scip, -consdata->lhs) && !(*cutoff) )
2769  {
2770  SCIP_Bool tightened;
2771 
2772  SCIP_CALL( SCIPtightenVarLb(scip, var, (consdata->lhs - constant)/scalar, TRUE, cutoff, &tightened) );
2773  if( tightened )
2774  {
2775  SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(var), SCIPvarGetLbGlobal(var));
2776  (*nchgbds)++;
2777  }
2778  }
2779  if( !SCIPisInfinity(scip, consdata->rhs) && !(*cutoff) )
2780  {
2781  SCIP_Bool tightened;
2782 
2783  SCIP_CALL( SCIPtightenVarUb(scip, var, (consdata->rhs - constant)/scalar, TRUE, cutoff, &tightened) );
2784  if( tightened )
2785  {
2786  SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(var), SCIPvarGetUbGlobal(var));
2787  (*nchgbds)++;
2788  }
2789  }
2790  }
2791  else
2792  {
2793  if( !SCIPisInfinity(scip, -consdata->lhs) && !(*cutoff) )
2794  {
2795  SCIP_Bool tightened;
2796 
2797  SCIP_CALL( SCIPtightenVarUb(scip, var, (consdata->lhs - constant)/scalar, TRUE, cutoff, &tightened) );
2798  if( tightened )
2799  {
2800  SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(var), SCIPvarGetUbGlobal(var));
2801  (*nchgbds)++;
2802  }
2803  }
2804  if( !SCIPisInfinity(scip, consdata->rhs) && !(*cutoff) )
2805  {
2806  SCIP_Bool tightened;
2807 
2808  SCIP_CALL( SCIPtightenVarLb(scip, var, (consdata->rhs - constant)/scalar, TRUE, cutoff, &tightened) );
2809  if( tightened )
2810  {
2811  SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(var), SCIPvarGetLbGlobal(var));
2812  (*nchgbds)++;
2813  }
2814  }
2815  }
2816  redundant = TRUE;
2817  }
2818  else
2819  {
2820  /* if the variables should be replaced, drop the events and catch the events on the new variables afterwards */
2821  if( varschanged )
2822  {
2823  SCIP_CALL( dropEvents(scip, cons, eventhdlr) );
2824  }
2825 
2826  /* apply aggregation on x */
2827  if( SCIPisZero(scip, varscalar) )
2828  {
2829  SCIPdebugMsg(scip, "variable bound constraint <%s>: variable <%s> is fixed to %.15g\n",
2830  SCIPconsGetName(cons), SCIPvarGetName(consdata->var), varconstant);
2831 
2832  /* cannot change bounds on multi-aggregated variables */
2833  if( SCIPvarGetStatus(vbdvar) != SCIP_VARSTATUS_MULTAGGR )
2834  {
2835  /* x is fixed to varconstant: update bounds of y and delete the variable bound constraint */
2836  if( !SCIPisInfinity(scip, -consdata->lhs) && !(*cutoff) )
2837  {
2838  if( consdata->vbdcoef > 0.0 )
2839  {
2840  SCIP_Bool tightened;
2841 
2842  SCIP_CALL( SCIPtightenVarLb(scip, consdata->vbdvar, (consdata->lhs - varconstant)/consdata->vbdcoef,
2843  TRUE, cutoff, &tightened) );
2844  if( tightened )
2845  {
2846  SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetLbGlobal(consdata->vbdvar));
2847  (*nchgbds)++;
2848  }
2849  }
2850  else
2851  {
2852  SCIP_Bool tightened;
2853 
2854  SCIP_CALL( SCIPtightenVarUb(scip, consdata->vbdvar, (consdata->lhs - varconstant)/consdata->vbdcoef,
2855  TRUE, cutoff, &tightened) );
2856  if( tightened )
2857  {
2858  SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetUbGlobal(consdata->vbdvar));
2859  (*nchgbds)++;
2860  }
2861  }
2862  }
2863  if( !SCIPisInfinity(scip, consdata->rhs) && !(*cutoff) )
2864  {
2865  if( consdata->vbdcoef > 0.0 )
2866  {
2867  SCIP_Bool tightened;
2868 
2869  SCIP_CALL( SCIPtightenVarUb(scip, consdata->vbdvar, (consdata->rhs - varconstant)/consdata->vbdcoef,
2870  TRUE, cutoff, &tightened) );
2871  if( tightened )
2872  {
2873  SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetUbGlobal(consdata->vbdvar));
2874  (*nchgbds)++;
2875  }
2876  }
2877  else
2878  {
2879  SCIP_Bool tightened;
2880 
2881  SCIP_CALL( SCIPtightenVarLb(scip, consdata->vbdvar, (consdata->rhs - varconstant)/consdata->vbdcoef,
2882  TRUE, cutoff, &tightened) );
2883  if( tightened )
2884  {
2885  SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(consdata->vbdvar), SCIPvarGetLbGlobal(consdata->vbdvar));
2886  (*nchgbds)++;
2887  }
2888  }
2889  }
2890  redundant = TRUE;
2891  }
2892  }
2893  else if( var != consdata->var )
2894  {
2895  /* replace aggregated variable x in the constraint by its aggregation */
2896  if( varscalar > 0.0 )
2897  {
2898  /* lhs := (lhs - varconstant) / varscalar
2899  * rhs := (rhs - varconstant) / varscalar
2900  * c := c / varscalar
2901  */
2902  if( !SCIPisInfinity(scip, -consdata->lhs) )
2903  consdata->lhs = (consdata->lhs - varconstant)/varscalar;
2904  if( !SCIPisInfinity(scip, consdata->rhs) )
2905  consdata->rhs = (consdata->rhs - varconstant)/varscalar;
2906  consdata->vbdcoef /= varscalar;
2907 
2908  /* try to avoid numerical troubles */
2909  if( SCIPisIntegral(scip, consdata->vbdcoef) )
2910  consdata->vbdcoef = SCIPround(scip, consdata->vbdcoef);
2911 
2912  consdata->tightened = FALSE;
2913  }
2914  else
2915  {
2916  SCIP_Real lhs;
2917 
2918  assert(varscalar != 0.0);
2919 
2920  /* lhs := (rhs - varconstant) / varscalar
2921  * rhs := (lhs - varconstant) / varscalar
2922  * c := c / varscalar
2923  */
2924  lhs = consdata->lhs;
2925  consdata->lhs = -consdata->rhs;
2926  consdata->rhs = -lhs;
2927  if( !SCIPisInfinity(scip, -consdata->lhs) )
2928  consdata->lhs = (consdata->lhs + varconstant)/(-varscalar);
2929  if( !SCIPisInfinity(scip, consdata->rhs) )
2930  consdata->rhs = (consdata->rhs + varconstant)/(-varscalar);
2931  consdata->vbdcoef /= varscalar;
2932 
2933  /* try to avoid numerical troubles */
2934  if( SCIPisIntegral(scip, consdata->vbdcoef) )
2935  consdata->vbdcoef = SCIPround(scip, consdata->vbdcoef);
2936 
2937  consdata->tightened = FALSE;
2938  }
2939  /* release old variable */
2940  SCIP_CALL( SCIPreleaseVar(scip, &(consdata->var)) );
2941  consdata->var = var;
2942  /* capture new variable */
2943  SCIP_CALL( SCIPcaptureVar(scip, consdata->var) );
2944  }
2945 
2946  /* apply aggregation on y */
2947  if( SCIPisZero(scip, vbdvarscalar) )
2948  {
2949  SCIPdebugMsg(scip, "variable bound constraint <%s>: vbd variable <%s> is fixed to %.15g\n",
2950  SCIPconsGetName(cons), SCIPvarGetName(consdata->vbdvar), vbdvarconstant);
2951 
2952  /* cannot change bounds on multi-aggregated variables */
2954  {
2955  /* y is fixed to vbdvarconstant: update bounds of x and delete the variable bound constraint */
2956  if( !SCIPisInfinity(scip, -consdata->lhs) && !(*cutoff) )
2957  {
2958  SCIP_Bool tightened;
2959 
2960  SCIP_CALL( SCIPtightenVarLb(scip, consdata->var, consdata->lhs - consdata->vbdcoef * vbdvarconstant,
2961  TRUE, cutoff, &tightened) );
2962  if( tightened )
2963  {
2964  SCIPdebugMsg(scip, " -> tightened lower bound: <%s> >= %.15g\n", SCIPvarGetName(consdata->var), SCIPvarGetLbGlobal(consdata->var));
2965  (*nchgbds)++;
2966  }
2967  }
2968  if( !SCIPisInfinity(scip, consdata->rhs) && !(*cutoff) )
2969  {
2970  SCIP_Bool tightened;
2971 
2972  SCIP_CALL( SCIPtightenVarUb(scip, consdata->var, consdata->rhs - consdata->vbdcoef * vbdvarconstant,
2973  TRUE, cutoff, &tightened) );
2974  if( tightened )
2975  {
2976  SCIPdebugMsg(scip, " -> tightened upper bound: <%s> <= %.15g\n", SCIPvarGetName(consdata->var), SCIPvarGetUbGlobal(consdata->var));
2977  (*nchgbds)++;
2978  }
2979  }
2980  redundant = TRUE;
2981  }
2982  }
2983  else if( vbdvar != consdata->vbdvar )
2984  {
2985  /* replace aggregated variable y in the constraint by its aggregation:
2986  * lhs := lhs - c * vbdvarconstant
2987  * rhs := rhs - c * vbdvarconstant
2988  * c := c * vbdvarscalar
2989  */
2990  if( !SCIPisInfinity(scip, -consdata->lhs) )
2991  consdata->lhs -= consdata->vbdcoef * vbdvarconstant;
2992  if( !SCIPisInfinity(scip, consdata->rhs) )
2993  consdata->rhs -= consdata->vbdcoef * vbdvarconstant;
2994  consdata->vbdcoef *= vbdvarscalar;
2995 
2996  consdata->tightened = FALSE;
2997 
2998  /* release old variable */
2999  SCIP_CALL( SCIPreleaseVar(scip, &(consdata->vbdvar)) );
3000  consdata->vbdvar = vbdvar;
3001  /* capture new variable */
3002  SCIP_CALL( SCIPcaptureVar(scip, consdata->vbdvar) );
3003  }
3004 
3005  /* catch the events again on the new variables */
3006  if( varschanged )
3007  {
3008  SCIP_CALL( catchEvents(scip, cons, eventhdlr) );
3009  }
3010  }
3011 
3012  /* mark constraint changed, if a variable was exchanged */
3013  if( varschanged )
3014  {
3015  consdata->changed = TRUE;
3016  }
3017 
3018  /* active multi aggregations are now resolved by creating a new linear constraint */
3019  if( !(*cutoff) && !redundant && (SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR || SCIPvarGetStatus(vbdvar) == SCIP_VARSTATUS_MULTAGGR) )
3020  {
3021  SCIP_CONS* newcons;
3022  SCIP_Real lhs;
3023  SCIP_Real rhs;
3024 
3025  lhs = consdata->lhs;
3026  rhs = consdata->rhs;
3027 
3028  /* create upgraded linear constraint */
3029  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons), 0, NULL, NULL, lhs, rhs,
3034 
3035  /* if var was fixed, then the case that vbdvar was multi-aggregated, was not yet resolved */
3036  if( var != consdata->var )
3037  {
3038  assert(SCIPvarGetStatus(vbdvar) == SCIP_VARSTATUS_MULTAGGR);
3039  assert(SCIPisZero(scip, varscalar)); /* this means that var was fixed */
3040 
3041  /* add offset that results of the fixed variable */
3042  if( SCIPisZero(scip, varconstant) != 0 )
3043  {
3044  if( !SCIPisInfinity(scip, rhs) )
3045  {
3046  SCIP_CALL( SCIPchgRhsLinear(scip, newcons, rhs - varconstant) );
3047  }
3048  if( !SCIPisInfinity(scip, -lhs) )
3049  {
3050  SCIP_CALL( SCIPchgLhsLinear(scip, newcons, lhs - varconstant) );
3051  }
3052  }
3053  }
3054  else
3055  {
3056  assert(var == consdata->var);
3057 
3058  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, consdata->var, 1.0) );
3059  }
3060 
3061  /* if vbdvar was fixed, then the case that var was multi-aggregated, was not yet resolved */
3062  if( vbdvar != consdata->vbdvar )
3063  {
3064  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
3065  assert(SCIPisZero(scip, vbdvarscalar)); /* this means that var was fixed */
3066 
3067  /* add offset that results of the fixed variable */
3068  if( SCIPisZero(scip, vbdvarconstant) != 0 )
3069  {
3070  if( !SCIPisInfinity(scip, rhs) )
3071  {
3072  SCIP_CALL( SCIPchgRhsLinear(scip, newcons, rhs - vbdvarconstant) );
3073  }
3074  if( !SCIPisInfinity(scip, -lhs) )
3075  {
3076  SCIP_CALL( SCIPchgLhsLinear(scip, newcons, lhs - vbdvarconstant) );
3077  }
3078  }
3079  }
3080  else
3081  {
3082  assert(vbdvar == consdata->vbdvar);
3083 
3084  SCIP_CALL( SCIPaddCoefLinear(scip, newcons, consdata->vbdvar, consdata->vbdcoef) );
3085  }
3086 
3087  SCIP_CALL( SCIPaddCons(scip, newcons) );
3088 
3089  SCIPdebugMsg(scip, "resolved multi aggregation in varbound constraint <%s> by creating a new linear constraint\n", SCIPconsGetName(cons));
3090  SCIPdebugPrintCons(scip, newcons, NULL);
3091 
3092  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3093 
3094  redundant = TRUE;
3095  ++(*naddconss);
3096  }
3097 
3098  /* delete a redundant constraint */
3099  if( !(*cutoff) && redundant )
3100  {
3101  SCIPdebugMsg(scip, " -> variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
3102  SCIP_CALL( SCIPdelCons(scip, cons) );
3103  (*ndelconss)++;
3104  }
3105 
3106  return SCIP_OKAY;
3107 }
3108 
3109 /** tightens variable bound coefficient by inspecting the global bounds of the involved variables; note: this is also
3110  * performed by the linear constraint handler - only necessary if the user directly creates variable bound constraints
3111  */
3112 static
3114  SCIP* scip, /**< SCIP data structure */
3115  SCIP_CONS* cons, /**< variable bound constraint */
3116  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
3117  int* nchgsides, /**< pointer to count the number of left and right hand sides */
3118  int* ndelconss, /**< pointer to count number of deleted constraints */
3119  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3120  int* nchgbds /**< pointer to count number of bound changes */
3121  )
3122 {
3123  SCIP_CONSDATA* consdata;
3124  SCIP_Real xlb;
3125  SCIP_Real xub;
3126  SCIP_Real oldcoef;
3127  int oldnchgcoefs;
3128  int oldnchgsides;
3129 
3130  assert(nchgcoefs != NULL);
3131  assert(nchgsides != NULL);
3132  assert(ndelconss != NULL);
3133 
3134  consdata = SCIPconsGetData(cons);
3135  assert(consdata != NULL);
3136 
3137  /* tightening already done */
3138  if( consdata->tightened )
3139  return SCIP_OKAY;
3140 
3141  SCIPdebugMsg(scip, "tightening coefficients on variable bound constraint <%s>\n", SCIPconsGetName(cons));
3142 
3143  consdata->tightened = TRUE;
3144 
3145  /* if values and variable are integral the sides should it be too */
3146  if( SCIPvarGetType(consdata->var) <= SCIP_VARTYPE_IMPLINT
3147  && SCIPvarGetType(consdata->vbdvar) <= SCIP_VARTYPE_IMPLINT
3148  && SCIPisIntegral(scip, consdata->vbdcoef) )
3149  {
3150  if( !SCIPisIntegral(scip, consdata->lhs) )
3151  {
3152  consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3153  ++(*nchgsides);
3154  consdata->changed = TRUE;
3155  }
3156  if( !SCIPisIntegral(scip, consdata->rhs) )
3157  {
3158  consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3159  ++(*nchgsides);
3160  consdata->changed = TRUE;
3161  }
3162  }
3163 
3164  /* coefficient tightening only works for binary bound variable */
3165  if( !SCIPvarIsBinary(consdata->vbdvar) )
3166  return SCIP_OKAY;
3167 
3168  oldnchgcoefs = *nchgcoefs;
3169  oldnchgsides = *nchgsides;
3170  oldcoef = consdata->vbdcoef;
3171 
3172  /* coefficients tightening when all variables are integer */
3173  /* we consider the following varbound constraint: lhs <= x + b*y <= rhs (sides are possibly infinity)
3174  * y should always be binary and x of integral type and b not integral, we also need at least one side with infinity
3175  * or not integral value.
3176  *
3177  * 1. if( (lhs is integral and not -infinity) and ((rhs is infinity) or (b - floor(b) <= rhs - floor(rhs))) ):
3178  *
3179  * lhs <= x + b*y <= rhs => lhs <= x + floor(b)*y <= floor(rhs)
3180  *
3181  * 2. if( (rhs is integral and not infinity) and ((lhs is -infinity) or (b - floor(b) >= lhs - floor(lhs))) ):
3182  *
3183  * lhs <= x + b*y <= rhs => ceil(lhs) <= x + ceil(b)*y <= rhs
3184  *
3185  * 3. if( ((lhs is -infinity) or (b - floor(b) >= lhs - floor(lhs)))
3186  * and ((rhs is infinity) or (b - floor(b) > rhs - floor(rhs))) ):
3187  *
3188  * lhs <= x + b*y <= rhs => ceil(lhs) <= x + ceil(b)*y <= floor(rhs)
3189  *
3190  * 4. if( ((lhs is -infinity) or (b - floor(b) < lhs - floor(lhs)))
3191  * and ((rhs is infinity) or (b - floor(b) <= rhs - floor(rhs))) ):
3192  *
3193  * lhs <= x + b*y <= rhs => ceil(lhs) <= x + floor(b)*y <= floor(rhs)
3194  *
3195  * 5. if( (lhs is not integral) or (rhs is not integral) )
3196  *
3197  * if (lhs is not -infinity)
3198  * if (b - floor(b) < lhs - floor(lhs)):
3199  *
3200  * lhs <= x + b*y => ceil(lhs) <= x + b*y
3201  *
3202  * else if (b - floor(b) > lhs - floor(lhs)):
3203  *
3204  * lhs <= x + b*y => floor(lhs) + b - floor(b) <= x + b*y
3205  *
3206  * if (rhs is not infinity)
3207  * if (b - floor(b) < rhs - floor(rhs)):
3208  *
3209  * x + b*y <= rhs => x + b*y <= floor(rhs) + b - floor(b)
3210  *
3211  * else if (b - floor(b) > rhs - floor(rhs)):
3212  *
3213  * x + b*y <= rhs => x + b*y <= floor(rhs)
3214  */
3215  if( (SCIPvarGetType(consdata->var) == SCIP_VARTYPE_INTEGER || SCIPvarGetType(consdata->var) == SCIP_VARTYPE_IMPLINT || SCIPvarGetType(consdata->var) == SCIP_VARTYPE_BINARY)
3216  && !SCIPisIntegral(scip, consdata->vbdcoef)
3217  && (!SCIPisIntegral(scip, consdata->lhs) || SCIPisInfinity(scip, -consdata->lhs)
3218  || !SCIPisIntegral(scip, consdata->rhs) || SCIPisInfinity(scip, consdata->rhs)) )
3219  {
3220  /* infinity should be an integral value */
3221  assert(!SCIPisInfinity(scip, -consdata->lhs) || SCIPisIntegral(scip, consdata->lhs));
3222  assert(!SCIPisInfinity(scip, consdata->rhs) || SCIPisIntegral(scip, consdata->rhs));
3223 
3224  /* should not be a redundant constraint */
3225  assert(!SCIPisInfinity(scip, consdata->rhs) || !SCIPisInfinity(scip, -consdata->lhs));
3226 
3227  /* case 1 */
3228  if( SCIPisIntegral(scip, consdata->lhs) && !SCIPisInfinity(scip, -consdata->lhs) &&
3229  (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasLE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs))) )
3230  {
3231  consdata->vbdcoef = SCIPfeasFloor(scip, consdata->vbdcoef);
3232  ++(*nchgcoefs);
3233 
3234  if( !SCIPisInfinity(scip, consdata->rhs) )
3235  {
3236  consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3237  ++(*nchgsides);
3238  }
3239  }
3240  /* case 2 */
3241  else if( SCIPisIntegral(scip, consdata->rhs) && !SCIPisInfinity(scip, consdata->rhs) &&
3242  (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasGE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs))) )
3243 
3244  {
3245  consdata->vbdcoef = SCIPfeasCeil(scip, consdata->vbdcoef);
3246  ++(*nchgcoefs);
3247 
3248  if( !SCIPisInfinity(scip, -consdata->lhs) )
3249  {
3250  if( !SCIPisIntegral(scip, consdata->lhs) )
3251  ++(*nchgsides);
3252 
3253  consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3254  }
3255  }
3256  /* case 3 */
3257  else if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasGE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs))) && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs))) )
3258  {
3259  consdata->vbdcoef = SCIPfeasCeil(scip, consdata->vbdcoef);
3260  ++(*nchgcoefs);
3261 
3262  if( !SCIPisInfinity(scip, -consdata->lhs) )
3263  {
3264  if( !SCIPisIntegral(scip, consdata->lhs) )
3265  ++(*nchgsides);
3266 
3267  consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3268  }
3269  if( !SCIPisInfinity(scip, consdata->rhs) )
3270  {
3271  if( !SCIPisIntegral(scip, consdata->rhs) )
3272  ++(*nchgsides);
3273 
3274  consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3275  }
3276  }
3277  /* case 4 */
3278  else if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs))) && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasLE(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs))) )
3279  {
3280  consdata->vbdcoef = SCIPfeasFloor(scip, consdata->vbdcoef);
3281  ++(*nchgcoefs);
3282 
3283  if( !SCIPisInfinity(scip, -consdata->lhs) )
3284  {
3285  if( !SCIPisIntegral(scip, consdata->lhs) )
3286  ++(*nchgsides);
3287 
3288  consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3289  }
3290  if( !SCIPisInfinity(scip, consdata->rhs) )
3291  {
3292  if( !SCIPisIntegral(scip, consdata->rhs) )
3293  ++(*nchgsides);
3294 
3295  consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3296  }
3297  }
3298  /* case 5 */
3299  if( !SCIPisFeasIntegral(scip, consdata->lhs) || !SCIPisFeasIntegral(scip, consdata->rhs) )
3300  {
3301  if( !SCIPisInfinity(scip, -consdata->lhs) )
3302  {
3303  if( SCIPisFeasLT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs)) )
3304  {
3305  consdata->lhs = SCIPfeasCeil(scip, consdata->lhs);
3306  ++(*nchgsides);
3307  }
3308  else if( SCIPisFeasGT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->lhs - SCIPfeasFloor(scip, consdata->lhs)) )
3309  {
3310  consdata->lhs = SCIPfeasFloor(scip, consdata->lhs) + (consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef));
3311  ++(*nchgsides);
3312  }
3313  }
3314  if( !SCIPisInfinity(scip, consdata->rhs) )
3315  {
3316  if( SCIPisFeasLT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs)) )
3317  {
3318  consdata->rhs = SCIPfeasFloor(scip, consdata->rhs) + (consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef));
3319  ++(*nchgsides);
3320  }
3321  else if( SCIPisFeasGT(scip, consdata->vbdcoef - SCIPfeasFloor(scip, consdata->vbdcoef), consdata->rhs - SCIPfeasFloor(scip, consdata->rhs)) )
3322  {
3323  consdata->rhs = SCIPfeasFloor(scip, consdata->rhs);
3324  ++(*nchgsides);
3325  }
3326  }
3327  }
3328  }
3329 
3330  /* check if due to tightening the constraint got redundant */
3331  if( SCIPisZero(scip, consdata->vbdcoef) )
3332  {
3333  /* we have to make sure that the induced bound(s) is (are) actually applied;
3334  * if the relative change is too small, this may have been skipped in propagation
3335  */
3336  if( SCIPisLT(scip, SCIPvarGetLbGlobal(consdata->var), consdata->lhs) )
3337  {
3338  SCIP_Bool tightened;
3339 
3340  SCIP_CALL( SCIPtightenVarLbGlobal(scip, consdata->var, consdata->lhs, TRUE, cutoff, &tightened) );
3341 
3342  if( tightened )
3343  {
3344  SCIPdebugMsg(scip, " -> tighten domain of <%s> to [%.15g,%.15g]\n", SCIPvarGetName(consdata->var),
3345  SCIPvarGetLbGlobal(consdata->var), SCIPvarGetUbGlobal(consdata->var));
3346  (*nchgbds)++;
3347  }
3348  }
3349  if( SCIPisGT(scip, SCIPvarGetUbGlobal(consdata->var), consdata->rhs) )
3350  {
3351  SCIP_Bool tightened;
3352 
3353  SCIP_CALL( SCIPtightenVarUbGlobal(scip, consdata->var, consdata->rhs, TRUE, cutoff, &tightened) );
3354 
3355  if( tightened )
3356  {
3357  SCIPdebugMsg(scip, " -> tighten domain of <%s> to [%.15g,%.15g]\n", SCIPvarGetName(consdata->var),
3358  SCIPvarGetLbGlobal(consdata->var), SCIPvarGetUbGlobal(consdata->var));
3359  (*nchgbds)++;
3360  }
3361  }
3362 
3363  SCIPdebugMsg(scip, " -> variable bound constraint <%s> is redundant\n", SCIPconsGetName(cons));
3364 
3365  /* in order to correctly update the rounding locks, we need the coefficient to have the same sign as before the
3366  * coefficient tightening
3367  */
3368  consdata->vbdcoef = oldcoef;
3369 
3370  SCIP_CALL( SCIPdelCons(scip, cons) );
3371  ++(*ndelconss);
3372 
3373  return SCIP_OKAY;
3374  }
3375 
3376  /* get bounds of variable x */
3377  xlb = SCIPvarGetLbGlobal(consdata->var);
3378  xub = SCIPvarGetUbGlobal(consdata->var);
3379 
3380  /* it can happen that var is not of varstatus SCIP_VARSTATUS_FIXED but the bounds are equal, in this case we need to
3381  * stop
3382  */
3383  if( SCIPisEQ(scip, xlb, xub) )
3384  return SCIP_OKAY;
3385 
3386  /* modification of coefficient checking for slack in constraints */
3387  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs) )
3388  {
3389  /* lhs <= x + c*y <= rhs => lhs - c*y <= x <= rhs - c*y */
3390  if( consdata->vbdcoef > 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs - consdata->vbdcoef) && SCIPisFeasLT(scip, xub, consdata->rhs) )
3391  {
3392  SCIP_Real newcoef;
3393  SCIP_Real newrhs;
3394  SCIP_Real oldrhs;
3395 
3396  oldrhs = consdata->rhs;
3397 
3398  /* constraint has positive slack for both non-restricting cases y = 0, or y = 1, respectively
3399  * -> modify coefficients such that constraint is tight in at least one of the non-restricting cases
3400  * -> c' = MAX(c - rhs + xub, lhs - xlb), rhs' = rhs - c + c'
3401  */
3402  newcoef = MAX(consdata->vbdcoef - consdata->rhs + xub, consdata->lhs - xlb);
3403  newrhs = consdata->rhs - consdata->vbdcoef + newcoef;
3404 
3405  SCIPdebugMsg(scip, "tighten varbound %.15g <= <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to %.15g <= <%s> %+.15g<%s> <= %.15g\n",
3406  consdata->lhs, SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
3407  consdata->lhs, SCIPvarGetName(consdata->var), newcoef, SCIPvarGetName(consdata->vbdvar), newrhs);
3408 
3409  /* we cannot allow that the coefficient changes the sign because of the rounding locks */
3410  assert(consdata->vbdcoef * newcoef > 0);
3411 
3412  consdata->vbdcoef = newcoef;
3413  consdata->rhs = newrhs;
3414  (*nchgcoefs)++;
3415  (*nchgsides)++;
3416 
3417  /* some of the cases 1. to 5. might be applicable after changing the rhs to an integral value; one example is
3418  * the varbound constraint 0.225 <= x - 1.225 y <= 0.775 for which none of the above cases apply but after
3419  * tightening the lhs to 0.0 it is possible to reduce the rhs by applying the 1. reduction
3420  */
3421  if( !SCIPisFeasIntegral(scip, oldrhs) && SCIPisFeasIntegral(scip, newrhs) )
3422  {
3423  consdata->tightened = FALSE;
3424  SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
3425  assert(consdata->tightened);
3426  }
3427  else
3428  consdata->tightened = (SCIPisIntegral(scip, consdata->vbdcoef) && SCIPisIntegral(scip, consdata->rhs));
3429  }
3430  else if( consdata->vbdcoef < 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs) && SCIPisFeasLT(scip, xub, consdata->rhs - consdata->vbdcoef) )
3431  {
3432  SCIP_Real newcoef;
3433  SCIP_Real newlhs;
3434  SCIP_Real oldlhs;
3435 
3436  oldlhs = consdata->lhs;
3437 
3438  /* constraint has positive slack for both non-restricting cases y = 0, or y = 1, respectively
3439  * -> modify coefficients such that constraint is tight in at least one of the non-restricting cases
3440  * -> c' = MIN(c - lhs + xlb, rhs - xub), lhs' = lhs - c + c'
3441  */
3442  newcoef = MIN(consdata->vbdcoef - consdata->lhs + xlb, consdata->rhs - xub);
3443  newlhs = consdata->lhs - consdata->vbdcoef + newcoef;
3444 
3445  SCIPdebugMsg(scip, "tighten varbound %.15g <= <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to %.15g <= <%s> %+.15g<%s> <= %.15g\n",
3446  consdata->lhs, SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
3447  newlhs, SCIPvarGetName(consdata->var), newcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs);
3448 
3449  /* we cannot allow that the coefficient changes the sign because of the rounding locks */
3450  assert(consdata->vbdcoef * newcoef > 0);
3451 
3452  consdata->vbdcoef = newcoef;
3453  consdata->lhs = newlhs;
3454  (*nchgcoefs)++;
3455  (*nchgsides)++;
3456 
3457  /* some of the cases 1. to 5. might be applicable after changing the rhs to an integral value; one example is
3458  * the varbound constraint 0.225 <= x - 1.225 y <= 0.775 for which none of the above cases apply but after
3459  * tightening the lhs to 0.0 it is possible to reduce the rhs by applying the 1. reduction
3460  */
3461  if( !SCIPisFeasIntegral(scip, oldlhs) && SCIPisFeasIntegral(scip, newlhs) )
3462  {
3463  consdata->tightened = FALSE;
3464  SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
3465  assert(consdata->tightened);
3466  }
3467  else
3468  consdata->tightened = (SCIPisIntegral(scip, consdata->vbdcoef) && SCIPisIntegral(scip, consdata->lhs));
3469  }
3470  }
3471  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, consdata->rhs) )
3472  {
3473  /* lhs <= x + c*y => x >= lhs - c*y */
3474  if( consdata->vbdcoef > 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs - consdata->vbdcoef) )
3475  {
3476  /* constraint has positive slack for the non-restricting case y = 1
3477  * -> modify coefficients such that constraint is tight in the non-restricting case y = 1 and equivalent in the restricting case y = 0
3478  * -> c' = lhs - xlb
3479  */
3480  SCIPdebugMsg(scip, "tighten binary VLB <%s>[%.15g,%.15g] %+.15g<%s> >= %.15g to <%s> %+.15g<%s> >= %.15g\n",
3481  SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->lhs,
3482  SCIPvarGetName(consdata->var), consdata->lhs - xlb, SCIPvarGetName(consdata->vbdvar), consdata->lhs);
3483 
3484  /* we cannot allow that the coefficient changes the sign because of the rounding locks */
3485  assert(consdata->vbdcoef * (consdata->lhs - xlb) > 0);
3486 
3487  consdata->vbdcoef = consdata->lhs - xlb;
3488  (*nchgcoefs)++;
3489  }
3490  else if( consdata->vbdcoef < 0.0 && SCIPisFeasGT(scip, xlb, consdata->lhs) )
3491  {
3492  /* constraint has positive slack for the non-restricting case y = 0
3493  * -> modify coefficients such that constraint is tight in the non-restricting case y = 0 and equivalent in the restricting case y = 1
3494  * -> c' = c - lhs + xlb, lhs' = xlb
3495  */
3496  SCIPdebugMsg(scip, "tighten binary VLB <%s>[%.15g,%.15g] %+.15g<%s> >= %.15g to <%s> %+.15g<%s> >= %.15g\n",
3497  SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->lhs,
3498  SCIPvarGetName(consdata->var), consdata->vbdcoef - consdata->lhs + xlb, SCIPvarGetName(consdata->vbdvar), xlb);
3499 
3500  /* we cannot allow that the coefficient changes the sign because of the rounding locks */
3501  assert(consdata->vbdcoef * (consdata->vbdcoef - consdata->lhs + xlb) > 0);
3502 
3503  consdata->vbdcoef = consdata->vbdcoef - consdata->lhs + xlb;
3504  consdata->lhs = xlb;
3505  (*nchgcoefs)++;
3506  (*nchgsides)++;
3507  }
3508  }
3509  else if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs) )
3510  {
3511  /* x + c*y <= rhs => x <= rhs - c*y */
3512  if( consdata->vbdcoef < 0.0 && SCIPisFeasLT(scip, xub, consdata->rhs - consdata->vbdcoef) )
3513  {
3514  /* constraint has positive slack for the non-restricting case y = 1
3515  * -> modify coefficients such that constraint is tight in the non-restricting case y = 1 and equivalent in the restricting case y = 0
3516  * -> c' = rhs - xub
3517  */
3518  SCIPdebugMsg(scip, "tighten binary VUB <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to <%s> %+.15g<%s> <= %.15g\n",
3519  SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
3520  SCIPvarGetName(consdata->var), consdata->rhs - xub, SCIPvarGetName(consdata->vbdvar), consdata->rhs);
3521 
3522  /* we cannot allow that the coefficient changes the sign because of the rounding locks */
3523  assert(consdata->vbdcoef * (consdata->rhs - xub) > 0);
3524 
3525  consdata->vbdcoef = consdata->rhs - xub;
3526  (*nchgcoefs)++;
3527  }
3528  else if( consdata->vbdcoef > 0.0 && SCIPisFeasLT(scip, xub, consdata->rhs) )
3529  {
3530  /* constraint has positive slack for the non-restricting case y = 0
3531  * -> modify coefficients such that constraint is tight in the non-restricting case y = 0 and equivalent in the restricting case y = 1
3532  * -> c' = c - rhs + xub, rhs' = xub
3533  */
3534  SCIPdebugMsg(scip, "tighten binary VUB <%s>[%.15g,%.15g] %+.15g<%s> <= %.15g to <%s> %+.15g<%s> <= %.15g\n",
3535  SCIPvarGetName(consdata->var), xlb, xub, consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
3536  SCIPvarGetName(consdata->var), consdata->vbdcoef - consdata->rhs + xub, SCIPvarGetName(consdata->vbdvar), xub);
3537 
3538  /* we cannot allow that the coefficient changes the sign because of the rounding locks */
3539  assert(consdata->vbdcoef * (consdata->vbdcoef - consdata->rhs + xub) > 0);
3540 
3541  consdata->vbdcoef = consdata->vbdcoef - consdata->rhs + xub;
3542  consdata->rhs = xub;
3543  (*nchgcoefs)++;
3544  (*nchgsides)++;
3545  }
3546  }
3547 
3548  /* if something a coefficient or side of the varbound constraint was changed, ensure that the variable lower or
3549  * upper bounds of the variables are informed
3550  */
3551  if( *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
3552  {
3553  consdata->varboundsadded = FALSE;
3554  consdata->changed = TRUE;
3555  }
3556 
3557  return SCIP_OKAY;
3558 }
3559 
3560 /** check if we can upgrade to a set-packing constraint */
3561 static
3563  SCIP* scip, /**< SCIP data structure */
3564  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
3565  SCIP_CONS** conss, /**< constraint set */
3566  int nconss, /**< number of constraints in constraint set */
3567  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
3568  int* naggrvars, /**< pointer to count the number of aggregated variables */
3569  int* nchgbds, /**< pointer to count number of bound changes */
3570  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
3571  int* nchgsides, /**< pointer to count the number of left and right hand sides */
3572  int* ndelconss, /**< pointer to count the number of deleted constraints */
3573  int* naddconss /**< pointer to count the number of added constraints */
3574  )
3575 {
3576  SCIP_VAR* vars[2];
3577  SCIP_CONS* newcons;
3578  SCIP_CONS* cons;
3579  SCIP_CONSDATA* consdata;
3580  int c;
3581 
3582  assert(scip != NULL);
3583  assert(conshdlrdata != NULL);
3584  assert(conss != NULL || nconss == 0);
3585  assert(cutoff != NULL);
3586  assert(naggrvars != NULL);
3587  assert(nchgbds != NULL);
3588  assert(nchgcoefs != NULL);
3589  assert(nchgsides != NULL);
3590  assert(ndelconss != NULL);
3591  assert(naddconss != NULL);
3592 
3593  /* if we cannot find any constraint for upgrading, stop */
3594  if( SCIPgetNBinVars(scip) + SCIPgetNImplVars(scip) <= 1 )
3595  return SCIP_OKAY;
3596 
3597  if( nconss == 0 )
3598  return SCIP_OKAY;
3599 
3600  assert(conss != NULL);
3601 
3602  for( c = nconss - 1; c >= 0; --c )
3603  {
3604  cons = conss[c];
3605  assert(cons != NULL);
3606 
3607  if( !SCIPconsIsActive(cons) )
3608  continue;
3609 
3610  consdata = SCIPconsGetData(cons);
3611  assert(consdata != NULL);
3612  assert(SCIPisLE(scip, consdata->lhs, consdata->rhs));
3613 
3614  if( !consdata->presolved )
3615  {
3616  /* incorporate fixings and aggregations in constraint */
3617  SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, cutoff, nchgbds, ndelconss, naddconss) );
3618 
3619  if( *cutoff )
3620  return SCIP_OKAY;
3621  if( !SCIPconsIsActive(cons) )
3622  continue;
3623  }
3624 
3625  if( SCIPconsIsMarkedPropagate(cons) )
3626  {
3627  /* propagate constraint */
3628  SCIP_CALL( propagateCons(scip, cons, conshdlrdata->usebdwidening, cutoff, nchgbds, nchgsides, ndelconss) );
3629 
3630  if( *cutoff )
3631  return SCIP_OKAY;
3632  if( !SCIPconsIsActive(cons) )
3633  continue;
3634  }
3635 
3636  if( !consdata->tightened )
3637  {
3638  /* tighten variable bound coefficient */
3639  SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, cutoff, nchgbds) );
3640 
3641  if( *cutoff )
3642  return SCIP_OKAY;
3643  if( !SCIPconsIsActive(cons) )
3644  continue;
3645 
3646  assert(SCIPisLE(scip, consdata->lhs, consdata->rhs));
3647  }
3648 
3649  /* check if both variables are of binary type */
3650  if( SCIPvarIsBinary(consdata->vbdvar) && SCIPvarIsBinary(consdata->var) )
3651  {
3652  /* coefficient and sides should be tightened and we assume that the constraint is not redundant */
3653  assert(SCIPisEQ(scip, REALABS(consdata->vbdcoef), 1.0));
3654  assert(SCIPisZero(scip, consdata->rhs) || SCIPisEQ(scip, consdata->rhs, 1.0) || SCIPisInfinity(scip, consdata->rhs));
3655  assert(SCIPisZero(scip, consdata->lhs) || SCIPisEQ(scip, consdata->lhs, 1.0) || SCIPisInfinity(scip, -consdata->lhs));
3656  assert(!SCIPisInfinity(scip, consdata->rhs) || !SCIPisInfinity(scip, -consdata->lhs));
3657 
3658  /* the case x + y <= 1 or x + y >= 1 */
3659  if( consdata->vbdcoef > 0.0 )
3660  {
3661  if( SCIPisEQ(scip, consdata->rhs, 1.0) )
3662  {
3663  /* check for aggregations like x + y == 1 */
3664  if( SCIPisEQ(scip, consdata->lhs, 1.0) )
3665  {
3666  SCIP_Bool infeasible;
3667  SCIP_Bool redundant;
3668  SCIP_Bool aggregated;
3669 
3670  SCIPdebugMsg(scip, "varbound constraint <%s>: aggregate <%s> + <%s> == 1\n",
3671  SCIPconsGetName(cons), SCIPvarGetName(consdata->var), SCIPvarGetName(consdata->vbdvar));
3672 
3673  /* aggregate both variables */
3674  SCIP_CALL( SCIPaggregateVars(scip, consdata->var, consdata->vbdvar, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
3675  assert(!infeasible);
3676  ++(*naggrvars);
3677 
3678  SCIP_CALL( SCIPdelCons(scip, cons) );
3679  ++(*ndelconss);
3680 
3681  continue;
3682  }
3683  assert(consdata->lhs < 0.5);
3684 
3685  vars[0] = consdata->var;
3686  vars[1] = consdata->vbdvar;
3687  }
3688  else
3689  {
3690  assert(SCIPisEQ(scip, consdata->lhs, 1.0));
3691 
3692  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->var, &vars[0]) );
3693  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vbdvar, &vars[1]) );
3694  }
3695  }
3696  /* the case x - y <= 0 or x - y >= 0 */
3697  else
3698  {
3699  /* the case x - y <= 0 */
3700  if( SCIPisZero(scip, consdata->rhs) )
3701  {
3702  /* check for aggregations like x - y == 0 */
3703  if( SCIPisZero(scip, consdata->lhs) )
3704  {
3705  SCIP_Bool infeasible;
3706  SCIP_Bool redundant;
3707  SCIP_Bool aggregated;
3708 
3709  SCIPdebugMsg(scip, "varbound constraint <%s>: aggregate <%s> - <%s> == 0\n",
3710  SCIPconsGetName(cons), SCIPvarGetName(consdata->var), SCIPvarGetName(consdata->vbdvar));
3711 
3712  /* aggregate both variables */
3713  SCIP_CALL( SCIPaggregateVars(scip, consdata->var, consdata->vbdvar, 1.0, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
3714  assert(!infeasible);
3715  ++(*naggrvars);
3716 
3717  SCIP_CALL( SCIPdelCons(scip, cons) );
3718  ++(*ndelconss);
3719 
3720  continue;
3721  }
3722  assert(consdata->lhs < -0.5);
3723 
3724  vars[0] = consdata->var;
3725  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vbdvar, &vars[1]) );
3726  }
3727  /* the case x - y >= 0 */
3728  else
3729  {
3730  assert(SCIPisZero(scip, consdata->lhs));
3731 
3732  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->var, &vars[0]) );
3733  vars[1] = consdata->vbdvar;
3734  }
3735  }
3736 
3737  SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), 2, vars,
3742 
3743  SCIP_CALL( SCIPaddCons(scip, newcons) );
3744  SCIPdebugMsg(scip, "upgraded varbound constraint <%s> to a set-packing constraint\n", SCIPconsGetName(cons));
3745  SCIPdebugPrintCons(scip, newcons, NULL);
3746 
3747  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3748  ++(*naddconss);
3749 
3750  SCIP_CALL( SCIPdelCons(scip, cons) );
3751  ++(*ndelconss);
3752  }
3753  }
3754 
3755  return SCIP_OKAY;
3756 }
3757 
3758 /**@} */
3759 
3760 
3761 /**@name Linear constraint upgrading
3762  *
3763  */
3764 
3765 /** tries to upgrade a linear constraint into a variable bound constraint */
3766 static
3767 SCIP_DECL_LINCONSUPGD(linconsUpgdVarbound)
3768 { /*lint --e{715}*/
3769  SCIP_Bool upgrade;
3770 
3771  assert(upgdcons != NULL);
3772 
3773  /* check, if linear constraint can be upgraded to a variable bound constraint lhs <= x + a*y <= rhs
3774  * - there are exactly two variables
3775  * - one of the variables is non-binary (called the bounded variable x)
3776  * - one of the variables is non-continuous (called the bounding variable y)
3777  */
3778  upgrade = (nvars == 2) && (nposbin + nnegbin <= 1) && (nposcont + nnegcont <= 1);
3779 
3780  if( upgrade )
3781  {
3782  SCIP_VAR* var;
3783  SCIP_VAR* vbdvar;
3784  SCIP_Real vbdcoef;
3785  SCIP_Real vbdlhs;
3786  SCIP_Real vbdrhs;
3787  int vbdind;
3788 
3789  /* decide which variable we want to use as bounding variable y */
3790  if( SCIPvarGetType(vars[0]) < SCIPvarGetType(vars[1]) )
3791  vbdind = 0;
3792  else if( SCIPvarGetType(vars[0]) > SCIPvarGetType(vars[1]) )
3793  vbdind = 1;
3794  else if( SCIPisIntegral(scip, vals[0]) && !SCIPisIntegral(scip, vals[1]) )
3795  vbdind = 0;
3796  else if( !SCIPisIntegral(scip, vals[0]) && SCIPisIntegral(scip, vals[1]) )
3797  vbdind = 1;
3798  else if( REALABS(REALABS(vals[0]) - 1.0) < REALABS(REALABS(vals[1]) - 1.0) )
3799  vbdind = 1;
3800  else
3801  vbdind = 0;
3802 
3803  /* do not upgrade when it is numerical unstable */
3804  if( SCIPisZero(scip, vals[vbdind]/vals[1-vbdind]) )
3805  return SCIP_OKAY;
3806 
3807  SCIPdebugMsg(scip, "upgrading constraint <%s> to variable bound constraint\n", SCIPconsGetName(cons));
3808 
3809  var = vars[1-vbdind];
3810  vbdvar = vars[vbdind];
3811 
3812  assert(!SCIPisZero(scip, vals[1-vbdind]));
3813  vbdcoef = vals[vbdind]/vals[1-vbdind];
3814 
3815  if( vals[1-vbdind] > 0.0 )
3816  {
3817  vbdlhs = SCIPisInfinity(scip, -lhs) ? -SCIPinfinity(scip) : lhs/vals[1-vbdind];
3818  vbdrhs = SCIPisInfinity(scip, rhs) ? SCIPinfinity(scip) : rhs/vals[1-vbdind];
3819  }
3820  else
3821  {
3822  vbdlhs = SCIPisInfinity(scip, rhs) ? -SCIPinfinity(scip) : rhs/vals[1-vbdind];
3823  vbdrhs = SCIPisInfinity(scip, -lhs) ? SCIPinfinity(scip) : lhs/vals[1-vbdind];
3824  }
3825 
3826  /* create the bin variable bound constraint (an automatically upgraded constraint is always unmodifiable) */
3827  assert(!SCIPconsIsModifiable(cons));
3828  SCIP_CALL( SCIPcreateConsVarbound(scip, upgdcons, SCIPconsGetName(cons), var, vbdvar, vbdcoef, vbdlhs, vbdrhs,
3831  SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons),
3833  }
3834 
3835  return SCIP_OKAY;
3836 }
3837 
3838 /**@} */
3839 
3840 
3841 /**@name Callback methods
3842  *
3843  * @{
3844  */
3845 
3846 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
3847 static
3848 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyVarbound)
3849 { /*lint --e{715}*/
3850  assert(scip != NULL);
3851  assert(conshdlr != NULL);
3852  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3853 
3854  /* call inclusion method of constraint handler */
3856 
3857  *valid = TRUE;
3858 
3859  return SCIP_OKAY;
3860 }
3861 
3862 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
3863 static
3864 SCIP_DECL_CONSFREE(consFreeVarbound)
3865 { /*lint --e{715}*/
3866  SCIP_CONSHDLRDATA* conshdlrdata;
3867 
3868  assert(scip != NULL);
3869  assert(conshdlr != NULL);
3870  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3871 
3872  /* free constraint handler data */
3873  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3874  assert(conshdlrdata != NULL);
3875 
3876  conshdlrdataFree(scip, &conshdlrdata);
3877 
3878  SCIPconshdlrSetData(conshdlr, NULL);
3879 
3880  return SCIP_OKAY;
3881 }
3882 
3883 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
3884 static
3885 SCIP_DECL_CONSEXITSOL(consExitsolVarbound)
3886 { /*lint --e{715}*/
3887  SCIP_CONSDATA* consdata;
3888  int c;
3889 
3890  /* release the rows of all constraints */
3891  for( c = 0; c < nconss; ++c )
3892  {
3893  consdata = SCIPconsGetData(conss[c]);
3894  assert(consdata != NULL);
3895 
3896  if( consdata->row != NULL )
3897  {
3898  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
3899  }
3900  }
3901 
3902  return SCIP_OKAY;
3903 }
3904 
3905 
3906 /** frees specific constraint data */
3907 static
3908 SCIP_DECL_CONSDELETE(consDeleteVarbound)
3909 { /*lint --e{715}*/
3910  SCIP_CONSHDLRDATA* conshdlrdata;
3911 
3912  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3913  assert(conshdlrdata != NULL);
3914 
3915  /* drop events */
3916  if( SCIPisTransformed(scip) )
3917  {
3918  SCIP_CALL( dropEvents(scip, cons, conshdlrdata->eventhdlr) );
3919  }
3920 
3921  SCIP_CALL( consdataFree(scip, consdata) );
3922 
3923  return SCIP_OKAY;
3924 }
3925 
3926 
3927 /** transforms constraint data into data belonging to the transformed problem */
3928 static
3929 SCIP_DECL_CONSTRANS(consTransVarbound)
3930 { /*lint --e{715}*/
3931  SCIP_CONSHDLRDATA* conshdlrdata;
3932  SCIP_CONSDATA* sourcedata;
3933  SCIP_CONSDATA* targetdata;
3934 
3935  assert(conshdlr != NULL);
3936 
3937  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3938  assert(conshdlrdata != NULL);
3939 
3940  sourcedata = SCIPconsGetData(sourcecons);
3941  assert(sourcedata != NULL);
3942 
3943  /* create target constraint data */
3944  SCIP_CALL( consdataCreate(scip, &targetdata,
3945  sourcedata->var, sourcedata->vbdvar, sourcedata->vbdcoef, sourcedata->lhs, sourcedata->rhs) );
3946 
3947  /* create target constraint */
3948  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
3949  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
3950  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
3951  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
3952  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
3953 
3954  /* catch events for variables */
3955  SCIP_CALL( catchEvents(scip, *targetcons, conshdlrdata->eventhdlr) );
3956 
3957  return SCIP_OKAY;
3958 }
3959 
3960 
3961 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
3962 static
3963 SCIP_DECL_CONSINITLP(consInitlpVarbound)
3964 { /*lint --e{715}*/
3965  int i;
3966 
3967  *infeasible = FALSE;
3968 
3969  for( i = 0; i < nconss && !(*infeasible); i++ )
3970  {
3971  assert(SCIPconsIsInitial(conss[i]));
3972  SCIP_CALL( addRelaxation(scip, conss[i], infeasible) );
3973  }
3974 
3975  return SCIP_OKAY;
3976 }
3977 
3978 
3979 /** separation method of constraint handler for LP solutions */
3980 static
3981 SCIP_DECL_CONSSEPALP(consSepalpVarbound)
3982 { /*lint --e{715}*/
3983  SCIP_CONSHDLRDATA* conshdlrdata;
3984  int i;
3985 
3986  assert(conshdlr != NULL);
3987 
3988  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3989  assert(conshdlrdata != NULL);
3990 
3991  *result = SCIP_DIDNOTFIND;
3992 
3993  /* separate useful constraints */
3994  for( i = 0; i < nusefulconss; ++i )
3995  {
3996  SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, NULL, result) );
3997  }
3998 
3999  /* separate remaining constraints */
4000  for( i = nusefulconss; i < nconss && *result == SCIP_DIDNOTFIND; ++i )
4001  {
4002  SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, NULL, result) );
4003  }
4004 
4005  return SCIP_OKAY;
4006 }
4007 
4008 
4009 /** separation method of constraint handler for arbitrary primal solutions */
4010 static
4011 SCIP_DECL_CONSSEPASOL(consSepasolVarbound)
4012 { /*lint --e{715}*/
4013  SCIP_CONSHDLRDATA* conshdlrdata;
4014  int i;
4015 
4016  assert(conshdlr != NULL);
4017 
4018  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4019  assert(conshdlrdata != NULL);
4020 
4021  *result = SCIP_DIDNOTFIND;
4022 
4023  /* separate useful constraints */
4024  for( i = 0; i < nusefulconss; ++i )
4025  {
4026  SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, sol, result) );
4027  }
4028 
4029  /* separate remaining constraints */
4030  for( i = nusefulconss; i < nconss && *result == SCIP_DIDNOTFIND; ++i )
4031  {
4032  SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, sol, result) );
4033  }
4034 
4035  return SCIP_OKAY;
4036 }
4037 
4038 
4039 /** constraint enforcing method of constraint handler for LP solutions */
4040 static
4041 SCIP_DECL_CONSENFOLP(consEnfolpVarbound)
4042 { /*lint --e{715}*/
4043  SCIP_CONSHDLRDATA* conshdlrdata;
4044  int i;
4045 
4046  assert(conshdlr != NULL);
4047 
4048  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4049  assert(conshdlrdata != NULL);
4050 
4051  *result = SCIP_FEASIBLE;
4052 
4053  for( i = 0; i < nconss; i++ )
4054  {
4055  if( !checkCons(scip, conss[i], NULL, FALSE) )
4056  {
4057  assert((*result) == SCIP_INFEASIBLE || (*result) == SCIP_FEASIBLE);
4058  (*result) = SCIP_INFEASIBLE;
4059 
4060  SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
4061 
4062  SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, NULL, result) );
4063  assert((*result) != SCIP_FEASIBLE);
4064 
4065  if( (*result) != SCIP_INFEASIBLE )
4066  break;
4067  }
4068  else
4069  {
4070  /* increase age of constraint */
4071  SCIP_CALL( SCIPincConsAge(scip, conss[i]) );
4072  }
4073  }
4074 
4075  return SCIP_OKAY;
4076 }
4077 
4078 
4079 /** constraint enforcing method of constraint handler for relaxation solutions */
4080 static
4081 SCIP_DECL_CONSENFORELAX(consEnforelaxVarbound)
4082 { /*lint --e{715}*/
4083  SCIP_CONSHDLRDATA* conshdlrdata;
4084  int i;
4085 
4086  assert(conshdlr != NULL);
4087 
4088  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4089  assert(conshdlrdata != NULL);
4090 
4091  *result = SCIP_FEASIBLE;
4092 
4093  for( i = 0; i < nconss; i++ )
4094  {
4095  if( !checkCons(scip, conss[i], sol, FALSE) )
4096  {
4097  assert((*result) == SCIP_INFEASIBLE || (*result) == SCIP_FEASIBLE);
4098  (*result) = SCIP_INFEASIBLE;
4099 
4100  SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
4101 
4102  SCIP_CALL( separateCons(scip, conss[i], conshdlrdata->usebdwidening, sol, result) );
4103  assert((*result) != SCIP_FEASIBLE);
4104 
4105  if( (*result) != SCIP_INFEASIBLE )
4106  break;
4107  }
4108  else
4109  {
4110  /* increase age of constraint */
4111  SCIP_CALL( SCIPincConsAge(scip, conss[i]) );
4112  }
4113  }
4114 
4115  return SCIP_OKAY;
4116 }
4117 
4118 
4119 /** constraint enforcing method of constraint handler for pseudo solutions */
4120 static
4121 SCIP_DECL_CONSENFOPS(consEnfopsVarbound)
4122 { /*lint --e{715}*/
4123  int i;
4124 
4125  for( i = 0; i < nconss; i++ )
4126  {
4127  if( !checkCons(scip, conss[i], NULL, TRUE) )
4128  {
4129  SCIP_CALL( SCIPresetConsAge(scip, conss[i]) );
4130 
4131  *result = SCIP_INFEASIBLE;
4132  return SCIP_OKAY;
4133  }
4134  else
4135  {
4136  /* increase age of constraint */
4137  SCIP_CALL( SCIPincConsAge(scip, conss[i]) );
4138  }
4139  }
4140  *result = SCIP_FEASIBLE;
4141 
4142  return SCIP_OKAY;
4143 }
4144 
4145 
4146 /** feasibility check method of constraint handler for integral solutions */
4147 static
4148 SCIP_DECL_CONSCHECK(consCheckVarbound)
4149 { /*lint --e{715}*/
4150  int i;
4151 
4152  *result = SCIP_FEASIBLE;
4153 
4154  for( i = 0; i < nconss && (*result == SCIP_FEASIBLE || completely); i++ )
4155  {
4156  if( !checkCons(scip, conss[i], sol, checklprows) )
4157  {
4158  *result = SCIP_INFEASIBLE;
4159 
4160  if( printreason )
4161  {
4162  SCIP_CONSDATA* consdata;
4163  SCIP_Real sum;
4164 
4165  consdata = SCIPconsGetData(conss[i]);
4166  assert( consdata != NULL );
4167 
4168  sum = SCIPgetSolVal(scip, sol, consdata->var) + consdata->vbdcoef * SCIPgetSolVal(scip, sol, consdata->vbdvar);
4169 
4170  SCIP_CALL( SCIPprintCons(scip, conss[i], NULL) );
4171  SCIPinfoMessage(scip, NULL, ";\n");
4172 
4173  if( !SCIPisFeasGE(scip, sum, consdata->lhs) )
4174  {
4175  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - sum);
4176  }
4177  if( !SCIPisFeasLE(scip, sum, consdata->rhs) )
4178  {
4179  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", sum - consdata->rhs);
4180  }
4181  }
4182  }
4183  }
4184 
4185  return SCIP_OKAY;
4186 }
4187 
4188 
4189 /** domain propagation method of constraint handler */
4190 static
4191 SCIP_DECL_CONSPROP(consPropVarbound)
4192 { /*lint --e{715}*/
4193  SCIP_CONSHDLRDATA* conshdlrdata;
4194  SCIP_Bool cutoff;
4195  int nchgbds;
4196  int nchgsides;
4197  int i;
4198 
4199  assert(conshdlr != NULL);
4200 
4201  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4202  assert(conshdlrdata != NULL);
4203 
4204  cutoff = FALSE;
4205  nchgbds = 0;
4206 
4207  SCIPdebugMsg(scip, "propagating %d variable bound constraints\n", nmarkedconss);
4208 
4209  /* process constraints marked for propagation */
4210  for( i = 0; i < nmarkedconss && !cutoff; i++ )
4211  {
4212  SCIP_CALL( propagateCons(scip, conss[i], conshdlrdata->usebdwidening, &cutoff, &nchgbds, &nchgsides, NULL) );
4213  }
4214 
4215  if( cutoff )
4216  *result = SCIP_CUTOFF;
4217  else if( nchgbds > 0 )
4218  *result = SCIP_REDUCEDDOM;
4219  else
4220  *result = SCIP_DIDNOTFIND;
4221 
4222  return SCIP_OKAY;
4223 }
4224 
4225 
4226 /** presolving method of constraint handler */
4227 static
4228 SCIP_DECL_CONSPRESOL(consPresolVarbound)
4229 { /*lint --e{715}*/
4230  SCIP_CONSHDLRDATA* conshdlrdata;
4231  SCIP_CONS* cons;
4232  SCIP_CONSDATA* consdata;
4233  SCIP_Bool cutoff;
4234  int oldnchgbds;
4235  int oldndelconss;
4236  int oldnaddconss;
4237  int oldnchgcoefs;
4238  int oldnchgsides;
4239  int oldnaggrvars;
4240  int i;
4241 
4242  assert(scip != NULL);
4243  assert(conshdlr != NULL);
4244  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4245  assert(result != NULL);
4246 
4247  /* get constraint handler data */
4248  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4249  assert(conshdlrdata != NULL);
4250 
4251  cutoff = FALSE;
4252  oldnchgbds = *nchgbds;
4253  oldndelconss = *ndelconss;
4254  oldnaddconss = *naddconss;
4255  oldnchgcoefs = *nchgcoefs;
4256  oldnchgsides = *nchgsides;
4257  oldnaggrvars = *naggrvars;
4258 
4259  for( i = 0; i < nconss; i++ )
4260  {
4261  cons = conss[i];
4262  assert(cons != NULL);
4263 
4264  assert(!SCIPconsIsModifiable(cons));
4265 
4266  consdata = SCIPconsGetData(cons);
4267  assert(consdata != NULL);
4268 
4269  if( i % 1000 == 0 && SCIPisStopped(scip) )
4270  break;
4271 
4272  /* force presolving the constraint in the initial round */
4273  if( nrounds == 0 )
4274  consdata->presolved = FALSE;
4275 
4276  if( consdata->presolved )
4277  continue;
4278  consdata->presolved = TRUE;
4279 
4280  /* incorporate fixings and aggregations in constraint */
4281  SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, &cutoff, nchgbds, ndelconss, naddconss) );
4282 
4283  if( cutoff )
4284  break;
4285  if( !SCIPconsIsActive(cons) )
4286  continue;
4287 
4288  /* propagate constraint */
4289  SCIP_CALL( propagateCons(scip, cons, conshdlrdata->usebdwidening, &cutoff, nchgbds, nchgsides, ndelconss) );
4290 
4291  if( cutoff )
4292  break;
4293  if( !SCIPconsIsActive(cons) )
4294  continue;
4295 
4296  /* tighten variable bound coefficient */
4297  SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, &cutoff, nchgbds) );
4298  if( cutoff )
4299  break;
4300  if( !SCIPconsIsActive(cons) )
4301  continue;
4302 
4303  /* informs once variable x about a globally valid variable lower or upper bound */
4304  if( !consdata->varboundsadded )
4305  {
4306  SCIP_Bool infeasible;
4307  int nlocalchgbds;
4308  int localoldnchgbds;
4309 
4310  localoldnchgbds = *nchgbds;
4311 
4312  /* if lhs is finite, we have a variable lower bound: lhs <= x + c*y => x >= -c*y + lhs */
4313  if( !SCIPisInfinity(scip, -consdata->lhs) )
4314  {
4315  SCIPdebugMsg(scip, "adding variable lower bound <%s> >= %g<%s> + %g (and potentially also <%s> %s %g<%s> + %g)\n",
4316  SCIPvarGetName(consdata->var), -consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->lhs,
4317  SCIPvarGetName(consdata->vbdvar), (consdata->vbdcoef > 0 ? ">=" : "<="), 1.0/-consdata->vbdcoef,
4318  SCIPvarGetName(consdata->var), consdata->lhs/consdata->vbdcoef);
4319 
4320  SCIP_CALL( SCIPaddVarVlb(scip, consdata->var, consdata->vbdvar, -consdata->vbdcoef, consdata->lhs,
4321  &infeasible, &nlocalchgbds) );
4322  assert(!infeasible);
4323 
4324  *nchgbds += nlocalchgbds;
4325  }
4326 
4327  /* if rhs is finite, we have a variable upper bound: x + c*y <= rhs => x <= -c*y + rhs */
4328  if( !SCIPisInfinity(scip, consdata->rhs) )
4329  {
4330  SCIPdebugMsg(scip, "adding variable upper bound <%s> <= %g<%s> + %g (and potentially also <%s> %s %g<%s> + %g)\n",
4331  SCIPvarGetName(consdata->var), -consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar), consdata->rhs,
4332  SCIPvarGetName(consdata->vbdvar), (consdata->vbdcoef > 0 ? "<=" : ">="), 1.0/-consdata->vbdcoef,
4333  SCIPvarGetName(consdata->var), consdata->rhs/consdata->vbdcoef);
4334 
4335  SCIP_CALL( SCIPaddVarVub(scip, consdata->var, consdata->vbdvar, -consdata->vbdcoef, consdata->rhs,
4336  &infeasible, &nlocalchgbds) );
4337  assert(!infeasible);
4338 
4339  *nchgbds += nlocalchgbds;
4340  }
4341  consdata->varboundsadded = TRUE;
4342 
4343  if( *nchgbds > localoldnchgbds )
4344  {
4345  /* tighten variable bound coefficient */
4346  SCIP_CALL( tightenCoefs(scip, cons, nchgcoefs, nchgsides, ndelconss, &cutoff, nchgbds) );
4347  if( cutoff )
4348  break;
4349  }
4350  }
4351  }
4352 
4353  if( !cutoff )
4354  {
4355  /* for varbound constraint with two integer variables make coefficients integral */
4356  SCIP_CALL( prettifyConss(scip, conss, nconss, nchgcoefs, nchgsides) );
4357 
4358  /* check if we can upgrade to a set-packing constraint */
4359  SCIP_CALL( upgradeConss(scip, conshdlrdata, conss, nconss, &cutoff, naggrvars, nchgbds, nchgcoefs, nchgsides, ndelconss, naddconss) );
4360 
4361  if( !cutoff && conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
4362  {
4363  /* preprocess pairs of variable bound constraints */
4364  SCIP_CALL( preprocessConstraintPairs(scip, conss, nconss, &cutoff, nchgbds, ndelconss, nchgcoefs, nchgsides) );
4365  }
4366  }
4367 
4368  /* return the correct result code */
4369  if( cutoff )
4370  *result = SCIP_CUTOFF;
4371  else if( *nchgbds > oldnchgbds || *ndelconss > oldndelconss || *naddconss > oldnaddconss
4372  || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides || *naggrvars > oldnaggrvars )
4373  *result = SCIP_SUCCESS;
4374  else
4375  *result = SCIP_DIDNOTFIND;
4376 
4377  return SCIP_OKAY;
4378 }
4379 
4380 
4381 /** propagation conflict resolving method of constraint handler */
4382 static
4383 SCIP_DECL_CONSRESPROP(consRespropVarbound)
4384 { /*lint --e{715}*/
4385  SCIP_CONSHDLRDATA* conshdlrdata;
4386 
4387  assert(conshdlr != NULL);
4388 
4389  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4390  assert(conshdlrdata != NULL);
4391 
4392  SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, boundtype, bdchgidx, relaxedbd, conshdlrdata->usebdwidening) );
4393 
4394  *result = SCIP_SUCCESS;
4395 
4396  return SCIP_OKAY;
4397 }
4398 
4399 
4400 /** variable rounding lock method of constraint handler */
4401 static
4402 SCIP_DECL_CONSLOCK(consLockVarbound)
4403 { /*lint --e{715}*/
4404  SCIP_CONSDATA* consdata;
4405 
4406  consdata = SCIPconsGetData(cons);
4407  assert(consdata != NULL);
4408 
4409  if( !SCIPisInfinity(scip, -consdata->lhs) )
4410  {
4411  SCIP_CALL( SCIPaddVarLocks(scip, consdata->var, nlockspos, nlocksneg) );
4412  if( consdata->vbdcoef > 0.0 )
4413  {
4414  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vbdvar, nlockspos, nlocksneg) );
4415  }
4416  else
4417  {
4418  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vbdvar, nlocksneg, nlockspos) );
4419  }
4420  }
4421 
4422  if( !SCIPisInfinity(scip, consdata->rhs) )
4423  {
4424  SCIP_CALL( SCIPaddVarLocks(scip, consdata->var, nlocksneg, nlockspos) );
4425  if( consdata->vbdcoef > 0.0 )
4426  {
4427  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vbdvar, nlocksneg, nlockspos) );
4428  }
4429  else
4430  {
4431  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vbdvar, nlockspos, nlocksneg) );
4432  }
4433  }
4434 
4435  return SCIP_OKAY;
4436 }
4437 
4438 /** constraint display method of constraint handler */
4439 static
4440 SCIP_DECL_CONSPRINT(consPrintVarbound)
4441 { /*lint --e{715}*/
4442  SCIP_CONSDATA* consdata;
4443 
4444  assert(scip != NULL);
4445  assert(conshdlr != NULL);
4446  assert(cons != NULL);
4447 
4448  consdata = SCIPconsGetData(cons);
4449  assert(consdata != NULL);
4450 
4451  /* print left hand side for ranged rows */
4452  if( !SCIPisInfinity(scip, -consdata->lhs)
4453  && !SCIPisInfinity(scip, consdata->rhs)
4454  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
4455  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
4456 
4457  /* print coefficients and variables */
4458  SCIPinfoMessage(scip, file, "<%s>[%c] %+.15g<%s>[%c]", SCIPvarGetName(consdata->var),
4462  consdata->vbdcoef, SCIPvarGetName(consdata->vbdvar),
4465  SCIPvarGetType(consdata->vbdvar) == SCIP_VARTYPE_IMPLINT ? SCIP_VARTYPE_IMPLINT_CHAR : SCIP_VARTYPE_CONTINUOUS_CHAR);
4466 
4467  /* print right hand side */
4468  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
4469  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
4470  else if( !SCIPisInfinity(scip, consdata->rhs) )
4471  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
4472  else if( !SCIPisInfinity(scip, -consdata->lhs) )
4473  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
4474  else
4475  SCIPinfoMessage(scip, file, " [free]");
4476 
4477  return SCIP_OKAY;
4478 }
4479 
4480 /** constraint copying method of constraint handler */
4481 static
4482 SCIP_DECL_CONSCOPY(consCopyVarbound)
4483 { /*lint --e{715}*/
4484  SCIP_VAR** vars;
4485  SCIP_Real* coefs;
4486  const char* consname;
4487 
4488  SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
4489  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, 2) );
4490 
4491  vars[0] = SCIPgetVarVarbound(sourcescip, sourcecons);
4492  vars[1] = SCIPgetVbdvarVarbound(sourcescip, sourcecons);
4493 
4494  coefs[0] = 1.0;
4495  coefs[1] = SCIPgetVbdcoefVarbound(sourcescip, sourcecons);
4496 
4497  if( name != NULL )
4498  consname = name;
4499  else
4500  consname = SCIPconsGetName(sourcecons);
4501 
4502  /* copy the varbound using the linear constraint copy method */
4503  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, 2, vars, coefs,
4504  SCIPgetLhsVarbound(sourcescip, sourcecons), SCIPgetRhsVarbound(sourcescip, sourcecons), varmap, consmap,
4505  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
4506 
4507  SCIPfreeBufferArray(scip, &coefs);
4508  SCIPfreeBufferArray(scip, &vars);
4509 
4510  return SCIP_OKAY;
4511 }
4512 
4513 /** constraint parsing method of constraint handler */
4514 static
4515 SCIP_DECL_CONSPARSE(consParseVarbound)
4516 { /*lint --e{715}*/
4517  SCIP_VAR** vars;
4518  SCIP_Real* coefs;
4519  SCIP_Real lhs;
4520  SCIP_Real rhs;
4521  char* endstr;
4522  int requiredsize;
4523  int nvars;
4524 
4525  assert(scip != NULL);
4526  assert(success != NULL);
4527  assert(str != NULL);
4528  assert(name != NULL);
4529  assert(cons != NULL);
4530 
4531  /* set left and right hand side to their default values */
4532  lhs = -SCIPinfinity(scip);
4533  rhs = SCIPinfinity(scip);
4534 
4535  (*success) = FALSE;
4536 
4537  /* return of string empty */
4538  if( !*str )
4539  return SCIP_OKAY;
4540 
4541  /* ignore whitespace */
4542  while( isspace(*str) )
4543  ++str;
4544 
4545  if( isdigit(str[0]) || ((str[0] == '-' || str[0] == '+') && isdigit(str[1])) )
4546  {
4547  if( !SCIPstrToRealValue(str, &lhs, &endstr) )
4548  {
4549  SCIPerrorMessage("error parsing left hand side\n");
4550  return SCIP_OKAY;
4551  }
4552 
4553  /* ignore whitespace */
4554  while( isspace(*endstr) )
4555  ++endstr;
4556 
4557  if( endstr[0] != '<' || endstr[1] != '=' )
4558  {
4559  SCIPerrorMessage("missing \"<=\" after left hand side(, found %c%c)\n", endstr[0], endstr[1]);
4560  return SCIP_OKAY;
4561  }
4562 
4563  SCIPdebugMsg(scip, "found left hand side <%g>\n", lhs);
4564 
4565  /* it was indeed a left-hand-side, so continue parsing after it */
4566  str = endstr + 2;
4567  }
4568 
4569  /* pares x + c*y as linear sum */
4570  SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
4571  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, 2) );
4572 
4573  /* parse linear sum to get variables and coefficients */
4574  SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, 2, &requiredsize, &endstr, success) );
4575 
4576  if( requiredsize == 2 && *success )
4577  {
4578  SCIP_Bool foundvalue;
4579  SCIP_Real value;
4580 
4581  assert(nvars == 2);
4582  assert(SCIPisEQ(scip, coefs[0], 1.0));
4583 
4584  SCIPdebugMsg(scip, "found linear sum <%s> + %g <%s>\n", SCIPvarGetName(vars[0]), coefs[1], SCIPvarGetName(vars[1]));
4585 
4586  /* ignore whitespace */
4587  while( isspace(*endstr) )
4588  ++endstr;
4589 
4590  str = endstr;
4591 
4592  foundvalue = SCIPstrToRealValue(str+2, &value, &endstr);
4593 
4594  if( foundvalue )
4595  {
4596  /* search for end of linear sum: either '<=', '>=', '==', or '[free]' */
4597  switch( *str )
4598  {
4599  case '<':
4600  assert(str[1] == '=');
4601  rhs = value;
4602  break;
4603  case '=':
4604  assert(str[1] == '=');
4605  assert(SCIPisInfinity(scip, -lhs));
4606  lhs = value;
4607  rhs = value;
4608  break;
4609  case '>':
4610  assert(str[1] == '=');
4611  assert(SCIPisInfinity(scip, -lhs));
4612  lhs = value;
4613  break;
4614  default:
4615  SCIPerrorMessage("missing relation symbol after linear sum\n");
4616  *success = FALSE;
4617  }
4618  }
4619  else if( strncmp(str, "[free]", 6) != 0 )
4620  *success = FALSE;
4621  }
4622 
4623  if( *success )
4624  {
4625  SCIP_CALL( SCIPcreateConsVarbound(scip, cons, name, vars[0], vars[1], coefs[1], lhs, rhs,
4626  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4627  }
4628 
4629  /* free buffer arrays */
4630  SCIPfreeBufferArray(scip, &coefs);
4631  SCIPfreeBufferArray(scip, &vars);
4632 
4633  return SCIP_OKAY;
4634 }
4635 
4636 /** constraint method of constraint handler which returns the variables (if possible) */
4637 static
4638 SCIP_DECL_CONSGETVARS(consGetVarsVarbound)
4639 { /*lint --e{715}*/
4640 
4641  if( varssize < 2 )
4642  (*success) = FALSE;
4643  else
4644  {
4645  SCIP_CONSDATA* consdata;
4646  assert(cons != NULL);
4647  assert(vars != NULL);
4648 
4649  consdata = SCIPconsGetData(cons);
4650  assert(consdata != NULL);
4651 
4652  vars[0] = consdata->var;
4653  vars[1] = consdata->vbdvar;
4654  (*success) = TRUE;
4655  }
4656 
4657  return SCIP_OKAY;
4658 }
4659 
4660 /** constraint method of constraint handler which returns the number of variables (if possible) */
4661 static
4662 SCIP_DECL_CONSGETNVARS(consGetNVarsVarbound)
4663 { /*lint --e{715}*/
4664  (*nvars) = 2;
4665  (*success) = TRUE;
4666 
4667  return SCIP_OKAY;
4668 }
4669 
4670 /*
4671  * Event Handler
4672  */
4673 
4674 /** execution method of bound change event handler */
4675 static
4676 SCIP_DECL_EVENTEXEC(eventExecVarbound)
4677 { /*lint --e{715}*/
4678  SCIP_CONS* cons;
4679  SCIP_CONSDATA* consdata;
4680 
4681  assert(event != NULL);
4682  cons = (SCIP_CONS*)eventdata;
4683  assert(cons != NULL);
4684  consdata = SCIPconsGetData(cons);
4685  assert(consdata != NULL);
4686 
4688  {
4689  consdata->presolved = FALSE;
4690  }
4691  else
4692  {
4693  assert((SCIPeventGetType(event) & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0);
4694 
4695  consdata->presolved = FALSE;
4696  consdata->tightened = FALSE;
4697 
4698  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
4699  }
4700 
4701  return SCIP_OKAY;
4702 }
4703 
4704 /**@} */
4705 
4706 
4707 /**@name Interface methods
4708  *
4709  * @{
4710  */
4711 
4712 /** creates the handler for variable bound constraints and includes it in SCIP */
4714  SCIP* scip /**< SCIP data structure */
4715  )
4716 {
4717  SCIP_CONSHDLRDATA* conshdlrdata;
4718  SCIP_EVENTHDLR* eventhdlr;
4719  SCIP_CONSHDLR* conshdlr;
4720 
4721  /* include event handler for bound change events */
4723  eventExecVarbound, NULL) );
4724 
4725  /* create variable bound constraint handler data */
4726  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
4727 
4728  /* include constraint handler */
4731  consEnfolpVarbound, consEnfopsVarbound, consCheckVarbound, consLockVarbound,
4732  conshdlrdata) );
4733  assert(conshdlr != NULL);
4734 
4735  /* set non-fundamental callbacks via specific setter functions */
4736  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyVarbound, consCopyVarbound) );
4737  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteVarbound) );
4738  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolVarbound) );
4739  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeVarbound) );
4740  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsVarbound) );
4741  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsVarbound) );
4742  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpVarbound) );
4743  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseVarbound) );
4744  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolVarbound, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
4745  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintVarbound) );
4746  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropVarbound, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
4748  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropVarbound) );
4749  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpVarbound, consSepasolVarbound, CONSHDLR_SEPAFREQ,
4751  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransVarbound) );
4752  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxVarbound) );
4753 
4754  if( SCIPfindConshdlr(scip,"linear") != NULL )
4755  {
4756  /* include the linear constraint to varbound constraint upgrade in the linear constraint handler */
4758  }
4759 
4760  /* add varbound constraint handler parameters */
4762  "constraints/" CONSHDLR_NAME "/presolpairwise",
4763  "should pairwise constraint comparison be performed in presolving?",
4764  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
4766  "constraints/" CONSHDLR_NAME "/maxlpcoef",
4767  "maximum coefficient in varbound constraint to be added as a row into LP",
4768  &conshdlrdata->maxlpcoef, TRUE, DEFAULT_MAXLPCOEF, 0.0, 1e+20, NULL, NULL) );
4770  "constraints/" CONSHDLR_NAME "/usebdwidening", "should bound widening be used in conflict analysis?",
4771  &conshdlrdata->usebdwidening, FALSE, DEFAULT_USEBDWIDENING, NULL, NULL) );
4772 
4773  return SCIP_OKAY;
4774 }
4775 
4776 /** creates and captures a variable bound constraint: lhs <= x + c*y <= rhs
4777  *
4778  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
4779  */
4781  SCIP* scip, /**< SCIP data structure */
4782  SCIP_CONS** cons, /**< pointer to hold the created constraint */
4783  const char* name, /**< name of constraint */
4784  SCIP_VAR* var, /**< variable x that has variable bound */
4785  SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
4786  SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
4787  SCIP_Real lhs, /**< left hand side of variable bound inequality */
4788  SCIP_Real rhs, /**< right hand side of variable bound inequality */
4789  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
4790  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
4791  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
4792  * Usually set to TRUE. */
4793  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
4794  * TRUE for model constraints, FALSE for additional, redundant constraints. */
4795  SCIP_Bool check, /**< should the constraint be checked for feasibility?
4796  * TRUE for model constraints, FALSE for additional, redundant constraints. */
4797  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
4798  * Usually set to TRUE. */
4799  SCIP_Bool local, /**< is constraint only valid locally?
4800  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
4801  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
4802  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
4803  * adds coefficients to this constraint. */
4804  SCIP_Bool dynamic, /**< is constraint subject to aging?
4805  * Usually set to FALSE. Set to TRUE for own cuts which
4806  * are separated as constraints. */
4807  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
4808  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
4809  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
4810  * if it may be moved to a more global node?
4811  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
4812  )
4813 {
4814  SCIP_CONSHDLR* conshdlr;
4815  SCIP_CONSHDLRDATA* conshdlrdata;
4816  SCIP_CONSDATA* consdata;
4817 
4818  /* find the variable bound constraint handler */
4819  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
4820  if( conshdlr == NULL )
4821  {
4822  SCIPerrorMessage("variable bound constraint handler not found\n");
4823  return SCIP_PLUGINNOTFOUND;
4824  }
4825 
4826  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4827  assert(conshdlrdata != NULL);
4828 
4829  /* create constraint data */
4830  SCIP_CALL( consdataCreate(scip, &consdata, var, vbdvar, vbdcoef, lhs, rhs) );
4831 
4832  /* create constraint */
4833  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
4834  local, modifiable, dynamic, removable, stickingatnode) );
4835 
4836  if( SCIPisTransformed(scip) )
4837  {
4838  /* catch events for variables */
4839  SCIP_CALL( catchEvents(scip, *cons, conshdlrdata->eventhdlr) );
4840  }
4841 
4842  return SCIP_OKAY;
4843 }
4844 
4845 /** creates and captures a variable bound constraint: lhs <= x + c*y <= rhs
4846  * with all constraint flags set to their default values
4847  *
4848  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
4849  */
4851  SCIP* scip, /**< SCIP data structure */
4852  SCIP_CONS** cons, /**< pointer to hold the created constraint */
4853  const char* name, /**< name of constraint */
4854  SCIP_VAR* var, /**< variable x that has variable bound */
4855  SCIP_VAR* vbdvar, /**< binary, integer or implicit integer bounding variable y */
4856  SCIP_Real vbdcoef, /**< coefficient c of bounding variable y */
4857  SCIP_Real lhs, /**< left hand side of variable bound inequality */
4858  SCIP_Real rhs /**< right hand side of variable bound inequality */
4859  )
4860 {
4861  SCIP_CALL( SCIPcreateConsVarbound(scip, cons, name, var, vbdvar,vbdcoef, lhs, rhs,
4862  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
4863 
4864  return SCIP_OKAY;
4865 }
4866 
4867 /** gets left hand side of variable bound constraint lhs <= x + c*y <= rhs */
4869  SCIP* scip, /**< SCIP data structure */
4870  SCIP_CONS* cons /**< constraint data */
4871  )
4872 {
4873  SCIP_CONSDATA* consdata;
4874 
4875  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
4876  {
4877  SCIPerrorMessage("constraint is not a variable bound constraint\n");
4878  SCIPABORT();
4879  return SCIP_INVALID; /*lint !e527*/
4880  }
4881 
4882  consdata = SCIPconsGetData(cons);
4883  assert(consdata != NULL);
4884 
4885  return consdata->lhs;
4886 }
4887 
4888 /** gets right hand side of variable bound constraint lhs <= x + c*y <= rhs */
4890  SCIP* scip, /**< SCIP data structure */
4891  SCIP_CONS* cons /**< constraint data */
4892  )
4893 {
4894  SCIP_CONSDATA* consdata;
4895 
4896  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
4897  {
4898  SCIPerrorMessage("constraint is not a variable bound constraint\n");
4899  SCIPABORT();
4900  return SCIP_INVALID; /*lint !e527*/
4901  }
4902 
4903  consdata = SCIPconsGetData(cons);
4904  assert(consdata != NULL);
4905 
4906  return consdata->rhs;
4907 }
4908 
4909 /** gets bounded variable x of variable bound constraint lhs <= x + c*y <= rhs */
4911  SCIP* scip, /**< SCIP data structure */
4912  SCIP_CONS* cons /**< constraint data */
4913  )
4914 {
4915  SCIP_CONSDATA* consdata;
4916 
4917  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
4918  {
4919  SCIPerrorMessage("constraint is not a variable bound constraint\n");
4920  SCIPABORT();
4921  return NULL; /*lint !e527*/
4922  }
4923 
4924  consdata = SCIPconsGetData(cons);
4925  assert(consdata != NULL);
4926 
4927  return consdata->var;
4928 }
4929 
4930 /** gets bounding variable y of variable bound constraint lhs <= x + c*y <= rhs */
4932  SCIP* scip, /**< SCIP data structure */
4933  SCIP_CONS* cons /**< constraint data */
4934  )
4935 {
4936  SCIP_CONSDATA* consdata;
4937 
4938  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
4939  {
4940  SCIPerrorMessage("constraint is not a variable bound constraint\n");
4941  SCIPABORT();
4942  return NULL; /*lint !e527*/
4943  }
4944 
4945  consdata = SCIPconsGetData(cons);
4946  assert(consdata != NULL);
4947 
4948  return consdata->vbdvar;
4949 }
4950 
4951 /** gets bound coefficient c of variable bound constraint lhs <= x + c*y <= rhs */
4953  SCIP* scip, /**< SCIP data structure */
4954  SCIP_CONS* cons /**< constraint data */
4955  )
4956 {
4957  SCIP_CONSDATA* consdata;
4958 
4959  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
4960  {
4961  SCIPerrorMessage("constraint is not a variable bound constraint\n");
4962  SCIPABORT();
4963  return SCIP_INVALID; /*lint !e527*/
4964  }
4965 
4966  consdata = SCIPconsGetData(cons);
4967  assert(consdata != NULL);
4968 
4969  return consdata->vbdcoef;
4970 }
4971 
4972 /** gets the dual solution of the variable bound constraint in the current LP */
4974  SCIP* scip, /**< SCIP data structure */
4975  SCIP_CONS* cons /**< constraint data */
4976  )
4977 {
4978  SCIP_CONSDATA* consdata;
4979 
4980  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
4981  {
4982  SCIPerrorMessage("constraint is not a variable bound constraint\n");
4983  SCIPABORT();
4984  return SCIP_INVALID; /*lint !e527*/
4985  }
4986 
4987  consdata = SCIPconsGetData(cons);
4988  assert(consdata != NULL);
4989 
4990  if( consdata->row != NULL )
4991  return SCIProwGetDualsol(consdata->row);
4992  else
4993  return 0.0;
4994 }
4995 
4996 /** gets the dual Farkas value of the variable bound constraint in the current infeasible LP */
4998  SCIP* scip, /**< SCIP data structure */
4999  SCIP_CONS* cons /**< constraint data */
5000  )
5001 {
5002  SCIP_CONSDATA* consdata;
5003 
5004  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5005  {
5006  SCIPerrorMessage("constraint is not a variable bound constraint\n");
5007  SCIPABORT();
5008  return SCIP_INVALID; /*lint !e527*/
5009  }
5010 
5011  consdata = SCIPconsGetData(cons);
5012  assert(consdata != NULL);
5013 
5014  if( consdata->row != NULL )
5015  return SCIProwGetDualfarkas(consdata->row);
5016  else
5017  return 0.0;
5018 }
5019 
5020 /** returns the linear relaxation of the given variable bound constraint; may return NULL if no LP row was yet created;
5021  * the user must not modify the row!
5022  */
5024  SCIP* scip, /**< SCIP data structure */
5025  SCIP_CONS* cons /**< constraint data */
5026  )
5027 {
5028  SCIP_CONSDATA* consdata;
5029 
5030  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5031  {
5032  SCIPerrorMessage("constraint is not a variable bound constraint\n");
5033  SCIPABORT();
5034  return NULL; /*lint !e527*/
5035  }
5036 
5037  consdata = SCIPconsGetData(cons);
5038  assert(consdata != NULL);
5039 
5040  return consdata->row;
5041 }
5042 
5043 /**@} */
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4143
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:11902
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47363
#define CONSHDLR_PROP_TIMING
Definition: cons_varbound.c:69
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28372
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:6291
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip.c:41459
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool usebdwidening, SCIP_SOL *sol, SCIP_RESULT *result)
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:46443
static SCIP_DECL_CONSPROP(consPropVarbound)
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22523
enum Proprule PROPRULE
#define CONSHDLR_DELAYSEPA
Definition: cons_varbound.c:64
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:821
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:58
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8245
#define CONSHDLR_DESC
Definition: cons_varbound.c:54
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:6314
SCIP_Real SCIPgetDualfarkasVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47311
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, SCIP_Real lhs, SCIP_Real rhs)
Constraint handler for variable bound constraints .
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Real inferbd, SCIP_Bool usebdwidening)
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:41226
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
static SCIP_DECL_CONSSEPALP(consSepalpVarbound)
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:6544
SCIP_RETCODE SCIPcopyConsLinear(SCIP *scip, SCIP_CONS **cons, SCIP *sourcescip, const char *name, int nvars, SCIP_VAR **sourcevars, SCIP_Real *sourcecoefs, SCIP_Real lhs, SCIP_Real rhs, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode, SCIP_Bool global, SCIP_Bool *valid)
static SCIP_DECL_CONSINITLP(consInitlpVarbound)
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
static SCIP_DECL_CONSENFOLP(consEnfolpVarbound)
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip.c:6036
#define SCIP_VARTYPE_INTEGER_CHAR
Definition: def.h:121
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28400
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12663
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30668
#define CONSHDLR_SEPAFREQ
Definition: cons_varbound.c:58
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:47088
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47015
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8611
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:18957
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip.c:28112
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18766
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16842
#define CONSHDLR_MAXPREROUNDS
Definition: cons_varbound.c:63
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47387
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47350
static SCIP_DECL_CONSTRANS(consTransVarbound)
#define FALSE
Definition: def.h:64
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip.c:21985
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:10289
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:5894
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47100
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28630
SCIP_Real SCIPgetConflictVarUb(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:27474
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
enum Proprule PROPRULE
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:27251
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:21660
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8265
static SCIP_DECL_CONSGETVARS(consGetVarsVarbound)
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8295
SCIP_RETCODE SCIPaddConflictRelaxedLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedlb)
Definition: scip.c:27218
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:27155
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22639
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:5948
#define CONSHDLR_NAME
Definition: cons_varbound.c:53
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_varbound.c:83
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:22628
SCIP_RETCODE SCIPchgVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:22016
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46963
SCIP_RETCODE SCIPaddVarVlb(SCIP *scip, SCIP_VAR *var, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:23975
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip.c:21953
Constraint handler for the set partitioning / packing / covering constraints .
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
static SCIP_DECL_LINCONSUPGD(linconsUpgdVarbound)
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1017
SCIP_RETCODE SCIPaddVarVub(SCIP *scip, SCIP_VAR *var, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:24034
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8255
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:6337
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:16504
#define SCIPdebugMsg
Definition: scip.h:455
static SCIP_DECL_CONSPARSE(consParseVarbound)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:6521
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8047
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1343
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:27584
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:46415
SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition: scip.c:18214
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:27184
real eps
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:47435
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:47423
SCIP_RETCODE SCIPcreateConsVarbound(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:16695
#define CONSHDLR_SEPAPRIORITY
Definition: cons_varbound.c:55
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:27133
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:8721
static SCIP_DECL_CONSEXITSOL(consExitsolVarbound)
static SCIP_DECL_EVENTEXEC(eventExecVarbound)
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11628
SCIP_ROW * SCIPgetRowVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8325
#define SCIP_PRESOLTIMING_MEDIUM
Definition: type_timing.h:44
SCIP_VAR * SCIPgetVarVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:6060
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds, int *ndelconss, int *nchgcoefs, int *nchgsides)
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12591
#define CONSHDLR_PRESOLTIMING
Definition: cons_varbound.c:68
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyVarbound)
SCIP_Real SCIPgetRhsVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:13297
static SCIP_DECL_SORTPTRCOMP(consVarboundComp)
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip.c:19311
#define EVENTHDLR_NAME
Definition: cons_varbound.c:71
SCIP_Real SCIPgetVbdcoefVarbound(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetConflictVarLb(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:27450
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21788
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7986
SCIP_RETCODE SCIPchgVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:22106
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8205
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:6085
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4133
SCIP_RETCODE SCIPtightenVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:23542
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28602
static SCIP_DECL_CONSCHECK(consCheckVarbound)
#define REALABS(x)
Definition: def.h:173
SCIP_VAR * SCIPgetVbdvarVarbound(SCIP *scip, SCIP_CONS *cons)
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
#define SCIP_CALL(x)
Definition: def.h:350
#define EVENTHDLR_DESC
Definition: cons_varbound.c:72
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47337
void SCIPupdateSolLPConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip.c:13802
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47324
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool usebdwidening, SCIP_Bool *cutoff, int *nchgbds, int *nchgsides, int *ndelconss)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:27535
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8225
#define DEFAULT_MAXLPCOEF
Definition: cons_varbound.c:84
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:34661
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:6360
static void checkRedundancySide(SCIP *scip, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real coef0, SCIP_Real coef1, SCIP_Real side0, SCIP_Real side1, SCIP_Bool *sideequal, SCIP_Bool *cons0sidered, SCIP_Bool *cons1sidered, SCIP_Bool islhs)
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:106
#define CONSHDLR_DELAYPROP
Definition: cons_varbound.c:65
SCIP_RETCODE SCIPcreateConsSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_setppc.c:9092
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
#define SCIP_UNKNOWN
Definition: def.h:170
static SCIP_DECL_CONSFREE(consFreeVarbound)
#define SCIP_Bool
Definition: def.h:61
int SCIPgetNImplVars(SCIP *scip)
Definition: scip.c:11947
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
#define CONSHDLR_CHECKPRIORITY
Definition: cons_varbound.c:57
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:30402
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_Real inferbd, PROPRULE proprule, SCIP_BOUNDTYPE boundtype, SCIP_Bool usebdwidening)
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:29091
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3217
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10082
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
static SCIP_DECL_CONSRESPROP(consRespropVarbound)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8006
SCIP_RETCODE SCIPaddConflictRelaxedUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Real relaxedub)
Definition: scip.c:27286
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8115
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8185
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8155
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17124
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:41272
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:25575
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:16517
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21714
#define DEFAULT_USEBDWIDENING
Definition: cons_varbound.c:85
SCIP_RETCODE SCIPcreateConsBasicVarbound(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *var, SCIP_VAR *vbdvar, SCIP_Real vbdcoef, SCIP_Real lhs, SCIP_Real rhs)
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:6498
#define CONSHDLR_PROPFREQ
Definition: cons_varbound.c:59
Constraint handler for linear constraints in their most general form, .
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
#define MAXSCALEDCOEF
Definition: cons_varbound.c:88
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22819
Proprule
#define LINCONSUPGD_PRIORITY
Definition: cons_varbound.c:74
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11857
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:35836
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nchgbds, int *ndelconss, int *naddconss)
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30540
#define SCIP_VARTYPE_IMPLINT_CHAR
Definition: def.h:122
static SCIP_RETCODE tightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides, int *ndelconss, SCIP_Bool *cutoff, int *nchgbds)
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3162
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47002
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47112
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8016
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22932
static SCIP_DECL_CONSCOPY(consCopyVarbound)
SCIP_Real SCIPgetHugeValue(SCIP *scip)
Definition: scip.c:47065
#define SCIP_VARTYPE_CONTINUOUS_CHAR
Definition: def.h:123
static SCIP_DECL_CONSSEPASOL(consSepasolVarbound)
static SCIP_DECL_CONSENFOPS(consEnfopsVarbound)
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27761
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:6253
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:47375
static SCIP_DECL_CONSENFORELAX(consEnforelaxVarbound)
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16781
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip.c:25684
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18732
#define SCIP_Real
Definition: def.h:149
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8235
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:6567
#define CONSHDLR_NEEDSCONS
Definition: cons_varbound.c:66
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8175
static SCIP_Bool checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows)
#define SCIP_INVALID
Definition: def.h:169
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8165
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:31160
static SCIP_RETCODE prettifyConss(SCIP *scip, SCIP_CONS **conss, int nconss, int *nchgcoefs, int *nchgsides)
static SCIP_DECL_CONSDELETE(consDeleteVarbound)
#define CONSHDLR_ENFOPRIORITY
Definition: cons_varbound.c:56
#define SCIP_Longint
Definition: def.h:134
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16959
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:31134
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
#define SCIP_VARTYPE_BINARY_CHAR
Definition: def.h:120
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47076
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46989
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17342
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47399
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8195
SCIP_RETCODE SCIPtightenVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:23662
static SCIP_RETCODE upgradeConss(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *naggrvars, int *nchgbds, int *nchgcoefs, int *nchgsides, int *ndelconss, int *naddconss)
static SCIP_RETCODE createRelaxation(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPgetDualsolVarbound(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSLOCK(consLockVarbound)
static SCIP_DECL_CONSPRESOL(consPresolVarbound)
static SCIP_RETCODE dropEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
static SCIP_DECL_CONSPRINT(consPrintVarbound)
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:6181
SCIP_Real SCIPgetLhsVarbound(SCIP *scip, SCIP_CONS *cons)
#define SCIPABORT()
Definition: def.h:322
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
Definition: scip.c:47173
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16853
static SCIP_RETCODE catchEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
#define CONSHDLR_EAGERFREQ
Definition: cons_varbound.c:60
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4321
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:19045
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4239
static SCIP_DECL_CONSGETNVARS(consGetNVarsVarbound)
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5994
SCIP_RETCODE SCIPincludeConshdlrVarbound(SCIP *scip)