Scippy

SCIP

Solving Constraint Integer Programs

cons_bounddisjunction.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_bounddisjunction.c
17  * @ingroup DEFPLUGINS_CONS
18  * @brief constraint handler for bound disjunction constraints \f$(x_1 \{\leq,\geq\} b_1) \vee \ldots \vee (x_n \{\leq,\geq\} b_n)\f$
19  * @author Tobias Achterberg
20  * @author Marc Pfetsch
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include "blockmemshell/memory.h"
27 #include "scip/cons_linear.h"
28 #include "scip/cons_logicor.h"
29 #include "scip/cons_setppc.h"
30 #include "scip/expr_pow.h"
31 #include "scip/expr_var.h"
32 #include "scip/pub_conflict.h"
33 #include "scip/pub_cons.h"
34 #include "scip/pub_event.h"
35 #include "scip/pub_lp.h"
36 #include "scip/pub_message.h"
37 #include "scip/pub_misc.h"
38 #include "scip/pub_var.h"
39 #include "scip/scip_branch.h"
40 #include "scip/scip_conflict.h"
41 #include "scip/scip_cons.h"
42 #include "scip/scip_copy.h"
43 #include "scip/scip_event.h"
44 #include "scip/scip_expr.h"
45 #include "scip/scip_general.h"
46 #include "scip/scip_mem.h"
47 #include "scip/scip_message.h"
48 #include "scip/scip_nlp.h"
49 #include "scip/scip_numerics.h"
50 #include "scip/scip_param.h"
51 #include "scip/scip_prob.h"
52 #include "scip/scip_probing.h"
53 #include "scip/scip_sol.h"
54 #include "scip/scip_solvingstats.h"
55 #include "scip/scip_tree.h"
56 #include "scip/scip_var.h"
57 #include <ctype.h>
58 #include <string.h>
59 
60 /**@name Constraint handler properties
61  *
62  * @{
63  */
64 
65 #define CONSHDLR_NAME "bounddisjunction"
66 #define CONSHDLR_DESC "bound disjunction constraints"
67 #define CONSHDLR_ENFOPRIORITY -3000000 /**< priority of the constraint handler for constraint enforcing */
68 #define CONSHDLR_CHECKPRIORITY -3000000 /**< priority of the constraint handler for checking feasibility */
69 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
70 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
71  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
72 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
73 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
74 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
75 
76 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FAST
77 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
78 
79 /**@} */
80 
81 /**@name Event handler properties
82  *
83  * @{
84  */
85 
86 #define EVENTHDLR_NAME "bounddisjunction"
87 #define EVENTHDLR_DESC "event handler for bound disjunction constraints"
88 
89 /**@} */
90 
91 /**@name Conflict handler properties
92  *
93  * @{
94  */
95 
96 #define CONFLICTHDLR_NAME "bounddisjunction"
97 #define CONFLICTHDLR_DESC "conflict handler creating bound disjunction constraints"
98 #define CONFLICTHDLR_PRIORITY -3000000
99 
100 /**@} */
101 
102 /**@name Default parameter values
103  *
104  * @{
105  */
106 
107 #define DEFAULT_CONTINUOUSFRAC 0.4 /**< maximal percantage of continuous variables within a conflict */
109 /**@} */
110 
111 /**@name Age increase defines
112  *
113  * @{
114  */
115 
116 /* @todo make this a parameter setting */
117 #if 1 /* @todo test which AGEINCREASE formula is better! */
118 #define AGEINCREASE(n) (1.0 + 0.2*n)
119 #else
120 #define AGEINCREASE(n) (0.1*n)
121 #endif
122 
123 /**@} */
124 
125 
126 /**@name Comparison for two values
127  *
128  * @{
129  */
130 
131 #ifdef SCIP_DISABLED_CODE /* These only work if one also passes integral values in case of integral variables. This is not always the case and not even asserted. */
132 /** use defines for numeric compare methods to be slightly faster for integral values */
133 #define isFeasLT(scip, var, val1, val2) (SCIPvarIsIntegral(var) ? (val2) - (val1) > 0.5 : SCIPisFeasLT(scip, val1, val2))
134 #define isFeasLE(scip, var, val1, val2) (SCIPvarIsIntegral(var) ? (val2) - (val1) > -0.5 : SCIPisFeasLE(scip, val1, val2))
135 #define isFeasGT(scip, var, val1, val2) (SCIPvarIsIntegral(var) ? (val1) - (val2) > 0.5 : SCIPisFeasGT(scip, val1, val2))
136 #define isFeasGE(scip, var, val1, val2) (SCIPvarIsIntegral(var) ? (val1) - (val2) > -0.5 : SCIPisFeasGE(scip, val1, val2))
137 #else
138 #define isFeasLT(scip, var, val1, val2) SCIPisFeasLT(scip, val1, val2)
139 #define isFeasLE(scip, var, val1, val2) SCIPisFeasLE(scip, val1, val2)
140 #define isFeasGT(scip, var, val1, val2) SCIPisFeasGT(scip, val1, val2)
141 #define isFeasGE(scip, var, val1, val2) SCIPisFeasGE(scip, val1, val2)
142 #endif
143 /**@} */
144 
145 
146 /** constraint handler data */
147 struct SCIP_ConshdlrData
148 {
149  SCIP_EVENTHDLR* eventhdlr; /**< event handler for events on watched variables */
150 };
151 
152 /** bound disjunction constraint data */
153 struct SCIP_ConsData
154 {
155  SCIP_VAR** vars; /**< variables of the literals in the constraint */
156  SCIP_BOUNDTYPE* boundtypes; /**< types of bounds of the literals (lower or upper bounds) */
157  SCIP_Real* bounds; /**< bounds of the literals */
158  int varssize; /**< size of vars, boundtypes, and bounds arrays */
159  int nvars; /**< number of variables in the constraint */
160  int watchedvar1; /**< position of the first watched variable */
161  int watchedvar2; /**< position of the second watched variable */
162  int filterpos1; /**< event filter position of first watched variable */
163  int filterpos2; /**< event filter position of second watched variable */
164 };
165 
166 /**@name Local methods
167  *
168  * @{
169  */
170 
171 /** adds rounding locks for the given variable in the given bound disjunction constraint */
172 static
174  SCIP* scip, /**< SCIP data structure */
175  SCIP_CONS* cons, /**< bound disjunction constraint */
176  SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
177  int pos /**< position of the variable in the constraint */
178  )
179 {
180  assert(consdata != NULL);
181  assert(0 <= pos && pos < consdata->nvars);
182 
183  if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
184  {
185  SCIP_CALL( SCIPlockVarCons(scip, consdata->vars[pos], cons, TRUE, FALSE) );
186  }
187  else
188  {
189  SCIP_CALL( SCIPlockVarCons(scip, consdata->vars[pos], cons, FALSE, TRUE) );
190  }
191 
192  return SCIP_OKAY;
193 }
194 
195 /** removes rounding locks for the given variable in the given bound disjunction constraint */
196 static
198  SCIP* scip, /**< SCIP data structure */
199  SCIP_CONS* cons, /**< bound disjunction constraint */
200  SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
201  int pos /**< position of the variable in the constraint */
202  )
203 {
204  assert(consdata != NULL);
205  assert(0 <= pos && pos < consdata->nvars);
206 
207  if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
208  {
209  SCIP_CALL( SCIPunlockVarCons(scip, consdata->vars[pos], cons, TRUE, FALSE) );
210  }
211  else
212  {
213  SCIP_CALL( SCIPunlockVarCons(scip, consdata->vars[pos], cons, FALSE, TRUE) );
214  }
215 
216  return SCIP_OKAY;
217 }
218 
219 /** catches the events on a single variable of the bound disjunction constraint */
220 static
222  SCIP* scip, /**< SCIP data structure */
223  SCIP_CONS* cons, /**< bound disjunction constraint */
224  SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
225  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
226  int pos, /**< position of the variable in the constraint */
227  int* filterpos /**< pointer to store position of event filter entry, or NULL */
228  )
229 {
230  assert(consdata != NULL);
231  assert(0 <= pos && pos < consdata->nvars);
232 
233  if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
234  {
236  eventhdlr, (SCIP_EVENTDATA*)cons, filterpos) );
237  }
238  else
239  {
241  eventhdlr, (SCIP_EVENTDATA*)cons, filterpos) );
242  }
243 
244  return SCIP_OKAY;
245 }
246 
247 /** drops the events on a single variable of the bound disjunction constraint */
248 static
250  SCIP* scip, /**< SCIP data structure */
251  SCIP_CONS* cons, /**< bound disjunction constraint */
252  SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
253  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
254  int pos, /**< position of the variable in the constraint */
255  int filterpos /**< position of event filter entry returned by SCIPcatchVarEvent(), or -1 */
256  )
257 {
258  assert(consdata != NULL);
259  assert(0 <= pos && pos < consdata->nvars);
260 
261  if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
262  {
264  eventhdlr, (SCIP_EVENTDATA*)cons, filterpos) );
265  }
266  else
267  {
269  eventhdlr, (SCIP_EVENTDATA*)cons, filterpos) );
270  }
271 
272  return SCIP_OKAY;
273 }
274 
275 /** creates constraint handler data for bound disjunction constraint handler */
276 static
278  SCIP* scip, /**< SCIP data structure */
279  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
280  SCIP_EVENTHDLR* eventhdlr /**< event handler */
281  )
282 {
283  assert(scip != NULL);
284  assert(conshdlrdata != NULL);
285  assert(eventhdlr != NULL);
286 
287  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
288 
289  /* set event handler for catching events on watched variables */
290  (*conshdlrdata)->eventhdlr = eventhdlr;
291 
292  return SCIP_OKAY;
293 }
294 
295 /** frees constraint handler data for bound disjunction constraint handler */
296 static
297 void conshdlrdataFree(
298  SCIP* scip, /**< SCIP data structure */
299  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
300  )
301 {
302  assert(conshdlrdata != NULL);
303  assert(*conshdlrdata != NULL);
304 
305  SCIPfreeBlockMemory(scip, conshdlrdata);
306 }
307 
308 /** creates a bound disjunction constraint data object */
309 static
311  SCIP* scip, /**< SCIP data structure */
312  SCIP_CONSDATA** consdata, /**< pointer to store the bound disjunction constraint data */
313  int nvars, /**< number of variables in the constraint */
314  SCIP_VAR** vars, /**< variables of the literals in the constraint */
315  SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
316  SCIP_Real* bounds /**< bounds of the literals */
317  )
318 {
319  assert(consdata != NULL);
320  assert(nvars == 0 || vars != NULL);
321  assert(nvars == 0 || boundtypes != NULL);
322  assert(nvars == 0 || bounds != NULL);
323 
324  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
325 
326  if( nvars > 0 )
327  {
328  if( SCIPisConsCompressionEnabled(scip) )
329  {
330  int k;
331  int v;
332  int nviolations;
333  SCIP_Bool redundant;
334  SCIP_VAR** varsbuffer;
335  SCIP_BOUNDTYPE* boundtypesbuffer;
336  SCIP_Real* boundsbuffer;
337 
338  SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
339  SCIP_CALL( SCIPallocBufferArray(scip, &boundtypesbuffer, nvars) );
340  SCIP_CALL( SCIPallocBufferArray(scip, &boundsbuffer, nvars) );
341 
342  nviolations = 0;
343  k = 0;
344  redundant = FALSE;
345  /* loop over variables, compare fixed ones against its bound disjunction */
346  for( v = 0; v < nvars && !redundant; ++v )
347  {
348  SCIP_VAR* var = vars[v];
349  SCIP_BOUNDTYPE boundtype = boundtypes[v];
350  SCIP_Real bound = bounds[v];
351 
352  /* is the variable fixed? */
353  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
354  {
355  if( (boundtype == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, var, SCIPvarGetLbLocal(var), bound))
356  || (boundtype == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, var, SCIPvarGetUbLocal(var), bound)) )
357  {
358  /* save this feasible assignment at the first position */
359  varsbuffer[0] = var;
360  boundtypesbuffer[0] = boundtype;
361  boundsbuffer[0] = bound;
362  k = 1;
363  redundant = TRUE;
364  }
365  else
366  ++nviolations;
367  }
368  else
369  {
370  /* append unfixed variable to buffer */
371  varsbuffer[k] = var;
372  boundtypesbuffer[k] = boundtype;
373  boundsbuffer[k] = bound;
374  ++k;
375  }
376  }
377 
378  /* duplicate a single, infeasible assignment, wlog the first one */
379  if( k == 0 )
380  {
381  assert(nviolations == nvars);
382  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, 1) );
383  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->boundtypes, boundtypes, 1) );
384  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->bounds, bounds, 1) );
385  (*consdata)->varssize = 1;
386  (*consdata)->nvars = 1;
387  }
388  else
389  {
390  /* if the bound disjunction is already trivially satisfied, we keep only a single feasible assignment */
391  assert(!redundant || k == 1);
392 
393  /* we only copy the buffered variables required to represent the constraint */
394  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
395  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->boundtypes, boundtypesbuffer, k) );
396  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->bounds, boundsbuffer, k) );
397  (*consdata)->varssize = k;
398  (*consdata)->nvars = k;
399  }
400 
401  /* free buffer storage */
402  SCIPfreeBufferArray(scip, &boundsbuffer);
403  SCIPfreeBufferArray(scip, &boundtypesbuffer);
404  SCIPfreeBufferArray(scip, &varsbuffer);
405  }
406  else
407  {
408  /* without problem compression, the entire vars array is copied */
409  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
410  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->boundtypes, boundtypes, nvars) );
411  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->bounds, bounds, nvars) );
412  (*consdata)->varssize = nvars;
413  (*consdata)->nvars = nvars;
414  }
415  }
416  else
417  {
418  (*consdata)->vars = NULL;
419  (*consdata)->boundtypes = NULL;
420  (*consdata)->bounds = NULL;
421  (*consdata)->varssize = 0;
422  (*consdata)->nvars = 0;
423  }
424  (*consdata)->watchedvar1 = -1;
425  (*consdata)->watchedvar2 = -1;
426  (*consdata)->filterpos1 = -1;
427  (*consdata)->filterpos2 = -1;
428 
429  /* get transformed variables, if we are in the transformed problem */
430  if( SCIPisTransformed(scip) )
431  {
432  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
433  }
434 
435  return SCIP_OKAY;
436 }
437 
438 /** creates a bound disjunction constraint data object with possibly redundant literals */
439 static
441  SCIP* scip, /**< SCIP data structure */
442  SCIP_CONSDATA** consdata, /**< pointer to store the bound disjunction constraint data */
443  int nvars, /**< number of variables in the constraint */
444  SCIP_VAR** vars, /**< variables of the literals in the constraint */
445  SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
446  SCIP_Real* bounds /**< bounds of the literals */
447  )
448 {
449  assert(consdata != NULL);
450  assert(nvars == 0 || vars != NULL);
451  assert(nvars == 0 || boundtypes != NULL);
452  assert(nvars == 0 || bounds != NULL);
453 
454  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
455 
456  if( nvars > 0 )
457  {
458  SCIP_BOUNDTYPE* boundtypesbuffer;
459  SCIP_Real* boundsbuffer;
460  SCIP_VAR** varsbuffer;
461  SCIP_VAR* var;
462  int nvarsbuffer = 0;
463  int nviolated = 0;
464  int v;
465 
466  SCIP_CALL( SCIPduplicateBufferArray(scip, &varsbuffer, vars, nvars) );
467  SCIP_CALL( SCIPduplicateBufferArray(scip, &boundtypesbuffer, boundtypes, nvars) );
468  SCIP_CALL( SCIPduplicateBufferArray(scip, &boundsbuffer, bounds, nvars) );
469 
470  /* sort variables according to index; this allows us to check for redundancy easily below because duplicate
471  * variables must now appear consecutively */
472  SCIPsortPtrRealInt((void**)varsbuffer, boundsbuffer, (int*) boundtypesbuffer, SCIPvarComp, nvars);
473 
474  /* filter out redundant literals */
475  for( v = 0; v < nvars; ++v )
476  {
477  int w;
478 
479  /* if we should compress fixed variables */
480  if( SCIPisConsCompressionEnabled(scip) && varsbuffer[v] != NULL )
481  {
482  var = varsbuffer[v];
483 
484  /* if the variable is fixed */
485  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
486  {
487  /* If the literal is feasible for the fixed variable, then the whole constraint is feasible. In this
488  * case, we reduce the constraint to only this literal. */
489  if( (boundtypesbuffer[v] == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, var, SCIPvarGetLbLocal(var), boundsbuffer[v]))
490  || (boundtypesbuffer[v] == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, var, SCIPvarGetUbLocal(var), boundsbuffer[v])) )
491  {
492  /* save this feasible assignment at the first position */
493  varsbuffer[0] = var;
494  boundtypesbuffer[0] = boundtypesbuffer[v];
495  boundsbuffer[0] = boundsbuffer[v];
496  nvarsbuffer = 1;
497  break;
498  }
499  else
500  {
501  /* otherwise the literal is violated - we skip the literal */
502  ++nviolated;
503  continue;
504  }
505  }
506  }
507 
508  /* check subsequent variables with the same variable for redundancy */
509  for( w = v + 1; w < nvars && varsbuffer[v] == varsbuffer[w]; ++w )
510  {
511  if( boundtypesbuffer[v] == boundtypesbuffer[w] )
512  {
513  if( boundtypesbuffer[v] == SCIP_BOUNDTYPE_LOWER )
514  {
515  /* check whether current bound is as strong */
516  if( SCIPisLE(scip, boundsbuffer[v], boundsbuffer[w]) )
517  varsbuffer[v] = NULL; /* skip current bound */
518  else
519  varsbuffer[w] = NULL; /* remove later bound */
520  }
521  else
522  {
523  assert(boundtypesbuffer[v] == SCIP_BOUNDTYPE_UPPER);
524 
525  /* check whether current bound is as strong */
526  if( SCIPisGE(scip, boundsbuffer[v], boundsbuffer[w]) )
527  varsbuffer[v] = NULL; /* skip current bound */
528  else
529  varsbuffer[w] = NULL; /* remove later bound */
530  }
531  }
532  }
533 
534  /* keep current bound if it is not redundant (possibly redundant variable w is treated later) */
535  if( varsbuffer[v] != NULL )
536  {
537  /* switch last and current bound */
538  varsbuffer[nvarsbuffer] = varsbuffer[v];
539  boundtypesbuffer[nvarsbuffer] = boundtypesbuffer[v];
540  boundsbuffer[nvarsbuffer] = boundsbuffer[v];
541  ++nvarsbuffer;
542  }
543  }
544  assert( nvarsbuffer > 0 || SCIPisConsCompressionEnabled(scip) ); /* no variables can only happen if compression is enabled */
545 
546 #ifndef NDEBUG
547  /* if there are no variables left, this is because all literals are infeasible */
548  if( nvarsbuffer == 0 )
549  {
550  for( v = 0; v < nvars; v++ )
551  {
552  var = vars[v];
553  assert( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) );
554  assert( (boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasLT(scip, var, SCIPvarGetLbLocal(var), bounds[v]))
555  || (boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasGT(scip, var, SCIPvarGetUbLocal(var), bounds[v])) );
556  }
557  }
558  else
559  {
560  /* check that the literals are not redundant */
561  for( v = 0; v < nvarsbuffer; v++ )
562  {
563  int v2;
564  assert(varsbuffer[v] != NULL);
565  for( v2 = v+1; v2 < nvarsbuffer; v2++ )
566  assert(varsbuffer[v] != varsbuffer[v2] || boundtypesbuffer[v] != boundtypesbuffer[v2]);
567  }
568  }
569 #endif
570 
571  /* if all literals are infeasible, we keep the first */
572  if( SCIPisConsCompressionEnabled(scip) && nviolated > 0 && nvarsbuffer == 0 )
573  nvarsbuffer = 1;
574 
575  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, nvarsbuffer) );
576  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->boundtypes, boundtypesbuffer, nvarsbuffer) );
577  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->bounds, boundsbuffer, nvarsbuffer) );
578  (*consdata)->varssize = nvarsbuffer;
579  (*consdata)->nvars = nvarsbuffer;
580 
581  /* free buffer storage */
582  SCIPfreeBufferArray(scip, &boundsbuffer);
583  SCIPfreeBufferArray(scip, &boundtypesbuffer);
584  SCIPfreeBufferArray(scip, &varsbuffer);
585  }
586  else
587  {
588  (*consdata)->vars = NULL;
589  (*consdata)->boundtypes = NULL;
590  (*consdata)->bounds = NULL;
591  (*consdata)->varssize = 0;
592  (*consdata)->nvars = 0;
593  }
594  (*consdata)->watchedvar1 = -1;
595  (*consdata)->watchedvar2 = -1;
596  (*consdata)->filterpos1 = -1;
597  (*consdata)->filterpos2 = -1;
598 
599  /* get transformed variables, if we are in the transformed problem */
600  if( SCIPisTransformed(scip) )
601  {
602  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
603  }
604 
605  return SCIP_OKAY;
606 }
607 
608 /** frees a bound disjunction constraint data */
609 static
610 void consdataFree(
611  SCIP* scip, /**< SCIP data structure */
612  SCIP_CONSDATA** consdata /**< pointer to the bound disjunction constraint */
613  )
614 {
615  assert(consdata != NULL);
616  assert(*consdata != NULL);
617 
618  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
619  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->boundtypes, (*consdata)->varssize);
620  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->bounds, (*consdata)->varssize);
621  SCIPfreeBlockMemory(scip, consdata);
622 }
623 
624 /** prints bound disjunction constraint to file stream */
625 static
626 void consdataPrint(
627  SCIP* scip, /**< SCIP data structure */
628  SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
629  FILE* file, /**< output file (or NULL for standard output) */
630  SCIP_Bool endline /**< should an endline be set? */
631  )
632 {
633  int v;
634 
635  assert(consdata != NULL);
636 
637  /* print coefficients */
638  SCIPinfoMessage(scip, file, "bounddisjunction(");
639  for( v = 0; v < consdata->nvars; ++v )
640  {
641  assert(consdata->vars[v] != NULL);
642  if( v > 0 )
643  SCIPinfoMessage(scip, file, ", ");
644  SCIPinfoMessage(scip, file, "<%s> %s %.15g", SCIPvarGetName(consdata->vars[v]),
645  consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", consdata->bounds[v]);
646  }
647  SCIPinfoMessage(scip, file, ")");
648 
649  if( endline )
650  SCIPinfoMessage(scip, file, "\n");
651 }
652 
653 /** stores the given variable numbers as watched variables, and updates the event processing */
654 static
656  SCIP* scip, /**< SCIP data structure */
657  SCIP_CONS* cons, /**< bound disjunction constraint */
658  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
659  int watchedvar1, /**< new first watched variable */
660  int watchedvar2 /**< new second watched variable */
661  )
662 {
663  SCIP_CONSDATA* consdata;
664 
665  consdata = SCIPconsGetData(cons);
666  assert(consdata != NULL);
667  assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
668  assert(watchedvar1 != -1 || watchedvar2 == -1);
669  assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
670  assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
671 
672  /* don't watch variables for non active constraints */
673  if( !SCIPconsIsActive(cons) )
674  return SCIP_OKAY;
675 
676  /* if one watched variable is equal to the old other watched variable, just switch positions */
677  if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
678  {
679  int tmp;
680 
681  tmp = consdata->watchedvar1;
682  consdata->watchedvar1 = consdata->watchedvar2;
683  consdata->watchedvar2 = tmp;
684  tmp = consdata->filterpos1;
685  consdata->filterpos1 = consdata->filterpos2;
686  consdata->filterpos2 = tmp;
687  }
688  assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
689  assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
690 
691  /* drop events on old watched variables */
692  if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
693  {
694  assert(consdata->filterpos1 != -1);
695  SCIP_CALL( dropEvents(scip, cons, consdata, eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
696  consdata->watchedvar1 = -1;
697  }
698  if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
699  {
700  assert(consdata->filterpos2 != -1);
701  SCIP_CALL( dropEvents(scip, cons, consdata, eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
702  consdata->watchedvar2 = -1;
703  }
704 
705  /* catch events on new watched variables */
706  if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
707  {
708  SCIP_CALL( catchEvents(scip, cons, consdata, eventhdlr, watchedvar1, &consdata->filterpos1) );
709  }
710  if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
711  {
712  SCIP_CALL( catchEvents(scip, cons, consdata, eventhdlr, watchedvar2, &consdata->filterpos2) );
713  }
714 
715  /* set the new watched variables */
716  consdata->watchedvar1 = watchedvar1;
717  consdata->watchedvar2 = watchedvar2;
718 
719  return SCIP_OKAY;
720 }
721 
722 /** check whether two intervals overlap */
723 static
725  SCIP* scip,
726  SCIP_VAR* var,
727  SCIP_BOUNDTYPE boundtype1,
728  SCIP_Real bound1,
729  SCIP_BOUNDTYPE boundtype2,
730  SCIP_Real bound2
731  )
732 {
733  SCIP_Bool overlapping = FALSE;
734 
735  if( boundtype1 == SCIP_BOUNDTYPE_LOWER )
736  {
737  assert(boundtype2 == SCIP_BOUNDTYPE_UPPER);
738 
739  if( SCIPisLE(scip, bound1 - bound2, (SCIP_Real)SCIPvarIsIntegral(var)) )
740  overlapping = TRUE;
741  }
742  else
743  {
744  assert(boundtype2 == SCIP_BOUNDTYPE_LOWER);
745 
746  if( SCIPisLE(scip, bound2 - bound1, (SCIP_Real)SCIPvarIsIntegral(var)) )
747  overlapping = TRUE;
748  }
749 
750  return overlapping;
751 }
752 
753 /** deletes coefficient at given position from bound disjunction constraint data */
754 static
756  SCIP* scip, /**< SCIP data structure */
757  SCIP_CONS* cons, /**< bound disjunction constraint */
758  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
759  int pos /**< position of coefficient to delete */
760  )
761 {
762  SCIP_CONSDATA* consdata;
763 
764  assert(eventhdlr != NULL);
765 
766  consdata = SCIPconsGetData(cons);
767  assert(consdata != NULL);
768  assert(0 <= pos && pos < consdata->nvars);
769  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
770 
771  /* remove the rounding locks of variable */
772  SCIP_CALL( unlockRounding(scip, cons, consdata, pos) );
773 
774  if( SCIPconsIsTransformed(cons) )
775  {
776  /* if the position is watched, stop watching the position */
777  if( consdata->watchedvar1 == pos )
778  {
779  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar2, -1) );
780  }
781  if( consdata->watchedvar2 == pos )
782  {
783  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, -1) );
784  }
785  }
786  assert(pos != consdata->watchedvar1);
787  assert(pos != consdata->watchedvar2);
788 
789  /* move the last variable to the free slot */
790  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
791  consdata->boundtypes[pos] = consdata->boundtypes[consdata->nvars-1];
792  consdata->bounds[pos] = consdata->bounds[consdata->nvars-1];
793  consdata->nvars--;
794 
795  /* if the last variable (that moved) was watched, update the watched position */
796  if( consdata->watchedvar1 == consdata->nvars )
797  consdata->watchedvar1 = pos;
798  if( consdata->watchedvar2 == consdata->nvars )
799  consdata->watchedvar2 = pos;
800 
801  SCIP_CALL( SCIPenableConsPropagation(scip, cons) );
802 
803  return SCIP_OKAY;
804 }
805 
806 /** adds literal to bound disjunction constraint data */
807 static
809  SCIP* scip, /**< SCIP data structure */
810  SCIP_CONS* cons, /**< bound disjunction constraint */
811  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
812  SCIP_VAR* var, /**< variable in literal */
813  SCIP_BOUNDTYPE boundtype, /**< boundtype of literal */
814  SCIP_Real bound, /**< bound of literal */
815  SCIP_Bool* redundant /**< flag to indicate whether constraint has been bound redundant */
816  )
817 {
818  SCIP_CONSDATA* consdata;
819  int samebndidx;
820  int v;
821 
822  assert(eventhdlr != NULL);
823 
824  consdata = SCIPconsGetData(cons);
825  assert(consdata != NULL);
826  assert(var != NULL);
827  assert(!SCIPisInfinity(scip, REALABS(bound)));
828  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
829 
830  /* ensure enough memory in consdata arrays */
831  if( consdata->varssize == consdata->nvars )
832  {
833  int newsize;
834 
835  newsize = SCIPcalcMemGrowSize(scip, consdata->nvars + 1);
836  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
837  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->boundtypes, consdata->varssize, newsize) );
838  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->bounds, consdata->varssize, newsize) );
839  consdata->varssize = newsize;
840  }
841  assert(consdata->varssize > consdata->nvars);
842 
843  /* remember the position of the literal in the constraint that has the same bound type on the same variable
844  *
845  * example: (x >= 5) or (x <= 2) and literal (x >= 2) should be added.
846  * if we see (x >= 5) first, we cannot stop immediately because only in combination with the second literal
847  * we see that the constraint is redundant.
848  */
849  samebndidx = -1;
850 
851  for( v = 0; v < consdata->nvars; v++ )
852  {
853  /* check if the variable is already part of the constraint */
854  if( consdata->vars[v] == var )
855  {
856  if( consdata->boundtypes[v] == boundtype )
857  samebndidx = v;
858  else if( isOverlapping(scip, var, consdata->boundtypes[v], consdata->bounds[v], boundtype, bound) )
859  {
860  *redundant = TRUE;
861  return SCIP_OKAY;
862  }
863  }
864  }
865 
866  /* the combination of variable and boundtype is already part of the constraint; check whether the clause
867  * can be relaxed
868  */
869  if( samebndidx > -1 )
870  {
871  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisLT(scip, bound, consdata->bounds[samebndidx]))
872  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisGT(scip, bound, consdata->bounds[samebndidx])) )
873  {
874  SCIPdebugMsg(scip, "relax clause of <%s>: (<%s> %s %.15g) -> (<%s> %s %.15g)\n", SCIPconsGetName(cons),
875  SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", consdata->bounds[samebndidx],
876  SCIPvarGetName(var), boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bound);
877  consdata->bounds[samebndidx] = bound;
878  }
879  }
880  else
881  {
882  /* add the variable to the end of the array */
883  consdata->vars[consdata->nvars] = var;
884  consdata->boundtypes[consdata->nvars] = boundtype;
885  consdata->bounds[consdata->nvars] = bound;
886  consdata->nvars++;
887 
888  if( SCIPconsIsTransformed(cons) )
889  {
890  /* add rounding lock of variable */
891  SCIP_CALL( lockRounding(scip, cons, consdata, consdata->nvars-1) );
892 
893  /* if less than 2 variables are watched, add the new one to the watched variables */
894  if( consdata->watchedvar1 == -1 )
895  {
896  assert(consdata->watchedvar2 == -1);
897  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->nvars-1, -1) );
898  }
899  else if( consdata->watchedvar2 == -1 )
900  {
901  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, consdata->nvars-1) );
902  }
903  }
904  }
905 
906  SCIP_CALL( SCIPenableConsPropagation(scip, cons) );
907 
908  return SCIP_OKAY;
909 }
910 
911 /** deletes all variables with global bounds violating the literal, checks for global bounds satisfying the literal */
912 static
914  SCIP* scip, /**< SCIP data structure */
915  SCIP_CONS* cons, /**< bound disjunction constraint */
916  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
917  SCIP_Bool* redundant /**< returns whether a variable fixed to one exists in the constraint */
918  )
919 {
920  SCIP_CONSDATA* consdata;
921  int v;
922  SCIP_Real bnd;
923 
924  assert(eventhdlr != NULL);
925  assert(redundant != NULL);
926 
927  consdata = SCIPconsGetData(cons);
928  assert(consdata != NULL);
929  assert(consdata->nvars == 0 || consdata->vars != NULL);
930 
931  *redundant = FALSE;
932  v = 0;
933  while( v < consdata->nvars )
934  {
935  SCIP_VAR* var;
936 
937  var = consdata->vars[v];
938 
939  if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
940  {
941  bnd = SCIPcomputeVarLbGlobal(scip, var);
942  if( isFeasGE(scip, var, bnd, consdata->bounds[v]) )
943  {
944  *redundant = TRUE;
945  return SCIP_OKAY;
946  }
947  else
948  {
949  bnd = SCIPcomputeVarUbGlobal(scip, var);
950  if( isFeasLT(scip, var, bnd, consdata->bounds[v]) )
951  {
952  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
953  }
954  else
955  ++v;
956  }
957  }
958  else
959  {
960  assert(consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
961  bnd = SCIPcomputeVarUbGlobal(scip, var);
962  if( isFeasLE(scip, var, bnd, consdata->bounds[v]) )
963  {
964  *redundant = TRUE;
965  return SCIP_OKAY;
966  }
967  else
968  {
969  bnd = SCIPcomputeVarLbGlobal(scip, var);
970  if( isFeasGT(scip, var, bnd, consdata->bounds[v]) )
971  {
972  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
973  }
974  else
975  ++v;
976  }
977  }
978  }
979 
980  SCIPdebugMsg(scip, "after global bounds: ");
981  SCIPdebug(consdataPrint(scip, consdata, NULL, TRUE));
982 
983  return SCIP_OKAY;
984 }
985 
986 /** returns whether literal at the given position is satisfied in the local bounds */
987 static
989  SCIP* scip, /**< SCIP data structure */
990  SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
991  int pos /**< position of the literal */
992  )
993 {
994  SCIP_Real bnd;
995 
996  assert(consdata != NULL);
997  assert(0 <= pos && pos < consdata->nvars);
998 
999  if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
1000  {
1001  bnd = SCIPcomputeVarLbLocal(scip, consdata->vars[pos]);
1002  return isFeasGE(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1003  }
1004  else
1005  {
1006  bnd = SCIPcomputeVarUbLocal(scip, consdata->vars[pos]);
1007  return isFeasLE(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1008  }
1009 }
1010 
1011 /** returns whether literal at the given position is violated in the local bounds */
1012 static
1014  SCIP* scip, /**< SCIP data structure */
1015  SCIP_CONSDATA* consdata, /**< bound disjunction constraint data */
1016  int pos /**< position of the literal */
1017  )
1018 {
1019  SCIP_Real bnd;
1020 
1021  assert(consdata != NULL);
1022  assert(0 <= pos && pos < consdata->nvars);
1023 
1024  if( consdata->boundtypes[pos] == SCIP_BOUNDTYPE_LOWER )
1025  {
1026  bnd = SCIPcomputeVarUbLocal(scip, consdata->vars[pos]);
1027  return isFeasLT(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1028  }
1029  else
1030  {
1031  bnd = SCIPcomputeVarLbLocal(scip, consdata->vars[pos]);
1032  return isFeasGT(scip, consdata->vars[pos], bnd, consdata->bounds[pos]);
1033  }
1034 }
1035 
1036 /** replace variables by their representative active (or multi-aggregated) variables */
1037 static
1039  SCIP* scip, /**< SCIP data structure */
1040  SCIP_CONS* cons, /**< bound disjunction constraint */
1041  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
1042  SCIP_Bool* redundant /**< flag to indicate whether constraint has been bound redundant */
1043  )
1044 {
1045  SCIP_CONSDATA* consdata;
1046  SCIP_VAR* var;
1047  SCIP_BOUNDTYPE boundtype;
1048  SCIP_Real bound;
1049  int v;
1050 
1051  assert(scip != NULL);
1052  assert(cons != NULL);
1053  assert(eventhdlr != NULL);
1054 
1055  consdata = SCIPconsGetData(cons);
1056  assert(consdata != NULL);
1057 
1058  v = 0;
1059  while( v < consdata->nvars )
1060  {
1061 #ifndef NDEBUG
1062  SCIP_VAR* oldvar;
1063 #endif
1064  var = consdata->vars[v];
1065  assert(var != NULL);
1066 
1067 #ifndef NDEBUG
1068  oldvar = var;
1069 #endif
1070 
1072  {
1073  /* check whether the literal is satisfied and the constraint is thus redundant */
1074  if( isLiteralSatisfied(scip, consdata, v) )
1075  {
1076  *redundant = TRUE;
1077  break;
1078  }
1079  if( isLiteralViolated(scip, consdata, v) )
1080  {
1081  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1082  continue;
1083  }
1084 
1085  ++v;
1086 
1087  continue;
1088  }
1089 
1090  /* get active/fixed/multiaggr equivalent of v'th literal */
1091  bound = consdata->bounds[v];
1092  boundtype = consdata->boundtypes[v];
1093  SCIP_CALL( SCIPvarGetProbvarBound(&var, &bound, &boundtype) );
1094  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED || oldvar != var);
1095 
1096  SCIPdebugMsg(scip, "in <%s>, replace <%s>[%g,%g] %c= %g by <%s>[%g,%g] %c= %g\n", SCIPconsGetName(cons),
1097  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbGlobal(consdata->vars[v]), SCIPvarGetUbGlobal(consdata->vars[v]), (consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? '>' : '<'), consdata->bounds[v],
1098  SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var), (boundtype == SCIP_BOUNDTYPE_LOWER ? '>' : '<'), bound);
1099 
1100  /* if literal is satisfied, then constraint is redundant and we can stop */
1101  if( (boundtype == SCIP_BOUNDTYPE_LOWER && isFeasLE(scip, var, bound, SCIPvarGetLbGlobal(var))) || /*lint !e666*/
1102  (boundtype == SCIP_BOUNDTYPE_UPPER && isFeasGE(scip, var, bound, SCIPvarGetUbGlobal(var))) ) /*lint !e666*/
1103  {
1104  *redundant = TRUE;
1105  break;
1106  }
1107 
1108  /* if literal is not fixed, replace it */
1110  {
1111  /* add new literal */
1112  SCIP_CALL( addCoef(scip, cons, eventhdlr, var, boundtype, bound, redundant) );
1113  }
1114 
1115  /* remove old literal */
1116  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1117  }
1118 
1119  return SCIP_OKAY;
1120 }
1121 
1122 /** try to upgrade the bounddisjunction constraint
1123  *
1124  * if only binary variables are left, we can upgrade a bounddisjunction to a logicor constraint(, if only two variables
1125  * are left, this logicor constraint can be formulated as set-packing constraint as well)
1126  *
1127  * e.g.: bounddisjunction( x1 >= 1, x2 <= 0; x3 >= 1; x4 <= 0 ) => x1 + ~x2 + x3 + ~x4 >= 1
1128  */
1129 static
1131  SCIP* scip, /**< SCIP data structure */
1132  SCIP_CONS* cons, /**< bound disjunction constraint that detected the conflict */
1133  int* ndelconss, /**< pointer to store the number of delete constraint */
1134  int* naddconss /**< pointer to store the number of added constraint */
1135  )
1136 {
1137  SCIP_CONSDATA* consdata;
1138  SCIP_VAR** newvars;
1139  SCIP_Bool allbinary;
1140  int nvars;
1141  int v;
1142 
1143  assert(scip != NULL);
1144  assert(cons != NULL);
1145  assert(ndelconss != NULL);
1146  assert(naddconss != NULL);
1147  assert(naddconss != NULL);
1148  assert(!SCIPconsIsModifiable(cons));
1149 
1150  consdata = SCIPconsGetData(cons);
1151  assert(consdata != NULL);
1152 
1153  nvars = consdata->nvars;
1154  assert(nvars >= 2);
1155  assert(consdata->vars != NULL);
1156 
1157  allbinary = TRUE;
1158 
1159  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nvars) );
1160 
1161  for( v = nvars - 1; v >= 0; --v )
1162  {
1163  if( !SCIPvarIsBinary(consdata->vars[v]) )
1164  {
1165  allbinary = FALSE;
1166  break;
1167  }
1168  else
1169  {
1170  if( consdata->boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
1171  {
1172  assert(SCIPisFeasGT(scip, consdata->bounds[v], 0.0));
1173 
1174  if( nvars == 2 )
1175  {
1176  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[v], &(newvars[v])) );
1177  }
1178  else
1179  newvars[v] = consdata->vars[v];
1180  }
1181  else
1182  {
1183  assert(consdata->boundtypes[v] == SCIP_BOUNDTYPE_UPPER);
1184  assert(SCIPisFeasLT(scip, consdata->bounds[v], 1.0));
1185 
1186  if( nvars > 2 )
1187  {
1188  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[v], &(newvars[v])) );
1189  }
1190  else
1191  newvars[v] = consdata->vars[v];
1192  }
1193  }
1194  }
1195 
1196  if( allbinary )
1197  {
1198  SCIP_CONS* newcons;
1199 
1200  if( nvars == 2 )
1201  {
1202  SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), nvars, newvars,
1207  }
1208  else
1209  {
1210  SCIP_CALL( SCIPcreateConsLogicor(scip, &newcons, SCIPconsGetName(cons), nvars, newvars,
1215  }
1216 
1217  SCIPdebugMsg(scip, "updated constraint <%s> to the following %s constraint\n", SCIPconsGetName(cons), (nvars == 2 ? "setppc" : "logicor"));
1218  SCIPdebugPrintCons(scip, newcons, NULL);
1219  SCIP_CALL( SCIPaddCons(scip, newcons) );
1220  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1221  ++(*naddconss);
1222 
1223  SCIP_CALL( SCIPdelCons(scip, cons) );
1224  ++(*ndelconss);
1225  }
1226 
1227  SCIPfreeBufferArray(scip, &newvars);
1228 
1229  return SCIP_OKAY;
1230 }
1231 
1232 /** analyzes conflicting assignment on given constraint, and adds conflict constraint to problem */
1233 static
1235  SCIP* scip, /**< SCIP data structure */
1236  SCIP_CONS* cons /**< bound disjunction constraint that detected the conflict */
1237  )
1238 {
1239  SCIP_CONSDATA* consdata;
1240  int v;
1241 
1242  /* conflict analysis can only be applied in solving stage and if it is turned on */
1244  return SCIP_OKAY;
1245 
1246  consdata = SCIPconsGetData(cons);
1247  assert(consdata != NULL);
1248 
1249  /* initialize conflict analysis, and add all bounds of infeasible constraint to conflict candidate queue */
1251 
1252  for( v = 0; v < consdata->nvars; ++v )
1253  {
1254  /* the opposite bound is in conflict with this literal */
1255  SCIP_CALL( SCIPaddConflictBd(scip, consdata->vars[v], SCIPboundtypeOpposite(consdata->boundtypes[v]), NULL) );
1256  }
1257 
1258  /* analyze the conflict */
1259  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
1260 
1261  return SCIP_OKAY;
1262 }
1263 
1264 /** disables or deletes the given constraint, depending on the current depth */
1265 static
1267  SCIP* scip, /**< SCIP data structure */
1268  SCIP_CONS* cons /**< bound disjunction constraint to be disabled */
1269  )
1270 {
1271  assert(SCIPconsGetValidDepth(cons) <= SCIPgetDepth(scip));
1272 
1273  if( SCIPgetDepth(scip) == SCIPconsGetValidDepth(cons) )
1274  {
1275  SCIP_CALL( SCIPdelCons(scip, cons) );
1276  }
1277  else
1278  {
1279  SCIP_CALL( SCIPdisableCons(scip, cons) );
1280  }
1281 
1282  return SCIP_OKAY;
1283 }
1284 
1285 /** checks constraint for violation only looking at the watched variables, applies bound changes if possible */
1286 static
1288  SCIP* scip, /**< SCIP data structure */
1289  SCIP_CONS* cons, /**< bound disjunction constraint to be processed */
1290  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1291  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1292  SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint is infeasible in current bounds */
1293  SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
1294  SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
1295  )
1296 {
1297  SCIP_CONSDATA* consdata;
1298  SCIP_VAR** vars;
1299  SCIP_BOUNDTYPE* boundtypes;
1300  SCIP_Real* bounds;
1301  SCIP_Longint nbranchings1;
1302  SCIP_Longint nbranchings2;
1303  int nvars;
1304  int watchedvar1;
1305  int watchedvar2;
1306 
1307  assert(cons != NULL);
1308  assert(SCIPconsGetHdlr(cons) != NULL);
1309  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1310  assert(cutoff != NULL);
1311  assert(reduceddom != NULL);
1312  assert(mustcheck != NULL);
1313 
1314  consdata = SCIPconsGetData(cons);
1315  assert(consdata != NULL);
1316  assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
1317 
1318  /* init bools */
1319  *cutoff = FALSE;
1320  *infeasible = FALSE;
1321  *reduceddom = FALSE;
1322  *mustcheck = FALSE;
1323 
1324  SCIPdebugMsg(scip, "processing watched variables of constraint <%s>\n", SCIPconsGetName(cons));
1325 
1326  nvars = consdata->nvars;
1327  vars = consdata->vars;
1328  boundtypes = consdata->boundtypes;
1329  bounds = consdata->bounds;
1330  assert(nvars == 0 || vars != NULL);
1331  assert(nvars == 0 || boundtypes != NULL);
1332  assert(nvars == 0 || bounds != NULL);
1333 
1334  /* check watched variables if they are satisfying the literal */
1335  if( consdata->watchedvar1 >= 0 && isLiteralSatisfied(scip, consdata, consdata->watchedvar1) )
1336  {
1337  /* the literal is satisfied, making the constraint redundant */
1338  SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar1 satisfied)\n", SCIPconsGetName(cons));
1339  SCIP_CALL( disableCons(scip, cons) );
1340  return SCIP_OKAY;
1341  }
1342  if( consdata->watchedvar2 >= 0 && isLiteralSatisfied(scip, consdata, consdata->watchedvar2) )
1343  {
1344  /* the literal is satisfied, making the constraint redundant */
1345  SCIPdebugMsg(scip, " -> disabling constraint <%s> (watchedvar2 satisfied)\n", SCIPconsGetName(cons));
1346  SCIP_CALL( disableCons(scip, cons) );
1347  return SCIP_OKAY;
1348  }
1349 
1350  /* check if watched variables are still undecided */
1351  watchedvar1 = -1;
1352  watchedvar2 = -1;
1353  nbranchings1 = SCIP_LONGINT_MAX;
1354  nbranchings2 = SCIP_LONGINT_MAX;
1355  if( consdata->watchedvar1 >= 0 && !isLiteralViolated(scip, consdata, consdata->watchedvar1) )
1356  {
1357  watchedvar1 = consdata->watchedvar1;
1358  nbranchings1 = -1; /* prefer keeping the watched variable */
1359  }
1360  if( consdata->watchedvar2 >= 0 && !isLiteralViolated(scip, consdata, consdata->watchedvar2) )
1361  {
1362  if( watchedvar1 == -1 )
1363  {
1364  watchedvar1 = consdata->watchedvar2;
1365  nbranchings1 = -1; /* prefer keeping the watched variable */
1366  }
1367  else
1368  {
1369  watchedvar2 = consdata->watchedvar2;
1370  nbranchings2 = -1; /* prefer keeping the watched variable */
1371  }
1372  }
1373  assert(watchedvar1 >= 0 || watchedvar2 == -1);
1374  assert(nbranchings1 <= nbranchings2);
1375  assert(watchedvar1 != -1 || nbranchings1 == SCIP_LONGINT_MAX);
1376  assert(watchedvar2 != -1 || nbranchings2 == SCIP_LONGINT_MAX);
1377 
1378  /* search for new watched variables */
1379  if( watchedvar2 == -1 )
1380  {
1381  int v;
1382 
1383  for( v = 0; v < nvars; ++v )
1384  {
1385  SCIP_Longint nbranchings;
1386 
1387  /* don't process the watched variables again */
1388  if( v == consdata->watchedvar1 || v == consdata->watchedvar2 )
1389  continue;
1390 
1391  /* check, if the literal is violated */
1392  if( isLiteralViolated(scip, consdata, v) )
1393  continue;
1394 
1395  /* check, if the literal is satisfied */
1396  if( isLiteralSatisfied(scip, consdata, v) )
1397  {
1398  assert(v != consdata->watchedvar1);
1399  assert(v != consdata->watchedvar2);
1400 
1401  /* the literal is satisfied, making the constraint redundant;
1402  * make sure, the feasible variable is watched and disable the constraint
1403  */
1404  SCIPdebugMsg(scip, " -> disabling constraint <%s> (variable <%s> fixed to 1.0)\n",
1405  SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
1406  if( consdata->watchedvar1 != -1 )
1407  {
1408  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, consdata->watchedvar1, v) );
1409  }
1410  else
1411  {
1412  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, v, consdata->watchedvar2) );
1413  }
1414  SCIP_CALL( disableCons(scip, cons) );
1415  return SCIP_OKAY;
1416  }
1417 
1418  /* the literal is still undecided and can be used as watched variable */
1419  nbranchings = SCIPvarGetNBranchingsCurrentRun(vars[v],
1421  if( nbranchings < nbranchings2 )
1422  {
1423  if( nbranchings < nbranchings1 )
1424  {
1425  watchedvar2 = watchedvar1;
1426  nbranchings2 = nbranchings1;
1427  watchedvar1 = v;
1428  nbranchings1 = nbranchings;
1429  }
1430  else
1431  {
1432  watchedvar2 = v;
1433  nbranchings2 = nbranchings;
1434  }
1435  }
1436  }
1437  }
1438  assert(nbranchings1 <= nbranchings2);
1439  assert(watchedvar1 >= 0 || watchedvar2 == -1);
1440 
1441  if( watchedvar1 == -1 )
1442  {
1443  /* there is no undecided literal left -> the constraint is infeasible
1444  * - a modifiable constraint is infeasible
1445  * - an unmodifiable constraint is infeasible and the node can be cut off
1446  */
1447  assert(watchedvar2 == -1);
1448 
1449  SCIPdebugMsg(scip, " -> constraint <%s> is infeasible\n", SCIPconsGetName(cons));
1450  *infeasible = TRUE;
1451 
1452  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1453  if( !SCIPconsIsModifiable(cons) )
1454  {
1455  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1456  SCIP_CALL( analyzeConflict(scip, cons) );
1457 
1458  /* mark the node to be cut off */
1459  *cutoff = TRUE;
1460  }
1461  }
1462  else if( watchedvar2 == -1 )
1463  {
1464  /* there is only one undecided literal:
1465  * - a modifiable constraint must be checked manually
1466  * - we cannot change bounds of multi-aggregated variables and have to check manually
1467  * - an unmodifiable constraint is feasible and can be disabled after the remaining literal is satisfied
1468  */
1469  assert(0 <= watchedvar1 && watchedvar1 < nvars);
1470  assert(!isLiteralViolated(scip, consdata, watchedvar1));
1471  assert(!isLiteralSatisfied(scip, consdata, watchedvar1));
1472  if( SCIPconsIsModifiable(cons)
1473  || SCIPvarGetStatus(SCIPvarGetProbvar(vars[watchedvar1])) == SCIP_VARSTATUS_MULTAGGR )
1474  *mustcheck = TRUE;
1475  else
1476  {
1477  SCIP_Bool infbdchg;
1478 
1479 #ifndef NDEBUG
1480  int v;
1481 
1482  /* check whether all other literals are violated */
1483  for (v = 0; v < nvars; ++v)
1484  {
1485  if ( v != watchedvar1 )
1486  {
1487  assert( isLiteralViolated(scip, consdata, v) );
1488  }
1489  }
1490 #endif
1491 
1492  /* satisfy remaining literal and disable constraint; make sure, the fixed-to-one variable is watched */
1493  SCIPdebugMsg(scip, " -> single-literal constraint <%s> (change bound <%s> %s %g) at depth %d\n",
1494  SCIPconsGetName(cons), SCIPvarGetName(vars[watchedvar1]),
1495  boundtypes[watchedvar1] == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", bounds[watchedvar1], SCIPgetDepth(scip));
1496 
1497  if( boundtypes[watchedvar1] == SCIP_BOUNDTYPE_LOWER )
1498  {
1499  SCIP_CALL( SCIPinferVarLbCons(scip, vars[watchedvar1], bounds[watchedvar1], cons, watchedvar1, TRUE,
1500  &infbdchg, NULL) );
1501  }
1502  else
1503  {
1504  SCIP_CALL( SCIPinferVarUbCons(scip, vars[watchedvar1], bounds[watchedvar1], cons, watchedvar1, TRUE,
1505  &infbdchg, NULL) );
1506  }
1507  assert(!infbdchg);
1508  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1509  if( watchedvar1 != consdata->watchedvar1 ) /* keep one of the watched variables */
1510  {
1511  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, consdata->watchedvar1) );
1512  }
1513  SCIP_CALL( disableCons(scip, cons) );
1514  *reduceddom = TRUE;
1515  }
1516  }
1517  else
1518  {
1519  SCIPdebugMsg(scip, " -> new watched variables <%s> and <%s> of constraint <%s> are still undecided\n",
1520  SCIPvarGetName(vars[watchedvar1]), SCIPvarGetName(vars[watchedvar2]), SCIPconsGetName(cons));
1521 
1522  /* switch to the new watched variables */
1523  SCIP_CALL( switchWatchedvars(scip, cons, eventhdlr, watchedvar1, watchedvar2) );
1524 
1525  /* there are at least two undecided variables -> the constraint must be checked manually */
1526  *mustcheck = TRUE;
1527 
1528  /* disable propagation of constraint until the corresponding bound of a watched variable changed */
1529  SCIP_CALL( SCIPdisableConsPropagation(scip, cons) );
1530 
1531  /* increase aging counter */
1532  SCIP_CALL( SCIPaddConsAge(scip, cons, AGEINCREASE(consdata->nvars)) );
1533  }
1534 
1535  return SCIP_OKAY;
1536 }
1537 
1538 /** checks constraint for violation, returns TRUE iff constraint is violated */
1539 static
1541  SCIP* scip, /**< SCIP data structure */
1542  SCIP_CONS* cons, /**< bound disjunction constraint to be checked */
1543  SCIP_SOL* sol /**< primal CIP solution */
1544  )
1545 {
1546  SCIP_CONSDATA* consdata;
1547  SCIP_VAR** vars;
1548  SCIP_BOUNDTYPE* boundtypes;
1549  SCIP_Real* bounds;
1550  SCIP_Real solval;
1551  SCIP_Real viol;
1552  SCIP_Real absviol;
1553  int violpos;
1554  int nvars;
1555  int v;
1556 
1557  consdata = SCIPconsGetData(cons);
1558  assert(consdata != NULL);
1559 
1560  nvars = consdata->nvars;
1561  vars = consdata->vars;
1562  boundtypes = consdata->boundtypes;
1563  bounds = consdata->bounds;
1564  assert(nvars == 0 || vars != NULL);
1565  assert(nvars == 0 || boundtypes != NULL);
1566  assert(nvars == 0 || bounds != NULL);
1567 
1568  /* check the given solution */
1569  absviol = SCIP_REAL_MAX;
1570  violpos = -1;
1571  for( v = 0; v < nvars; ++v )
1572  {
1573  solval = SCIPgetSolVal(scip, sol, vars[v]);
1574 
1575  /* update absolute violation if needed */
1576  viol = (boundtypes[v] == SCIP_BOUNDTYPE_LOWER) ? bounds[v] - solval : solval - bounds[v];
1577  if( viol < absviol )
1578  {
1579  absviol = viol;
1580  violpos = v;
1581  }
1582 
1583  if( (boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, vars[v], solval, bounds[v]))
1584  || (boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, vars[v], solval, bounds[v])) )
1585  {
1586  return FALSE;
1587  }
1588  }
1589  /* update constraint violation in solution */
1590  if( sol != NULL )
1591  {
1592  SCIP_Real relviol;
1593 
1594  assert(0 == nvars || -1 != violpos);
1595 
1596  if( 0 == nvars )
1597  relviol = SCIP_REAL_MAX;
1598  else
1599  relviol = SCIPrelDiff(SCIPgetSolVal(scip, sol, vars[violpos]), bounds[violpos]);
1600 
1601  SCIPupdateSolConsViolation(scip, sol, absviol, relviol);
1602  }
1603  return TRUE;
1604 }
1605 
1606 /* registers variables of a constraint as branching candidates
1607  * indicates whether an n-ary branch is necessary to enforce this constraint,
1608  * because all active literals are w.r.t. continuous variables which bound (in the literal) is at the variable's bound
1609  */
1610 static
1612  SCIP* scip, /**< SCIP data structure */
1613  SCIP_CONS* cons, /**< bound disjunction constraint which variables should be registered for branching */
1614  SCIP_SOL* sol, /**< solution (NULL for LP solution) */
1615  SCIP_Bool* cutoff, /**< pointer to store whether the constraint cannot be made feasible by branching */
1616  SCIP_Bool* neednarybranch /**< pointer to store TRUE, if n-ary branching is necessary to enforce this constraint */
1617  )
1618 {
1619  SCIP_CONSDATA* consdata;
1620  SCIP_VAR** vars;
1621  SCIP_BOUNDTYPE* boundtypes;
1622  SCIP_Real* bounds;
1623  SCIP_Real violation;
1624  SCIP_Real varlb;
1625  SCIP_Real varub;
1626  int nvars;
1627  int v;
1628 
1629  assert(cons != NULL);
1630  assert(SCIPconsGetHdlr(cons) != NULL);
1631  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1632  assert(cutoff != NULL);
1633  assert(neednarybranch != NULL);
1634 
1635  consdata = SCIPconsGetData(cons);
1636  assert(consdata != NULL);
1637  nvars = consdata->nvars;
1638  vars = consdata->vars;
1639  boundtypes = consdata->boundtypes;
1640  bounds = consdata->bounds;
1641  assert(nvars == 0 || vars != NULL);
1642  assert(nvars == 0 || boundtypes != NULL);
1643  assert(nvars == 0 || bounds != NULL);
1644 
1645  *cutoff = TRUE;
1646  *neednarybranch = TRUE;
1647 
1648  for( v = 0; v < nvars; ++v )
1649  {
1650  SCIP_VAR* var;
1651 
1652  var = vars[v];
1653  assert(var != NULL);
1654 
1655  /* constraint should be violated, so all bounds in the constraint have to be violated */
1656  assert( !(boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPisFeasGE(scip, SCIPgetSolVal(scip, sol, var), bounds[v])) &&
1657  !(boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPisFeasLE(scip, SCIPgetSolVal(scip, sol, var), bounds[v])) );
1658 
1659  varlb = SCIPcomputeVarLbLocal(scip, var);
1660  varub = SCIPcomputeVarUbLocal(scip, var);
1661 
1662  /* if literal is x >= varlb, but upper bound on x is < varlb, then this literal can never be satisfied,
1663  * thus there is no use for branching
1664  */
1665  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasLT(scip, var, varub, bounds[v]) )
1666  continue;
1667 
1668  /* if literal is x <= varub, but lower bound on x is > varub, then this literal can never be satisfied,
1669  * thus there is no use for branching
1670  */
1671  if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasGT(scip, var, varlb, bounds[v]) )
1672  continue;
1673 
1674  /* if literal is always satisfied, then no need to branch on it may happen if propagation is disabled for some
1675  * reason and due to numerics current solution does not satisfy literal, but variable bounds do
1676  */
1677  if( isLiteralSatisfied(scip, consdata, v) )
1678  continue;
1679 
1680  violation = SCIPgetSolVal(scip, sol, var) - bounds[v];
1681 
1682  /* if variable is continuous, then we cannot branch on one of the variable bounds */
1683  if( SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS ||
1684  ((SCIPisInfinity(scip, -varlb) || !SCIPisFeasEQ(scip, bounds[v], varlb)) &&
1685  (SCIPisInfinity(scip, varub) || !SCIPisFeasEQ(scip, bounds[v], varub))) )
1686  {
1687  SCIP_CALL( SCIPaddExternBranchCand(scip, var, REALABS(violation), bounds[v]) );
1688  *neednarybranch = FALSE;
1689  }
1690  *cutoff = FALSE;
1691  }
1692 
1693  return SCIP_OKAY;
1694 }
1695 
1696 /** enforces the pseudo or LP solution on the given constraint */
1697 static
1699  SCIP* scip, /**< SCIP data structure */
1700  SCIP_CONS* cons, /**< bound disjunction constraint to be separated */
1701  SCIP_SOL* sol, /**< solution which should be enforced (NULL for LP solution) */
1702  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1703  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1704  SCIP_Bool* infeasible, /**< pointer to store TRUE, if the constraint was infeasible */
1705  SCIP_Bool* reduceddom, /**< pointer to store TRUE, if a domain reduction was found */
1706  SCIP_Bool* registeredbrcand /**< pointer to store TRUE, if branching variable candidates were registered or was already true */
1707  )
1708 {
1709  SCIP_Bool mustcheck;
1710  SCIP_Bool neednarybranch;
1711 
1712  assert(cons != NULL);
1713  assert(SCIPconsGetHdlr(cons) != NULL);
1714  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1715  assert(cutoff != NULL);
1716  assert(infeasible != NULL);
1717  assert(reduceddom != NULL);
1718  assert(registeredbrcand != NULL);
1719 
1720  SCIPdebugMsg(scip, "enforce bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
1721 
1722  /* update and check the watched variables, if they were changed since last processing */
1723  if( SCIPconsIsPropagationEnabled(cons) )
1724  {
1725  SCIP_CALL( processWatchedVars(scip, cons, eventhdlr, cutoff, infeasible, reduceddom, &mustcheck) );
1726  }
1727  else
1728  mustcheck = TRUE;
1729 
1730  if( mustcheck )
1731  {
1732  if( isConsViolated(scip, cons, sol) )
1733  {
1734  /* constraint was infeasible -> reset age */
1735  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1736  *infeasible = TRUE;
1737 
1738  /* register branching candidates */
1739  SCIP_CALL( registerBranchingCandidates(scip, cons, sol, cutoff, &neednarybranch) );
1740 
1741  if( !neednarybranch )
1742  *registeredbrcand = TRUE;
1743  }
1744  }
1745 
1746  return SCIP_OKAY;
1747 }
1748 
1749 /** enforces a constraint by creating an n-ary branch consisting of a set of child nodes, each enforcing one literal
1750  */
1751 static
1753  SCIP* scip, /**< SCIP data structure */
1754  SCIP_CONS* cons, /**< bound disjunction constraint to branch on */
1755  SCIP_SOL* sol /**< solution which should be enforced (NULL for LP solution) */
1756  )
1757 {
1758  SCIP_CONSDATA* consdata;
1759  SCIP_VAR** vars;
1760  SCIP_BOUNDTYPE* boundtypes;
1761  SCIP_Real* bounds;
1762  SCIP_Real varlb;
1763  SCIP_Real varub;
1764  int nvars;
1765  int v;
1766 
1767  SCIP_Real priority;
1768  SCIP_Real estimate;
1769  SCIP_NODE* node;
1770 
1771  assert(cons != NULL);
1772  assert(SCIPconsGetHdlr(cons) != NULL);
1773  assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
1774 
1775  consdata = SCIPconsGetData(cons);
1776  assert(consdata != NULL);
1777  nvars = consdata->nvars;
1778  vars = consdata->vars;
1779  boundtypes = consdata->boundtypes;
1780  bounds = consdata->bounds;
1781  assert(nvars == 0 || vars != NULL);
1782  assert(nvars == 0 || boundtypes != NULL);
1783  assert(nvars == 0 || bounds != NULL);
1784 
1785  for( v = 0; v < nvars; ++v )
1786  {
1787  SCIP_VAR* var;
1788 
1789  var = vars[v];
1790  assert(var != NULL);
1791 
1792  /* constraint should be violated, so all bounds in the constraint have to be violated */
1793  assert( !(boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasGE(scip, var, SCIPgetSolVal(scip, sol, var), bounds[v])) && /*lint !e666*/
1794  !(boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasLE(scip, var, SCIPgetSolVal(scip, sol, var), bounds[v])) ); /*lint !e666*/
1795 
1796  varlb = SCIPcomputeVarLbLocal(scip, var);
1797  varub = SCIPcomputeVarUbLocal(scip, var);
1798 
1799  /* if literal is x >= varlb, but upper bound on x is < varlb, then this literal can never be satisfied,
1800  * thus there is no use in creating an extra child for it
1801  */
1802  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && isFeasLT(scip, var, varub, bounds[v]) )
1803  continue;
1804  /* if literal is x <= varub, but lower bound on x is > varub, then this literal can never be satisfied,
1805  * thus there is no use in creating an extra child for it
1806  */
1807  if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && isFeasGT(scip, var, varlb, bounds[v]) )
1808  continue;
1809  /* if literal is always satisfied, then no need to branch on it */
1810  if( isLiteralSatisfied(scip, consdata, v) )
1811  continue;
1812 
1813  /* create a child that enforces the current literal */
1814  priority = SCIPcalcNodeselPriority(scip, var, boundtypes[v] == SCIP_BOUNDTYPE_LOWER ?
1816  estimate = SCIPcalcChildEstimate (scip, var, bounds[v]);
1817 
1818  SCIPdebugMsg(scip, " -> creating child to enforce: <%s> %c= %g (priority: %g, estimate: %g)\n",
1819  SCIPvarGetName(vars[v]), boundtypes[v] == SCIP_BOUNDTYPE_LOWER ? '>' : '<', bounds[v], priority, estimate);
1820 
1821  SCIP_CALL( SCIPcreateChild(scip, &node, priority, estimate) );
1822 
1823  /* enforce current literal */
1825  {
1826  SCIP_CONS* brcons;
1827  SCIP_Real one;
1828 
1829  one = 1.0;
1830 
1831  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
1832  {
1833  SCIP_CALL( SCIPcreateConsLinear(scip, &brcons, "bounddisjbranch", 1, &var, &one, bounds[v], SCIPinfinity(scip),
1837  SCIPconsIsStickingAtNode(cons)) );
1838  }
1839  else
1840  {
1841  SCIP_CALL( SCIPcreateConsLinear(scip, &brcons, "bounddisjbranch", 1, &var, &one, -SCIPinfinity(scip), bounds[v],
1845  SCIPconsIsStickingAtNode(cons)) );
1846  }
1847  SCIP_CALL( SCIPaddConsNode(scip, node, brcons, NULL) );
1848  SCIP_CALL( SCIPreleaseCons(scip, &brcons) );
1849  }
1850  else
1851  {
1852  assert(SCIPvarIsActive(var));
1853  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER )
1854  {
1855  SCIP_CALL( SCIPchgVarLbNode(scip, node, var, bounds[v]) );
1856  }
1857  else
1858  {
1859  SCIP_CALL( SCIPchgVarUbNode(scip, node, var, bounds[v]) );
1860  }
1861  }
1862 
1863  /* delete bound disjunction constraint from child node */
1864  SCIP_CALL( SCIPdelConsNode(scip, node, cons) );
1865  }
1866 
1867  return SCIP_OKAY;
1868 }
1869 
1870 /** helper function to enforce constraints */
1871 static
1873  SCIP* scip, /**< SCIP data structure */
1874  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1875  SCIP_CONS** conss, /**< constraints to process */
1876  int nconss, /**< number of constraints */
1877  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
1878  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
1879  )
1880 {
1881  SCIP_CONSHDLRDATA* conshdlrdata;
1882  SCIP_Bool cutoff;
1883  SCIP_Bool infeasible;
1884  SCIP_Bool reduceddom;
1885  SCIP_Bool registeredbrcand;
1886  SCIP_Bool infeasiblecons;
1887  int c;
1888  int nnarybranchconsvars;
1889  SCIP_CONS* narybranchcons; /* constraint that is a candidate for an n-ary branch */
1890 
1891  assert(conshdlr != NULL);
1892  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1893  assert(nconss == 0 || conss != NULL);
1894  assert(result != NULL);
1895 
1896  SCIPdebugMsg(scip, "Enforcing %d bound disjunction constraints for %s solution\n", nconss, sol == NULL ? "LP" : "relaxation");
1897 
1898  *result = SCIP_FEASIBLE;
1899 
1900  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1901  assert(conshdlrdata != NULL);
1902 
1903  cutoff = FALSE;
1904  infeasible = FALSE;
1905  reduceddom = FALSE;
1906  registeredbrcand = FALSE;
1907  narybranchcons = NULL;
1908  nnarybranchconsvars = INT_MAX;
1909 
1910  /* check all bound disjunction constraints for feasibility */
1911  for( c = 0; c < nconss && !cutoff && !reduceddom; ++c )
1912  {
1913  infeasiblecons = FALSE;
1914  SCIP_CALL( enforceCurrentSol(scip, conss[c], sol, conshdlrdata->eventhdlr, &cutoff, &infeasiblecons, &reduceddom,
1915  &registeredbrcand) );
1916  infeasible |= infeasiblecons;
1917  if( infeasiblecons && !registeredbrcand )
1918  {
1919  /* if cons. c has less literals than the previous candidate for an n-ary branch, then keep cons. c as candidate for n-ary branch */
1920  if( narybranchcons == NULL || SCIPconsGetData(conss[c])->nvars < nnarybranchconsvars )
1921  {
1922  narybranchcons = conss[c];
1923  nnarybranchconsvars = SCIPconsGetData(narybranchcons)->nvars;
1924  assert(nnarybranchconsvars > 0);
1925  }
1926  }
1927  }
1928 
1929  if( cutoff )
1930  *result = SCIP_CUTOFF;
1931  else if( reduceddom )
1932  *result = SCIP_REDUCEDDOM;
1933  else if( infeasible )
1934  {
1935  if( registeredbrcand )
1936  {
1937  *result = SCIP_INFEASIBLE;
1938  }
1939  else
1940  {
1941  SCIP_CALL( createNAryBranch(scip, narybranchcons, sol) );
1942  *result = SCIP_BRANCHED;
1943  }
1944  }
1945 
1946  return SCIP_OKAY;
1947 }
1948 
1949 /**@} */
1950 
1951 /**@name Callback methods of constraint handler
1952  *
1953  * @{
1954  */
1955 
1956 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1957 static
1958 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyBounddisjunction)
1959 { /*lint --e{715}*/
1960  assert(scip != NULL);
1961  assert(conshdlr != NULL);
1962  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1963 
1964  /* call inclusion method of constraint handler */
1966 
1967  *valid = TRUE;
1968 
1969  return SCIP_OKAY;
1970 }
1971 
1972 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
1973 static
1974 SCIP_DECL_CONSFREE(consFreeBounddisjunction)
1975 { /*lint --e{715}*/
1976  SCIP_CONSHDLRDATA* conshdlrdata;
1977 
1978  assert(conshdlr != NULL);
1979  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1980  assert(scip != NULL);
1981 
1982  /* free constraint handler data */
1983  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1984  assert(conshdlrdata != NULL);
1985 
1986  conshdlrdataFree(scip, &conshdlrdata);
1987 
1988  SCIPconshdlrSetData(conshdlr, NULL);
1989 
1990  return SCIP_OKAY;
1991 }
1992 
1993 
1994 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
1995 static
1996 SCIP_DECL_CONSEXITPRE(consExitpreBounddisjunction)
1997 { /*lint --e{715}*/
1998  SCIP_CONSHDLRDATA* conshdlrdata;
1999  SCIP_CONS* cons;
2000  SCIP_Bool redundant;
2001  int c;
2002 
2003  assert(conshdlr != NULL);
2004  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2005  assert(scip != NULL);
2006 
2007  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2008  assert(conshdlrdata != NULL);
2009 
2010  /* fast processing of constraints, apply global bounds and remove fixed variables */
2011  for( c = 0; c < nconss; ++c )
2012  {
2013  cons = conss[c];
2014  assert(cons != NULL);
2015 
2016  SCIPdebugMsg(scip, "exit-presolving bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2017 
2018  if( SCIPconsIsDeleted(cons) )
2019  continue;
2020 
2021  /* remove all literals that are violated in global bounds, check redundancy due to global bounds */
2022  SCIP_CALL( applyGlobalBounds(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2023 
2024  if( !redundant )
2025  {
2026  /* replace variables by their representative active (or multi-aggregated) variables */
2027  SCIP_CALL( removeFixedVariables(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2028  }
2029 
2030  if( redundant && SCIPconsIsAdded(cons) )
2031  {
2032  SCIPdebugMsg(scip, "bound disjunction constraint <%s> is redundant\n", SCIPconsGetName(cons));
2033  SCIP_CALL( SCIPdelCons(scip, cons) );
2034  }
2035  }
2036 
2037  return SCIP_OKAY;
2038 }
2039 
2040 /** solving process initialization method of constraint handler */
2041 static
2042 SCIP_DECL_CONSINITSOL(consInitsolBounddisjunction)
2043 { /*lint --e{715}*/
2044  /* add nlrow representation to NLP, if NLP had been constructed and disjunction is simple enough */
2045  if( SCIPisNLPConstructed(scip) )
2046  {
2047  SCIP_CONSDATA* consdata;
2048  SCIP_NLROW* nlrow;
2049  SCIP_EXPR* expr;
2050  SCIP_EXPR* exprvar;
2051  SCIP_Real lincoef;
2052  SCIP_Real a, b;
2053  int c;
2054 
2055  for( c = 0; c < nconss; ++c )
2056  {
2057  /* skip deactivated or redundant constraints */
2058  if( !SCIPconsIsActive(conss[c]) || !SCIPconsIsChecked(conss[c]) )
2059  return SCIP_OKAY;
2060 
2061  assert(!SCIPconsIsLocal(conss[c])); /* we are at the root node (or short before) */
2062 
2063  consdata = SCIPconsGetData(conss[c]);
2064  assert(consdata != NULL);
2065 
2066  /* look for a bounddisjunction of the form
2067  * x <= a or x >= b with a < b
2068  * only one of the inequalities can be strictly satisfied, so we can reformulate as
2069  * (x-a)*(b-x) <= 0
2070  * this should be sufficient to get bounddisjunction constraints that represent semi-continuous variables into the NLP
2071  */
2072 
2073  if( consdata->nvars != 2 )
2074  continue;
2075 
2076  if( consdata->vars[0] != consdata->vars[1] )
2077  continue;
2078 
2079  if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_UPPER && consdata->boundtypes[1] == SCIP_BOUNDTYPE_LOWER )
2080  {
2081  a = consdata->bounds[0];
2082  b = consdata->bounds[1];
2083  }
2084  else if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_LOWER && consdata->boundtypes[1] == SCIP_BOUNDTYPE_UPPER )
2085  {
2086  a = consdata->bounds[1];
2087  b = consdata->bounds[0];
2088  }
2089  else
2090  {
2091  continue;
2092  }
2093 
2094  if( a >= b )
2095  continue;
2096 
2097  SCIP_CALL( SCIPcreateExprVar(scip, &exprvar, consdata->vars[0], NULL, NULL) );
2098  SCIP_CALL( SCIPcreateExprPow(scip, &expr, exprvar, 2.0, NULL, NULL) );
2099 
2100  /* add xb-xx-ab+ax <= 0 as -ab <= -(a+b)x + x^2 */
2101  lincoef = -a - b;
2102  SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[c]),
2103  0.0, 1, consdata->vars, &lincoef, expr, -a*b, SCIPinfinity(scip), SCIP_EXPRCURV_CONVEX) );
2104 
2105  SCIP_CALL( SCIPreleaseExpr(scip, &expr) );
2106  SCIP_CALL( SCIPreleaseExpr(scip, &exprvar) );
2107 
2108  SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
2109  SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
2110  }
2111  }
2112 
2113  return SCIP_OKAY;
2114 }
2115 
2116 /** frees specific constraint data */
2117 static
2118 SCIP_DECL_CONSDELETE(consDeleteBounddisjunction)
2119 { /*lint --e{715}*/
2120  assert(conshdlr != NULL);
2121  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2122  assert(consdata != NULL);
2123  assert(*consdata != NULL);
2124 
2125  /* free LP row and bound disjunction constraint */
2126  consdataFree(scip, consdata);
2127 
2128  return SCIP_OKAY;
2129 }
2130 
2131 
2132 /** transforms constraint data into data belonging to the transformed problem */
2133 static
2134 SCIP_DECL_CONSTRANS(consTransBounddisjunction)
2135 { /*lint --e{715}*/
2136  SCIP_CONSDATA* sourcedata;
2137  SCIP_CONSDATA* targetdata;
2138 
2139  /*debugMsg(scip, "Trans method of bound disjunction constraints\n");*/
2140 
2141  assert(conshdlr != NULL);
2142  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2143  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
2144  assert(sourcecons != NULL);
2145  assert(targetcons != NULL);
2146 
2147  sourcedata = SCIPconsGetData(sourcecons);
2148  assert(sourcedata != NULL);
2149 
2150  /* create constraint data for target constraint */
2151  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars,
2152  sourcedata->boundtypes, sourcedata->bounds) );
2153 
2154  /* create target constraint */
2155  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
2156  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
2157  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
2158  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
2159  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
2160 
2161  return SCIP_OKAY;
2162 }
2163 
2164 
2165 /** constraint enforcing method of constraint handler for LP solutions */
2166 static
2167 SCIP_DECL_CONSENFOLP(consEnfolpBounddisjunction)
2168 { /*lint --e{715}*/
2169  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, NULL, result) );
2170 
2171  return SCIP_OKAY;
2172 }
2173 
2174 
2175 /** constraint enforcing method of constraint handler for relaxation solutions */
2176 static
2177 SCIP_DECL_CONSENFORELAX(consEnforelaxBounddisjunction)
2178 { /*lint --e{715}*/
2179  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, sol, result) );
2180 
2181  return SCIP_OKAY;
2182 }
2183 
2184 
2185 /** constraint enforcing method of constraint handler for pseudo solutions */
2186 static
2187 SCIP_DECL_CONSENFOPS(consEnfopsBounddisjunction)
2188 { /*lint --e{715}*/
2189  SCIP_CONSHDLRDATA* conshdlrdata;
2190  SCIP_Bool cutoff;
2191  SCIP_Bool infeasible;
2192  SCIP_Bool reduceddom;
2193  SCIP_Bool registeredbrcand;
2194  int c;
2195  SCIP_CONS* narybranchcons; /* constraint that is a candidate for an n-ary branch */
2196 
2197  assert(conshdlr != NULL);
2198  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2199  assert(nconss == 0 || conss != NULL);
2200  assert(result != NULL);
2201 
2202  SCIPdebugMsg(scip, "pseudo enforcing %d bound disjunction constraints\n", nconss);
2203 
2204  *result = SCIP_FEASIBLE;
2205 
2206  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2207  assert(conshdlrdata != NULL);
2208 
2209  cutoff = FALSE;
2210  infeasible = FALSE;
2211  reduceddom = FALSE;
2212  registeredbrcand = FALSE;
2213  narybranchcons = NULL;
2214 
2215  /* check all bound disjunction constraints for feasibility */
2216  for( c = 0; c < nconss && !cutoff && !reduceddom; ++c )
2217  {
2218  SCIP_CALL( enforceCurrentSol(scip, conss[c], NULL, conshdlrdata->eventhdlr, &cutoff, &infeasible, &reduceddom,
2219  &registeredbrcand) );
2220  if( infeasible && !registeredbrcand )
2221  {
2222  /* if cons. c has less literals than the previous candidate for an n-ary branch, then keep cons. c as candidate for n-ary branch */
2223  if( !narybranchcons || SCIPconsGetData(conss[c])->nvars < SCIPconsGetData(narybranchcons)->nvars )
2224  narybranchcons = conss[c];
2225  }
2226  }
2227 
2228  if( cutoff )
2229  *result = SCIP_CUTOFF;
2230  else if( reduceddom )
2231  *result = SCIP_REDUCEDDOM;
2232  else if( infeasible )
2233  {
2234  if( registeredbrcand )
2235  {
2236  *result = SCIP_INFEASIBLE;
2237  }
2238  else
2239  {
2240  SCIP_CALL( createNAryBranch(scip, narybranchcons, NULL) );
2241  *result = SCIP_BRANCHED;
2242  }
2243  }
2244 
2245  return SCIP_OKAY;
2246 }
2247 
2248 
2249 /** feasibility check method of constraint handler for integral solutions */
2250 static
2251 SCIP_DECL_CONSCHECK(consCheckBounddisjunction)
2252 { /*lint --e{715}*/
2253  SCIP_CONS* cons;
2254  SCIP_CONSDATA* consdata;
2255  int c;
2256 
2257  assert(conshdlr != NULL);
2258  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2259  assert(nconss == 0 || conss != NULL);
2260  assert(result != NULL);
2261 
2262  *result = SCIP_FEASIBLE;
2263 
2264  /* check all bound disjunction constraints for feasibility */
2265  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
2266  {
2267  cons = conss[c];
2268  consdata = SCIPconsGetData(cons);
2269  assert(consdata != NULL);
2270 
2271  if( isConsViolated(scip, cons, sol) )
2272  {
2273  if( printreason )
2274  {
2275  int v;
2276 
2277  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
2278  SCIPinfoMessage(scip, NULL, ";\nviolation: ");
2279  for( v = 0; v < consdata->nvars; ++v )
2280  {
2281  assert(consdata->vars[v] != NULL);
2282  if( v > 0 )
2283  SCIPinfoMessage(scip, NULL, ", ");
2284  SCIPinfoMessage(scip, NULL, "<%s> = %.15g",
2285  SCIPvarGetName(consdata->vars[v]), SCIPgetSolVal(scip, sol, consdata->vars[v]));
2286  }
2287  SCIPinfoMessage(scip, NULL, ")\n");
2288  }
2289 
2290  /* constraint is violated */
2291  *result = SCIP_INFEASIBLE;
2292  }
2293  }
2294 
2295  return SCIP_OKAY;
2296 }
2297 
2298 
2299 /** domain propagation method of constraint handler */
2300 static
2301 SCIP_DECL_CONSPROP(consPropBounddisjunction)
2302 { /*lint --e{715}*/
2303  SCIP_CONSHDLRDATA* conshdlrdata;
2304  SCIP_Bool cutoff;
2305  SCIP_Bool infeasible;
2306  SCIP_Bool reduceddom;
2307  SCIP_Bool mustcheck;
2308  SCIP_Bool consreduceddom;
2309  int c;
2310 
2311  assert(conshdlr != NULL);
2312  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2313  assert(nconss == 0 || conss != NULL);
2314  assert(result != NULL);
2315 
2316  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2317  assert(conshdlrdata != NULL);
2318 
2319  cutoff = FALSE;
2320  infeasible = FALSE;
2321  reduceddom = FALSE;
2322 
2323  /* propagate all useful bound disjunction constraints */
2324  for( c = 0; c < nusefulconss && !cutoff; ++c )
2325  {
2326  SCIP_CALL( processWatchedVars(scip, conss[c], conshdlrdata->eventhdlr,
2327  &cutoff, &infeasible, &consreduceddom, &mustcheck) );
2328  reduceddom = reduceddom || consreduceddom;
2329  }
2330 
2331  /* return the correct result */
2332  if( cutoff )
2333  *result = SCIP_CUTOFF;
2334  else if( reduceddom )
2335  *result = SCIP_REDUCEDDOM;
2336  else
2337  *result = SCIP_DIDNOTFIND;
2338 
2339  return SCIP_OKAY; /*lint !e438*/
2340 }
2341 
2342 
2343 /** presolving method of constraint handler */
2344 static
2345 SCIP_DECL_CONSPRESOL(consPresolBounddisjunction)
2346 { /*lint --e{715}*/
2347  SCIP_CONSHDLRDATA* conshdlrdata;
2348  SCIP_CONS* cons;
2349  SCIP_CONSDATA* consdata;
2350  SCIP_Bool infeasible;
2351  SCIP_Bool redundant;
2352  SCIP_Bool tightened;
2353  int c;
2354 
2355  assert(conshdlr != NULL);
2356  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2357  assert(scip != NULL);
2358  assert(result != NULL);
2359 
2360  *result = SCIP_DIDNOTFIND;
2361 
2362  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2363  assert(conshdlrdata != NULL);
2364 
2365  /* process constraints */
2366  for( c = 0; c < nconss && *result != SCIP_CUTOFF && !SCIPisStopped(scip); ++c )
2367  {
2368  cons = conss[c];
2369  assert(cons != NULL);
2370  consdata = SCIPconsGetData(cons);
2371  assert(consdata != NULL);
2372 
2373  SCIPdebugMsg(scip, "presolving bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2374 
2375  /* force presolving the constraint in the initial round */
2376  if( nrounds == 0 )
2377  {
2378  SCIP_CALL( SCIPenableConsPropagation(scip, cons) );
2379  }
2380 
2381  /* remove all literals that are violated in global bounds, check redundancy due to global bounds */
2382  SCIP_CALL( applyGlobalBounds(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2383 
2384  if( !redundant )
2385  {
2386  /* replace variables by their representative active (or multi-aggregated) variables */
2387  SCIP_CALL( removeFixedVariables(scip, cons, conshdlrdata->eventhdlr, &redundant) );
2388  }
2389 
2390  /**@todo find pairs of negated variables in constraint: constraint is redundant */
2391  /**@todo find sets of equal variables in constraint: multiple entries of variable can be replaced by single entry */
2392 
2393  if( redundant )
2394  {
2395  SCIPdebugMsg(scip, "bound disjunction constraint <%s> is redundant\n", SCIPconsGetName(cons));
2396  SCIP_CALL( SCIPdelCons(scip, cons) );
2397  (*ndelconss)++;
2398  *result = SCIP_SUCCESS;
2399  continue;
2400  }
2401  else if( !SCIPconsIsModifiable(cons) )
2402  {
2403  /* if unmodifiable constraint has no variables, it is infeasible,
2404  * if unmodifiable constraint has only one variable, the literal can be satisfied and the constraint deleted
2405  */
2406  if( consdata->nvars == 0 )
2407  {
2408  SCIPdebugMsg(scip, "bound disjunction constraint <%s> is infeasible\n", SCIPconsGetName(cons));
2409  *result = SCIP_CUTOFF;
2410  return SCIP_OKAY;
2411  }
2412  else if( consdata->nvars == 1 )
2413  {
2414  SCIPdebugMsg(scip, "bound disjunction constraint <%s> has only one undecided literal\n",
2415  SCIPconsGetName(cons));
2416 
2417  assert(consdata->vars != NULL);
2418  assert(!isLiteralSatisfied(scip, consdata, 0));
2419  assert(!isLiteralViolated(scip, consdata, 0));
2420 
2421  if( SCIPvarIsActive(consdata->vars[0]) )
2422  {
2423  if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_LOWER )
2424  {
2425  SCIP_CALL( SCIPtightenVarLb(scip, consdata->vars[0], consdata->bounds[0], TRUE, &infeasible, &tightened) );
2426  }
2427  else
2428  {
2429  SCIP_CALL( SCIPtightenVarUb(scip, consdata->vars[0], consdata->bounds[0], TRUE, &infeasible, &tightened) );
2430  }
2431  if( infeasible )
2432  {
2433  SCIPdebugMsg(scip, " -> infeasible fixing\n");
2434  *result = SCIP_CUTOFF;
2435  return SCIP_OKAY;
2436  }
2437  assert(tightened);
2438  (*nchgbds)++;
2439  }
2440  else
2441  {
2442  /* upgrade to a linear constraint, if vars[0] is multi-aggregated */
2443  SCIP_CONS* lincons;
2444  SCIP_Real one;
2445 
2446  assert(SCIPvarGetStatus(consdata->vars[0]) == SCIP_VARSTATUS_MULTAGGR);
2447 
2448  one = 1.0;
2449  if( consdata->boundtypes[0] == SCIP_BOUNDTYPE_LOWER )
2450  {
2451  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons),
2452  1, &consdata->vars[0], &one, consdata->bounds[0], SCIPinfinity(scip),
2456  SCIPconsIsStickingAtNode(cons)) );
2457  }
2458  else
2459  {
2460  SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, SCIPconsGetName(cons),
2461  1, &consdata->vars[0], &one, -SCIPinfinity(scip), consdata->bounds[0],
2465  SCIPconsIsStickingAtNode(cons)) );
2466  }
2467  SCIP_CALL( SCIPaddCons(scip, lincons) );
2468  SCIP_CALL( SCIPreleaseCons(scip, &lincons) );
2469  (*nupgdconss)++;
2470  }
2471 
2472  SCIP_CALL( SCIPdelCons(scip, cons) );
2473  (*ndelconss)++;
2474  *result = SCIP_SUCCESS;
2475  continue;
2476  }
2477  else
2478  {
2479  /* try to upgrade the bounddisjunction constraint */
2480  SCIP_CALL( upgradeCons(scip, cons, ndelconss, naddconss) );
2481  }
2482  }
2483  }
2484 
2485  /**@todo preprocess pairs of bound disjunction constraints */
2486 
2487  return SCIP_OKAY;
2488 }
2489 
2490 
2491 /** propagation conflict resolving method of constraint handler */
2492 static
2493 SCIP_DECL_CONSRESPROP(consRespropBounddisjunction)
2494 { /*lint --e{715}*/
2495  SCIP_CONSDATA* consdata;
2496  SCIP_VAR** vars;
2497  SCIP_BOUNDTYPE* boundtypes;
2498 #ifndef NDEBUG
2499  SCIP_Real* bounds;
2500 #endif
2501  int v;
2502 
2503  assert(conshdlr != NULL);
2504  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2505  assert(cons != NULL);
2506  assert(infervar != NULL);
2507  assert(result != NULL);
2508 
2509  consdata = SCIPconsGetData(cons);
2510  assert(consdata != NULL);
2511  assert(consdata->vars != NULL);
2512  assert(consdata->nvars > 0);
2513  assert(0 <= inferinfo && inferinfo < consdata->nvars);
2514  assert(consdata->vars[inferinfo] == infervar);
2515 
2516  vars = consdata->vars;
2517  boundtypes = consdata->boundtypes;
2518 #ifndef NDEBUG
2519  bounds = consdata->bounds;
2520  assert(bounds != NULL);
2521 #endif
2522  assert(boundtypes != NULL);
2523 
2524  SCIPdebugMsg(scip, "conflict resolving method of bound disjunction constraint handler\n");
2525 
2526  /* the only deductions are bounds tightened to a literal's bound on bound disjunction constraints where all other
2527  * literals are violated
2528  */
2529  assert((boundtypes[inferinfo] == SCIP_BOUNDTYPE_LOWER
2530  && SCIPisFeasGE(scip, SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE), bounds[inferinfo]))
2531  || (boundtypes[inferinfo] == SCIP_BOUNDTYPE_UPPER
2532  && SCIPisFeasLE(scip, SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE), bounds[inferinfo])));
2533 
2534  for( v = 0; v < consdata->nvars; ++v )
2535  {
2536  if( v != inferinfo )
2537  {
2538  assert(consdata->vars[v] != infervar || consdata->boundtypes[v] != consdata->boundtypes[inferinfo]);
2539 
2540  /* the reason literal must have been violated
2541  * we do not check for multi-aggregated variables, since SCIPvarGetXbAtIndex is not implemented for them */
2542  /* Use a weaker comparison to SCIPvarGetXbAtIndex here (i.e., SCIPisXT instead of SCIPisFeasXT),
2543  * because SCIPvarGetXbAtIndex might differ from the local bound at time bdchgidx by epsilon. */
2544  assert(SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_MULTAGGR
2545  || (boundtypes[v] == SCIP_BOUNDTYPE_LOWER
2546  && SCIPisLT(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, TRUE), bounds[v]))
2547  || (boundtypes[v] == SCIP_BOUNDTYPE_UPPER
2548  && SCIPisGT(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, TRUE), bounds[v])));
2549  SCIP_CALL( SCIPaddConflictBd(scip, vars[v], SCIPboundtypeOpposite(boundtypes[v]), bdchgidx) );
2550  }
2551  }
2552 
2553  *result = SCIP_SUCCESS;
2554 
2555  return SCIP_OKAY;
2556 }
2557 
2558 
2559 /** variable rounding lock method of constraint handler */
2560 static
2561 SCIP_DECL_CONSLOCK(consLockBounddisjunction)
2562 { /*lint --e{715}*/
2563  SCIP_CONSDATA* consdata;
2564  int i;
2565 
2566  consdata = SCIPconsGetData(cons);
2567  assert(consdata != NULL);
2568 
2569  /* lock every single coefficient */
2570  for( i = 0; i < consdata->nvars; ++i )
2571  {
2572  if( consdata->boundtypes[i] == SCIP_BOUNDTYPE_LOWER )
2573  {
2574  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
2575  }
2576  else
2577  {
2578  SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
2579  }
2580  }
2581 
2582  return SCIP_OKAY;
2583 }
2584 
2585 
2586 /** constraint activation notification method of constraint handler */
2587 static
2588 SCIP_DECL_CONSACTIVE(consActiveBounddisjunction)
2589 { /*lint --e{715}*/
2590  SCIP_CONSHDLRDATA* conshdlrdata;
2591  SCIP_CONSDATA* consdata;
2592 
2593  assert(conshdlr != NULL);
2594  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2595  assert(cons != NULL);
2596  assert(SCIPconsIsTransformed(cons));
2597 
2598  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2599  assert(conshdlrdata != NULL);
2600  consdata = SCIPconsGetData(cons);
2601  assert(consdata != NULL);
2602  assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
2603 
2604  SCIPdebugMsg(scip, "activating information for bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2605  SCIPdebug(consdataPrint(scip, consdata, NULL, TRUE));
2606 
2607  /* catch events on watched variables */
2608  if( consdata->watchedvar1 != -1 )
2609  {
2610  SCIP_CALL( catchEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar1,
2611  &consdata->filterpos1) );
2612  }
2613  if( consdata->watchedvar2 != -1 )
2614  {
2615  SCIP_CALL( catchEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar2,
2616  &consdata->filterpos2) );
2617  }
2618 
2619  return SCIP_OKAY;
2620 }
2621 
2622 
2623 /** constraint deactivation notification method of constraint handler */
2624 static
2625 SCIP_DECL_CONSDEACTIVE(consDeactiveBounddisjunction)
2626 { /*lint --e{715}*/
2627  SCIP_CONSHDLRDATA* conshdlrdata;
2628  SCIP_CONSDATA* consdata;
2629 
2630  assert(conshdlr != NULL);
2631  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
2632  assert(cons != NULL);
2633  assert(SCIPconsIsTransformed(cons));
2634 
2635  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2636  assert(conshdlrdata != NULL);
2637  consdata = SCIPconsGetData(cons);
2638  assert(consdata != NULL);
2639  assert(consdata->watchedvar1 == -1 || consdata->watchedvar1 != consdata->watchedvar2);
2640 
2641  SCIPdebugMsg(scip, "deactivating information for bound disjunction constraint <%s>\n", SCIPconsGetName(cons));
2642  SCIPdebug(consdataPrint(scip, consdata, NULL, TRUE));
2643 
2644  /* drop events on watched variables */
2645  if( consdata->watchedvar1 != -1 )
2646  {
2647  assert(consdata->filterpos1 != -1);
2648  SCIP_CALL( dropEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
2649  consdata->watchedvar1 = -1;
2650  }
2651  if( consdata->watchedvar2 != -1 )
2652  {
2653  assert(consdata->filterpos2 != -1);
2654  SCIP_CALL( dropEvents(scip, cons, consdata, conshdlrdata->eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
2655  consdata->watchedvar2 = -1;
2656  }
2657 
2658  return SCIP_OKAY;
2659 }
2660 
2661 
2662 /** constraint display method of constraint handler */
2663 static
2664 SCIP_DECL_CONSPRINT(consPrintBounddisjunction)
2665 { /*lint --e{715}*/
2666  assert( scip != NULL );
2667  assert( conshdlr != NULL );
2668  assert( cons != NULL );
2669 
2670  consdataPrint(scip, SCIPconsGetData(cons), file, FALSE);
2671 
2672  return SCIP_OKAY;
2673 }
2674 
2675 /** constraint copying method of constraint handler */
2676 static
2677 SCIP_DECL_CONSCOPY(consCopyBounddisjunction)
2678 { /*lint --e{715}*/
2679  SCIP_VAR** sourcevars;
2680  SCIP_VAR** targetvars;
2681  SCIP_BOUNDTYPE* boundtypes;
2682  SCIP_Real* bounds;
2683  int nvars;
2684  int v;
2685 
2686  assert(valid != NULL);
2687 
2688  *valid = TRUE;
2689 
2690  /* get source data */
2691  sourcevars = SCIPgetVarsBounddisjunction(sourcescip, sourcecons);
2692  nvars = SCIPgetNVarsBounddisjunction(sourcescip, sourcecons);
2693  boundtypes = SCIPgetBoundtypesBounddisjunction(sourcescip, sourcecons);
2694  bounds = SCIPgetBoundsBounddisjunction(sourcescip, sourcecons);
2695 
2696  SCIP_CALL( SCIPallocBufferArray(scip, &targetvars, nvars) );
2697 
2698  /* map source variables to active variables of the target SCIP */
2699  for( v = 0; v < nvars && *valid; ++v )
2700  {
2701  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &targetvars[v], varmap, consmap, global, valid) );
2702  assert(!(*valid) || targetvars[v] != NULL);
2703  }
2704 
2705  /* only create the target constraint, if all variables could be copied */
2706  if( *valid )
2707  {
2708  SCIP_CALL( SCIPcreateConsBounddisjunction(scip, cons, name ? name : SCIPconsGetName(sourcecons), nvars, targetvars, boundtypes,
2709  bounds, initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2710  }
2711 
2712  SCIPfreeBufferArray(scip, &targetvars);
2713 
2714  return SCIP_OKAY;
2715 }
2716 
2717 /** constraint parsing method of constraint handler */
2718 static
2719 SCIP_DECL_CONSPARSE(consParseBounddisjunction)
2720 { /*lint --e{715}*/
2721  SCIP_BOUNDTYPE* boundtypes;
2722  SCIP_Real* bounds;
2723  SCIP_VAR** vars;
2724  char* endptr;
2725  int varssize;
2726  int nvars;
2727 
2728  assert( success != NULL );
2729  *success = TRUE;
2730 
2731  SCIPdebugMsg(scip, "parse <%s> as bounddisjunction constraint\n", str);
2732 
2733  /* skip white space */
2734  while( *str != '\0' && isspace((unsigned char)*str) )
2735  ++str;
2736 
2737  /* check for string "bounddisjunction" */
2738  if( strncmp(str, "bounddisjunction(", 16) != 0 )
2739  {
2740  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "error during parsing: expected \"bounddisjunction(\" in <%s>.\n", str);
2741  *success = FALSE;
2742  return SCIP_OKAY;
2743  }
2744 
2745  /* skip "bounddisjunction(" */
2746  str += 17;
2747 
2748  varssize = 100;
2749  nvars = 0;
2750 
2751  /* allocate buffer array for variables */
2752  SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
2753  SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, varssize) );
2754  SCIP_CALL( SCIPallocBufferArray(scip, &bounds, varssize) );
2755 
2756  /* parse string until ")" */
2757  while( *str != '\0' && *str != ')' )
2758  {
2759  SCIP_VAR* var;
2760 
2761  /* parse variable name */
2762  SCIP_CALL( SCIPparseVarName(scip, str, &var, &endptr) );
2763  str = endptr;
2764 
2765  if( var == NULL )
2766  {
2767  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Error while parsing variable.\n");
2768  *success = FALSE;
2769  goto TERMINATE;
2770  }
2771 
2772  /* skip white space */
2773  while( *str != '\0' && isspace((unsigned char)*str) && *str != '>' && *str != '<' )
2774  ++str;
2775 
2776  /* parse bound type */
2777  switch( *str )
2778  {
2779  case '<':
2780  boundtypes[nvars] = SCIP_BOUNDTYPE_UPPER;
2781  break;
2782  case '>':
2783  boundtypes[nvars] = SCIP_BOUNDTYPE_LOWER;
2784  break;
2785  default:
2786  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "variable with name <%s> does not exist\n", SCIPvarGetName(var));
2787  *success = FALSE;
2788  goto TERMINATE;
2789  }
2790 
2791  ++str;
2792  if( *str != '=' )
2793  {
2794  SCIPdebugMsg(scip, "expected '=': %s\n", str);
2795  *success = FALSE;
2796  goto TERMINATE;
2797  }
2798 
2799  /* skip '=' */
2800  ++str;
2801 
2802  /* skip white space */
2803  while( *str != '\0' && isspace((unsigned char)*str) )
2804  ++str;
2805 
2806  /* parse bound value */
2807  if( !SCIPstrToRealValue(str, &bounds[nvars], &endptr) )
2808  {
2809  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error during parsing of the weight: %s\n", str);
2810  *success = FALSE;
2811  goto TERMINATE;
2812  }
2813 
2814  /* skip white space */
2815  str = endptr;
2816  while( (*str != '\0' && isspace((unsigned char)*str)) || *str == ',' )
2817  ++str;
2818 
2819  /* set variable */
2820  vars[nvars++] = var;
2821 
2822  /* check if the size of the variable array was big enough */
2823  if( nvars > varssize )
2824  {
2825  /* reallocate memory */
2826  varssize *= 2;
2827  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
2828  SCIP_CALL( SCIPreallocBufferArray(scip, &boundtypes, varssize) );
2829  SCIP_CALL( SCIPreallocBufferArray(scip, &bounds, varssize) );
2830  }
2831  }
2832  /* ignore if the string ended without ")" */
2833 
2834  /* add bounddisjunction */
2835  if( *success && nvars > 0 )
2836  {
2837  SCIP_CALL( SCIPcreateConsBounddisjunction(scip, cons, name, nvars, vars, boundtypes, bounds,
2838  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2839  }
2840 
2841  TERMINATE:
2842  /* free variable buffer */
2843  SCIPfreeBufferArray(scip, &bounds);
2844  SCIPfreeBufferArray(scip, &boundtypes);
2845  SCIPfreeBufferArray(scip, &vars);
2846 
2847  return SCIP_OKAY;
2848 }
2849 
2850 /** constraint method of constraint handler which returns the variables (if possible) */
2851 static
2852 SCIP_DECL_CONSGETVARS(consGetVarsBounddisjunction)
2853 { /*lint --e{715}*/
2854  SCIP_CONSDATA* consdata;
2855 
2856  assert(cons != NULL);
2857 
2858  consdata = SCIPconsGetData(cons);
2859  assert(consdata != NULL);
2860 
2861  if( varssize < consdata->nvars )
2862  (*success) = FALSE;
2863  else
2864  {
2865  assert(vars != NULL);
2866 
2867  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
2868  (*success) = TRUE;
2869  }
2870 
2871  return SCIP_OKAY;
2872 }
2873 
2874 /** constraint method of constraint handler which returns the number of variables (if possible) */
2875 static
2876 SCIP_DECL_CONSGETNVARS(consGetNVarsBounddisjunction)
2877 { /*lint --e{715}*/
2878  SCIP_CONSDATA* consdata;
2879 
2880  assert(cons != NULL);
2881 
2882  consdata = SCIPconsGetData(cons);
2883  assert(consdata != NULL);
2884 
2885  (*nvars) = consdata->nvars;
2886  (*success) = TRUE;
2887 
2888  return SCIP_OKAY;
2889 }
2890 
2891 /**@} */
2892 
2893 /**@name Callback methods of event handler
2894  *
2895  * @{
2896  */
2897 
2898 static
2899 SCIP_DECL_EVENTEXEC(eventExecBounddisjunction)
2900 { /*lint --e{715}*/
2901  assert(eventhdlr != NULL);
2902  assert(eventdata != NULL);
2903  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
2904  assert(event != NULL);
2905 
2906  /*SCIPdebugMsg(scip, "exec method of event handler for bound disjunction constraints\n");*/
2907 
2908  assert(SCIPconsGetData((SCIP_CONS*)eventdata) != NULL);
2909  assert(SCIPconsIsActive((SCIP_CONS*)eventdata) || SCIPconsIsUpdatedeactivate((SCIP_CONS*)eventdata));
2910 
2911  if( (SCIPeventGetType(event) & SCIP_EVENTTYPE_BOUNDRELAXED) != 0 )
2912  {
2913  SCIP_CALL( SCIPenableCons(scip, (SCIP_CONS*)eventdata) );
2914  }
2915  else
2916  assert((SCIPeventGetType(event) & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0);
2917 
2918  SCIP_CALL( SCIPenableConsPropagation(scip, (SCIP_CONS*)eventdata) );
2919 
2920  return SCIP_OKAY;
2921 }
2922 
2923 /**@} */
2924 
2925 /**@name Callback methods of conflict handler
2926  *
2927  * @{
2928  */
2929 
2930 /** conflict handler data struct */
2931 struct SCIP_ConflicthdlrData
2932 {
2933  SCIP_Real continuousfrac; /**< maximal percantage of continuous variables within a conflict */
2934 };
2935 
2936 /** conflict processing method of conflict handler (called when conflict was found) */
2937 static
2938 SCIP_DECL_CONFLICTEXEC(conflictExecBounddisjunction)
2939 { /*lint --e{715}*/
2940  SCIP_VAR** vars;
2941  SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
2942  SCIP_BOUNDTYPE* boundtypes;
2943  SCIP_Real* bounds;
2944  SCIP_CONS* cons;
2945  char consname[SCIP_MAXSTRLEN];
2946  int nliterals;
2947  int ncontinuous;
2948  int i;
2949 
2950  assert(conflicthdlr != NULL);
2951  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
2952  assert(bdchginfos != NULL || nbdchginfos == 0);
2953  assert(result != NULL);
2954 
2955  /* don't process already resolved conflicts */
2956  if( resolved )
2957  {
2958  *result = SCIP_DIDNOTRUN;
2959  return SCIP_OKAY;
2960  }
2961 
2962  conflicthdlrdata = SCIPconflicthdlrGetData(conflicthdlr);
2963  assert(conflicthdlrdata != NULL);
2964 
2965  *result = SCIP_DIDNOTFIND;
2966  ncontinuous = 0;
2967 
2968  /* create array of variables, boundtypes, and bound values in conflict constraint */
2969  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
2970  SCIP_CALL( SCIPallocBufferArray(scip, &boundtypes, nbdchginfos) );
2971  SCIP_CALL( SCIPallocBufferArray(scip, &bounds, nbdchginfos) );
2972 
2973  nliterals = 0;
2974 
2975  for( i = 0; i < nbdchginfos; ++i )
2976  {
2977  SCIP_VAR* var;
2978  SCIP_Real bound;
2979  SCIP_BOUNDTYPE boundtype;
2980  int j;
2981 
2982  assert(bdchginfos != NULL);
2983 
2984  var = SCIPbdchginfoGetVar(bdchginfos[i]);
2985  assert(var != NULL);
2986 
2987  boundtype = SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(bdchginfos[i]));
2988  bound = relaxedbds[i];
2989 
2990  /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
2991  if( SCIPvarIsIntegral(var) )
2992  bound += (boundtype == SCIP_BOUNDTYPE_LOWER ? +1.0 : -1.0);
2993 
2994  /* check whether we have seen the variable before */
2995  for( j = nliterals-1; j >= 0; --j )
2996  {
2997  if( vars[j] != var )
2998  continue;
2999 
3000  /* check whether both literals contribute with the same bound type */
3001  if( boundtypes[j] == boundtype )
3002  {
3003  /* check whether the lower bound can be relaxed */
3004  if( boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisLT(scip, bound, bounds[j]) )
3005  {
3006  SCIPdebugMsg(scip, "relax lower bound of variable <%s> from %g to %g in bounddisjunction conflict\n",
3007  SCIPvarGetName(var), bounds[j], bound);
3008  bounds[j] = bound;
3009  }
3010  /* check whether the upper bound can be relaxed */
3011  else if( boundtype == SCIP_BOUNDTYPE_UPPER && SCIPisGT(scip, bound, bounds[j]) )
3012  {
3013  SCIPdebugMsg(scip, "relax upper bound of variable <%s> from %g to %g in bounddisjunction conflict\n",
3014  SCIPvarGetName(var), bounds[j], bound);
3015  bounds[j] = bound;
3016  }
3017 
3018  continue;
3019  }
3020  /* check whether the bounds are overlapping */
3021  else if( isOverlapping(scip, var, boundtype, bound, boundtypes[j], bounds[j]) )
3022  {
3023  /* the conflict is redundant -> discard the conflict constraint */
3024  SCIPdebugMsg(scip, "redundant bounddisjunction conflict due to overlapping\n");
3025  goto DISCARDCONFLICT;
3026  }
3027  }
3028 
3029  vars[nliterals] = var;
3030  boundtypes[nliterals] = boundtype;
3031  bounds[nliterals] = bound;
3032 
3033  /* check if the relaxed bound is really a relaxed bound */
3034  assert(SCIPbdchginfoGetBoundtype(bdchginfos[i]) == SCIP_BOUNDTYPE_LOWER || SCIPisGE(scip, relaxedbds[i], SCIPbdchginfoGetNewbound(bdchginfos[i])));
3035  assert(SCIPbdchginfoGetBoundtype(bdchginfos[i]) == SCIP_BOUNDTYPE_UPPER || SCIPisLE(scip, relaxedbds[i], SCIPbdchginfoGetNewbound(bdchginfos[i])));
3036 
3037  /* for continuous variables, we can only use the relaxed version of the bounds negation: !(x <= u) -> x >= u */
3038  if( !SCIPvarIsIntegral(vars[nliterals]) )
3039  {
3040  if( (boundtypes[i] == SCIP_BOUNDTYPE_LOWER && SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), bounds[nliterals]))
3041  || (boundtypes[i] == SCIP_BOUNDTYPE_UPPER && SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), bounds[nliterals])) )
3042  {
3043  /* the literal is satisfied in global bounds (may happen due to weak "negation" of continuous variables)
3044  * -> discard the conflict constraint
3045  */
3046  SCIPdebugMsg(scip, "redundant bounddisjunction conflict due to globally fulfilled literal\n");
3047  goto DISCARDCONFLICT;
3048  }
3049  else
3050  ncontinuous++;
3051  }
3052 
3053  nliterals++;
3054  }
3055 
3056  /* create a constraint out of the conflict set */
3057  if( i == nbdchginfos && ncontinuous < conflicthdlrdata->continuousfrac * nbdchginfos + 0.5 )
3058  {
3059  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%d_%" SCIP_LONGINT_FORMAT, SCIPgetNRuns(scip), SCIPgetNConflictConssApplied(scip));
3060  SCIP_CALL( SCIPcreateConsBounddisjunction(scip, &cons, consname, nliterals, vars, boundtypes, bounds,
3061  FALSE, FALSE, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
3062 
3063  /* add conflict to SCIP */
3064  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
3065  SCIPdebugMsg(scip, "added conflict\n");
3066  *result = SCIP_CONSADDED;
3067  }
3068 
3069  DISCARDCONFLICT:
3070  /* free temporary memory */
3071  SCIPfreeBufferArray(scip, &bounds);
3072  SCIPfreeBufferArray(scip, &boundtypes);
3073  SCIPfreeBufferArray(scip, &vars);
3074 
3075  return SCIP_OKAY;
3076 }
3077 
3078 /** free method of conflict handler */
3079 static
3080 SCIP_DECL_CONFLICTFREE(conflictFreeBounddisjunction)
3082  SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
3083 
3084  assert(conflicthdlr != NULL);
3085 
3086  /* get conflict handler data */
3087  conflicthdlrdata = SCIPconflicthdlrGetData(conflicthdlr);
3088  assert(conflicthdlrdata != NULL);
3089 
3090  /* free conflict handler structure */
3091  SCIPfreeBlockMemory(scip, &conflicthdlrdata);
3092 
3093  return SCIP_OKAY;
3094 }
3095 
3096 /**@} */
3097 
3098 /** creates the handler for bound disjunction constraints and includes it in SCIP */
3100  SCIP* scip /**< SCIP data structure */
3101  )
3102 {
3103  SCIP_CONSHDLRDATA* conshdlrdata;
3104  SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
3105  SCIP_CONFLICTHDLR* conflicthdlr;
3106  SCIP_CONSHDLR* conshdlr;
3107  SCIP_EVENTHDLR* eventhdlr;
3108 
3109  /* create event handler for events on watched variables */
3111  eventExecBounddisjunction, NULL) );
3112 
3113  /* allocate memory for conflict handler data */
3114  SCIP_CALL( SCIPallocBlockMemory(scip, &conflicthdlrdata) );
3115 
3116  /* create conflict handler parameter */
3118  "conflict/" CONSHDLR_NAME "/continuousfrac", "maximal percantage of continuous variables within a conflict",
3119  &conflicthdlrdata->continuousfrac, FALSE, DEFAULT_CONTINUOUSFRAC, 0.0, 1.0, NULL, NULL) );
3120 
3121  /* create conflict handler for bound disjunction constraints */
3123  conflictExecBounddisjunction, conflicthdlrdata) );
3124 
3125  SCIP_CALL( SCIPsetConflicthdlrFree(scip, conflicthdlr, conflictFreeBounddisjunction) );
3126 
3127  /* create constraint handler data */
3128  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
3129 
3130  /* include constraint handler */
3133  consEnfolpBounddisjunction, consEnfopsBounddisjunction, consCheckBounddisjunction, consLockBounddisjunction,
3134  conshdlrdata) );
3135 
3136  assert(conshdlr != NULL);
3137 
3138  /* set non-fundamental callbacks via specific setter functions */
3139  SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveBounddisjunction) );
3140  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyBounddisjunction, consCopyBounddisjunction) );
3141  SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveBounddisjunction) );
3142  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteBounddisjunction) );
3143  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreBounddisjunction) );
3144  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolBounddisjunction) );
3145  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeBounddisjunction) );
3146  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsBounddisjunction) );
3147  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsBounddisjunction) );
3148  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseBounddisjunction) );
3149  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolBounddisjunction, CONSHDLR_MAXPREROUNDS,
3151  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintBounddisjunction) );
3152  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropBounddisjunction, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
3154  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropBounddisjunction) );
3155  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransBounddisjunction) );
3156  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxBounddisjunction) );
3157 
3158  return SCIP_OKAY;
3159 }
3160 
3161 
3162 /** creates and captures a bound disjunction constraint
3163  *
3164  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3165  */
3167  SCIP* scip, /**< SCIP data structure */
3168  SCIP_CONS** cons, /**< pointer to hold the created constraint */
3169  const char* name, /**< name of constraint */
3170  int nvars, /**< number of variables in the constraint */
3171  SCIP_VAR** vars, /**< variables of the literals in the constraint */
3172  SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3173  SCIP_Real* bounds, /**< bounds of the literals */
3174  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3175  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3176  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3177  * Usually set to TRUE. */
3178  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3179  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3180  SCIP_Bool check, /**< should the constraint be checked for feasibility?
3181  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3182  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3183  * Usually set to TRUE. */
3184  SCIP_Bool local, /**< is constraint only valid locally?
3185  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3186  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3187  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3188  * adds coefficients to this constraint. */
3189  SCIP_Bool dynamic, /**< is constraint subject to aging?
3190  * Usually set to FALSE. Set to TRUE for own cuts which
3191  * are separated as constraints. */
3192  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3193  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3194  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3195  * if it may be moved to a more global node?
3196  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3197  )
3198 {
3199  SCIP_CONSHDLR* conshdlr;
3200  SCIP_CONSDATA* consdata;
3201 
3202  assert(scip != NULL);
3203 
3204  /* find the bounddisjunction constraint handler */
3205  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3206  if( conshdlr == NULL )
3207  {
3208  SCIPerrorMessage("bound disjunction constraint handler not found\n");
3209  return SCIP_PLUGINNOTFOUND;
3210  }
3211 
3212 #ifndef NDEBUG
3213  {
3214  int v1;
3215  /* ensure that the given data neither contains overlapping nor redundant literals */
3216  for( v1 = 0; v1 < nvars; v1++ )
3217  {
3218  int v2;
3219  for( v2 = v1+1; v2 < nvars; v2++ )
3220  {
3221  assert(vars[v1] != vars[v2] || (SCIPboundtypeOpposite(boundtypes[v1]) == boundtypes[v2]
3222  && !isOverlapping(scip, vars[v1], boundtypes[v1], bounds[v1], boundtypes[v2], bounds[v2])));
3223  }
3224  }
3225  }
3226 #endif
3227 
3228  /* create the constraint specific data */
3229  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, boundtypes, bounds) );
3230 
3231  /* create constraint */
3232  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
3233  local, modifiable, dynamic, removable, stickingatnode) );
3234 
3235  return SCIP_OKAY;
3236 }
3237 
3238 /** creates and captures a bound disjunction constraint
3239  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
3240  * method SCIPcreateConsBounddisjunction(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
3241  *
3242  * @see SCIPcreateConsBounddisjunction() for information about the basic constraint flag configuration
3243  *
3244  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3245  */
3247  SCIP* scip, /**< SCIP data structure */
3248  SCIP_CONS** cons, /**< pointer to hold the created constraint */
3249  const char* name, /**< name of constraint */
3250  int nvars, /**< number of variables in the constraint */
3251  SCIP_VAR** vars, /**< variables of the literals in the constraint */
3252  SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3253  SCIP_Real* bounds /**< bounds of the literals */
3254  )
3255 {
3256  assert(scip != NULL);
3257 
3258  SCIP_CALL( SCIPcreateConsBounddisjunction(scip, cons, name, nvars, vars, boundtypes, bounds,
3259  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
3260 
3261  return SCIP_OKAY;
3262 }
3263 
3264 /** creates and captures a bound disjunction constraint with possibly redundant literals
3265  *
3266  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3267  */
3269  SCIP* scip, /**< SCIP data structure */
3270  SCIP_CONS** cons, /**< pointer to hold the created constraint */
3271  const char* name, /**< name of constraint */
3272  int nvars, /**< number of variables in the constraint */
3273  SCIP_VAR** vars, /**< variables of the literals in the constraint */
3274  SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3275  SCIP_Real* bounds, /**< bounds of the literals */
3276  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
3277  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
3278  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
3279  * Usually set to TRUE. */
3280  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
3281  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3282  SCIP_Bool check, /**< should the constraint be checked for feasibility?
3283  * TRUE for model constraints, FALSE for additional, redundant constraints. */
3284  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
3285  * Usually set to TRUE. */
3286  SCIP_Bool local, /**< is constraint only valid locally?
3287  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
3288  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
3289  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
3290  * adds coefficients to this constraint. */
3291  SCIP_Bool dynamic, /**< is constraint subject to aging?
3292  * Usually set to FALSE. Set to TRUE for own cuts which
3293  * are separated as constraints. */
3294  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3295  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
3296  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3297  * if it may be moved to a more global node?
3298  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
3299  )
3300 {
3301  SCIP_CONSHDLR* conshdlr;
3302  SCIP_CONSDATA* consdata;
3303 
3304  assert(scip != NULL);
3305 
3306  /* find the bounddisjunction constraint handler */
3307  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
3308  if( conshdlr == NULL )
3309  {
3310  SCIPerrorMessage("bound disjunction constraint handler not found\n");
3311  return SCIP_PLUGINNOTFOUND;
3312  }
3313 
3314  /* create the constraint specific data */
3315  SCIP_CALL( consdataCreateRedundant(scip, &consdata, nvars, vars, boundtypes, bounds) );
3316 
3317  /* create constraint */
3318  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
3319  local, modifiable, dynamic, removable, stickingatnode) );
3320 
3321  return SCIP_OKAY;
3322 }
3323 
3324 /** creates and captures a bound disjunction constraint with possibly redundant literals
3325  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
3326  * method SCIPcreateConsBounddisjunction(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
3327  *
3328  * @see SCIPcreateConsBounddisjunction() for information about the basic constraint flag configuration
3329  *
3330  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3331  */
3333  SCIP* scip, /**< SCIP data structure */
3334  SCIP_CONS** cons, /**< pointer to hold the created constraint */
3335  const char* name, /**< name of constraint */
3336  int nvars, /**< number of variables in the constraint */
3337  SCIP_VAR** vars, /**< variables of the literals in the constraint */
3338  SCIP_BOUNDTYPE* boundtypes, /**< types of bounds of the literals (lower or upper bounds) */
3339  SCIP_Real* bounds /**< bounds of the literals */
3340  )
3341 {
3342  assert(scip != NULL);
3343 
3344  SCIP_CALL( SCIPcreateConsBounddisjunctionRedundant(scip, cons, name, nvars, vars, boundtypes, bounds,
3345  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
3346 
3347  return SCIP_OKAY;
3348 }
3349 
3350 /** gets number of variables in bound disjunction constraint */ /*lint -e{715}*/
3352  SCIP* scip, /**< SCIP data structure */
3353  SCIP_CONS* cons /**< constraint data */
3354  )
3355 {
3356  SCIP_CONSDATA* consdata;
3357 
3358  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3359  {
3360  SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3361  SCIPABORT();
3362  return 0; /*lint !e527*/
3363  }
3364 
3365  consdata = SCIPconsGetData(cons);
3366  assert(consdata != NULL);
3367 
3368  return consdata->nvars;
3369 }
3370 
3371 /** gets array of variables in bound disjunction constraint */ /*lint -e{715}*/
3373  SCIP* scip, /**< SCIP data structure */
3374  SCIP_CONS* cons /**< constraint data */
3375  )
3376 {
3377  SCIP_CONSDATA* consdata;
3378 
3379  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3380  {
3381  SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3382  SCIPABORT();
3383  return NULL; /*lint !e527*/
3384  }
3385 
3386  consdata = SCIPconsGetData(cons);
3387  assert(consdata != NULL);
3388 
3389  return consdata->vars;
3390 }
3391 
3392 /** gets array of bound types in bound disjunction constraint */ /*lint -e{715}*/
3394  SCIP* scip, /**< SCIP data structure */
3395  SCIP_CONS* cons /**< constraint data */
3396  )
3397 {
3398  SCIP_CONSDATA* consdata;
3399 
3400  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3401  {
3402  SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3403  SCIPABORT();
3404  return NULL; /*lint !e527*/
3405  }
3406 
3407  consdata = SCIPconsGetData(cons);
3408  assert(consdata != NULL);
3409 
3410  return consdata->boundtypes;
3411 }
3412 
3413 /** gets array of bounds in bound disjunction constraint */ /*lint -e{715}*/
3415  SCIP* scip, /**< SCIP data structure */
3416  SCIP_CONS* cons /**< constraint data */
3417  )
3418 {
3419  SCIP_CONSDATA* consdata;
3420 
3421  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
3422  {
3423  SCIPerrorMessage("constraint is not a bound disjunction constraint\n");
3424  SCIPABORT();
3425  return NULL; /*lint !e527*/
3426  }
3427 
3428  consdata = SCIPconsGetData(cons);
3429  assert(consdata != NULL);
3430 
3431  return consdata->bounds;
3432 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
static SCIP_DECL_CONSCHECK(consCheckBounddisjunction)
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4205
static SCIP_RETCODE dropEvents(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int filterpos)
SCIP_RETCODE SCIPaddConsAge(SCIP *scip, SCIP_CONS *cons, SCIP_Real deltaage)
Definition: scip_cons.c:1692
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip_mem.h:90
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:563
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, int pos)
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip_nlp.c:101
SCIP_RETCODE SCIPcreateExprPow(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_pow.c:3166
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
SCIP_RETCODE SCIPincludeConshdlrBounddisjunction(SCIP *scip)
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2125
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
public methods for SCIP parameter handling
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip_general.c:356
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8344
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)
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:1989
static SCIP_Bool isOverlapping(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype1, SCIP_Real bound1, SCIP_BOUNDTYPE boundtype2, SCIP_Real bound2)
int SCIPconsGetValidDepth(SCIP_CONS *cons)
Definition: cons.c:8168
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_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18512
static SCIP_DECL_CONSDELETE(consDeleteBounddisjunction)
#define CONSHDLR_PROPFREQ
int SCIPgetNVarsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17910
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:816
#define SCIP_MAXSTRLEN
Definition: def.h:293
public methods for conflict handler plugins and conflict analysis
#define CONSHDLR_NEEDSCONS
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:308
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
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:130
static long bound
SCIP_RETCODE SCIPcreateConsBasicBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
static SCIP_RETCODE applyGlobalBounds(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *redundant)
SCIP_VAR ** SCIPgetVarsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17966
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPdisableConsPropagation(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1918
SCIP_RETCODE SCIPsetConshdlrDeactive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDEACTIVE((*consdeactive)))
Definition: scip_cons.c:678
SCIP_Real * SCIPgetBoundsBounddisjunction(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPchgVarLbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4843
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition: cons.c:8514
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 SCIPdelConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons)
Definition: scip_prob.c:3423
static SCIP_RETCODE consdataCreateRedundant(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
static SCIP_RETCODE disableCons(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip_var.c:524
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17431
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define isFeasGT(scip, var, val1, val2)
static SCIP_DECL_CONSGETVARS(consGetVarsBounddisjunction)
#define FALSE
Definition: def.h:87
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:315
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11063
#define isFeasGE(scip, var, val1, val2)
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
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
#define CONFLICTHDLR_DESC
SCIP_Real SCIPinfinity(SCIP *scip)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10755
#define TRUE
Definition: def.h:86
#define SCIPdebug(x)
Definition: pub_message.h:84
static SCIP_RETCODE catchEvents(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int *filterpos)
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
static void consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
#define CONSHDLR_PROP_TIMING
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8364
#define CONFLICTHDLR_PRIORITY
static SCIP_DECL_CONSENFORELAX(consEnforelaxBounddisjunction)
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8394
public methods for problem variables
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
static SCIP_Bool isConsViolated(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:99
SCIP_RETCODE SCIPenableConsPropagation(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1888
static SCIP_DECL_CONSTRANS(consTransBounddisjunction)
SCIP_RETCODE SCIPchgVarUbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_var.c:4887
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip_mem.h:123
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define SCIP_LONGINT_MAX
Definition: def.h:163
SCIP_RETCODE SCIPcreateExprVar(SCIP *scip, SCIP_EXPR **expr, SCIP_VAR *var, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_var.c:381
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:127
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15743
Constraint handler for the set partitioning / packing / covering constraints .
static SCIP_DECL_CONSFREE(consFreeBounddisjunction)
#define CONSHDLR_ENFOPRIORITY
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:93
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:566
variable expression handler
public methods for SCIP variables
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8354
#define SCIPdebugMsg
Definition: scip_message.h:69
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1477
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:793
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8146
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
#define CONSHDLR_DELAYPROP
SCIP_Real SCIPcomputeVarUbGlobal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:6481
SCIP_Real SCIPcomputeVarLbLocal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:6502
public methods for numerical tolerances
public methods for querying solving statistics
static SCIP_Bool isLiteralSatisfied(SCIP *scip, SCIP_CONSDATA *consdata, int pos)
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4256
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:69
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
public methods for the branch-and-bound tree
#define CONSHDLR_EAGERFREQ
SCIP_RETCODE SCIPenableCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1774
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
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real bound, SCIP_Bool *redundant)
static SCIP_RETCODE enforceCurrentSol(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *infeasible, SCIP_Bool *reduceddom, SCIP_Bool *registeredbrcand)
SCIP_VAR * w
Definition: circlepacking.c:58
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:96
public methods for managing constraints
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:332
SCIP_BOUNDTYPE SCIPboundtypeOpposite(SCIP_BOUNDTYPE boundtype)
Definition: lp.c:17136
#define SCIPerrorMessage
Definition: pub_message.h:55
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4175
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, SCIP_SOL *sol, SCIP_RESULT *result)
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_prob.c:2769
#define CONSHDLR_NAME
static SCIP_DECL_CONSGETNVARS(consGetNVarsBounddisjunction)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
void SCIPsortPtrRealInt(void **ptrarray, SCIP_Real *realarray, int *intarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_RETCODE SCIPaddNlRow(SCIP *scip, SCIP_NLROW *nlrow)
Definition: scip_nlp.c:354
public methods for event handler plugins and event handlers
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
SCIP_RETCODE SCIPreleaseNlRow(SCIP *scip, SCIP_NLROW **nlrow)
Definition: scip_nlp.c:1016
public functions to work with algebraic expressions
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4434
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8085
SCIP_RETCODE SCIPcreateConsBounddisjunction(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, 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 SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8304
static SCIP_DECL_CONSINITSOL(consInitsolBounddisjunction)
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
static SCIP_DECL_CONSENFOLP(consEnfolpBounddisjunction)
#define CONSHDLR_CHECKPRIORITY
#define NULL
Definition: lpi_spx1.cpp:155
power and signed power expression handlers
#define REALABS(x)
Definition: def.h:201
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:71
SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip_branch.c:1008
public methods for problem copies
struct SCIP_ConflicthdlrData SCIP_CONFLICTHDLRDATA
Definition: type_conflict.h:40
#define SCIP_CALL(x)
Definition: def.h:384
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:68
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPcomputeVarUbLocal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:6523
static SCIP_DECL_CONSPARSE(consParseBounddisjunction)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip_message.c:216
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8324
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:632
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:56
SCIP_RETCODE SCIPdisableCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip_cons.c:1808
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:114
public methods for constraint handler plugins and constraints
#define AGEINCREASE(n)
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip_prob.c:3322
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
static SCIP_RETCODE processWatchedVars(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *infeasible, SCIP_Bool *reduceddom, SCIP_Bool *mustcheck)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:115
public data structures and miscellaneous methods
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
#define SCIP_Bool
Definition: def.h:84
SCIP_Bool SCIPconsIsUpdatedeactivate(SCIP_CONS *cons)
Definition: cons.c:8156
#define isFeasLT(scip, var, val1, val2)
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1021
SCIP_RETCODE SCIPcreateConsBasicBounddisjunctionRedundant(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
SCIP_Bool SCIPconsIsPropagationEnabled(SCIP_CONS *cons)
Definition: cons.c:8203
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyBounddisjunction)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:661
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition: scip_expr.c:1407
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2473
static SCIP_DECL_CONSACTIVE(consActiveBounddisjunction)
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10856
static SCIP_RETCODE removeFixedVariables(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *redundant)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8105
SCIP_RETCODE SCIPaddConflictBd(SCIP *scip, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx)
public methods for LP management
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8214
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8284
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8254
SCIP_Real SCIPcomputeVarLbGlobal(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:6460
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_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18502
SCIP_Real SCIPcalcNodeselPriority(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR branchdir, SCIP_Real targetvalue)
Definition: scip_branch.c:911
SCIP_RETCODE SCIPaddExternBranchCand(SCIP *scip, SCIP_VAR *var, SCIP_Real score, SCIP_Real solval)
Definition: scip_branch.c:656
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
static SCIP_DECL_CONSRESPROP(consRespropBounddisjunction)
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:127
int SCIPgetNRuns(SCIP *scip)
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip_var.c:4348
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:770
static SCIP_DECL_CONSPRESOL(consPresolBounddisjunction)
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:70
SCIP_RETCODE SCIPsetConflicthdlrFree(SCIP *scip, SCIP_CONFLICTHDLR *conflicthdlr, SCIP_DECL_CONFLICTFREE((*conflictfree)))
Constraint handler for linear constraints in their most general form, .
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPcreateConsLogicor(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)
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
SCIP_Real SCIPcalcChildEstimate(SCIP *scip, SCIP_VAR *var, SCIP_Real targetvalue)
Definition: scip_branch.c:938
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip_probing.c:88
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:12468
static SCIP_Bool isLiteralViolated(SCIP *scip, SCIP_CONSDATA *consdata, int pos)
#define SCIP_REAL_MAX
Definition: def.h:178
public methods for nonlinear relaxation
#define isFeasLE(scip, var, val1, val2)
static SCIP_DECL_CONSENFOPS(consEnfopsBounddisjunction)
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 SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip_cons.c:501
public methods for branching rule plugins and branching
SCIP_VAR ** b
Definition: circlepacking.c:56
public methods for managing events
general public methods
static SCIP_RETCODE createNAryBranch(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
static SCIP_RETCODE upgradeCons(SCIP *scip, SCIP_CONS *cons, int *ndelconss, int *naddconss)
#define EVENTHDLR_DESC
public methods for solutions
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip_copy.c:702
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_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, int pos)
public methods for conflict analysis handlers
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip_copy.c:651
public methods for the probing mode
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip_cons.c:1110
SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
Definition: scip_conflict.c:99
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:763
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_BOUNDTYPE * SCIPgetBoundtypesBounddisjunction(SCIP *scip, SCIP_CONS *cons)
void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip_sol.c:264
SCIP_VAR * a
Definition: circlepacking.c:57
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17370
#define SCIP_Real
Definition: def.h:177
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8334
static SCIP_DECL_CONSPROP(consPropBounddisjunction)
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
public methods for message handling
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8274
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8264
#define SCIP_Longint
Definition: def.h:162
static void consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file, SCIP_Bool endline)
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17416
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:55
#define EVENTHDLR_NAME
static SCIP_DECL_CONSCOPY(consCopyBounddisjunction)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17976
static SCIP_DECL_CONSEXITPRE(consExitpreBounddisjunction)
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:102
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17393
SCIP_RETCODE SCIPcreateConsBounddisjunctionRedundant(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_BOUNDTYPE *boundtypes, SCIP_Real *bounds, 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_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18532
#define CONSHDLR_DESC
SCIP_RETCODE SCIPsetConshdlrActive(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSACTIVE((*consactive)))
Definition: scip_cons.c:655
SCIPallocBlockMemory(scip, subsol))
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip_prob.c:3227
static SCIP_DECL_CONFLICTFREE(conflictFreeBounddisjunction)
static SCIP_DECL_CONFLICTEXEC(conflictExecBounddisjunction)
SCIP_CONFLICTHDLRDATA * SCIPconflicthdlrGetData(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:676
constraint handler for bound disjunction constraints
static SCIP_RETCODE registerBranchingCandidates(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *cutoff, SCIP_Bool *neednarybranch)
#define CONFLICTHDLR_NAME
static SCIP_DECL_CONSPRINT(consPrintBounddisjunction)
static SCIP_DECL_EVENTEXEC(eventExecBounddisjunction)
#define CONSHDLR_MAXPREROUNDS
#define SCIPABORT()
Definition: def.h:356
public methods for global and local (sub)problems
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17442
#define CONSHDLR_PRESOLTIMING
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1352
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
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
#define DEFAULT_CONTINUOUSFRAC
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip_var.c:1524
static SCIP_DECL_CONSDEACTIVE(consDeactiveBounddisjunction)
static SCIP_RETCODE switchWatchedvars(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17580
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:119
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_CONSLOCK(consLockBounddisjunction)
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:115
memory allocation routines