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