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