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