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