Scippy

SCIP

Solving Constraint Integer Programs

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