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