Scippy

SCIP

Solving Constraint Integer Programs

cons_or.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-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_or.c
17  * @brief Constraint handler for "or" constraints, \f$r = x_1 \vee x_2 \vee \dots \vee x_n\f$
18  * @author Tobias Achterberg
19  * @author Stefan Heinz
20  * @author Michael Winkler
21  *
22  * This constraint handler deals with "or" constraint. These are constraint of the form:
23  *
24  * \f[
25  * r = x_1 \vee x_2 \vee \dots \vee x_n
26  * \f]
27  *
28  * where \f$x_i\f$ is a binary variable for all \f$i\f$. Hence, \f$r\f$ is also of binary type. The variable \f$r\f$ is
29  * called resultant and the \f$x\f$'s operators.
30  */
31 
32 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33 
34 #include <assert.h>
35 #include <string.h>
36 
37 #include "scip/cons_or.h"
38 #include "scip/cons_and.h"
39 #include "scip/pub_misc.h"
40 
41 
42 /* constraint handler properties */
43 #define CONSHDLR_NAME "or"
44 #define CONSHDLR_DESC "constraint handler for or constraints: r = or(x1, ..., xn)"
45 #define CONSHDLR_SEPAPRIORITY +850000 /**< priority of the constraint handler for separation */
46 #define CONSHDLR_ENFOPRIORITY -850000 /**< priority of the constraint handler for constraint enforcing */
47 #define CONSHDLR_CHECKPRIORITY -850000 /**< priority of the constraint handler for checking feasibility */
48 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
49 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
50 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
51  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
52 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
53 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
54 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
55 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
56 
57 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP /**< propagation timing mask of the constraint handler */
58 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_MEDIUM /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
59 
60 #define EVENTHDLR_NAME "or"
61 #define EVENTHDLR_DESC "event handler for or constraints"
62 
63 
64 /*
65  * Data structures
66  */
67 
68 /** constraint data for or constraints */
69 struct SCIP_ConsData
70 {
71  SCIP_VAR** vars; /**< variables in the or operation */
72  SCIP_VAR* resvar; /**< resultant variable */
73  SCIP_ROW** rows; /**< rows for linear relaxation of or constraint */
74  int nvars; /**< number of variables in or operation */
75  int varssize; /**< size of vars array */
76  int rowssize; /**< size of rows array */
77  int watchedvar1; /**< position of first watched operator variable */
78  int watchedvar2; /**< position of second watched operator variable */
79  int filterpos1; /**< event filter position of first watched operator variable */
80  int filterpos2; /**< event filter position of second watched operator variable */
81  unsigned int propagated:1; /**< is constraint already preprocessed/propagated? */
82  unsigned int nofixedone:1; /**< is none of the operator variables fixed to TRUE? */
83  unsigned int impladded:1; /**< were the implications of the constraint already added? */
84  unsigned int opimpladded:1; /**< was the implication for 2 operands with fixed resultant added? */
85 };
86 
87 /** constraint handler data */
88 struct SCIP_ConshdlrData
89 {
90  SCIP_EVENTHDLR* eventhdlr; /**< event handler for events on watched variables */
91 };
92 
93 
94 /*
95  * Propagation rules
96  */
97 
98 enum Proprule
99 {
100  PROPRULE_1, /**< v_i = TRUE => r = TRUE */
101  PROPRULE_2, /**< r = FALSE => v_i = FALSE for all i */
102  PROPRULE_3, /**< v_i = FALSE for all i => r = FALSE */
103  PROPRULE_4, /**< r = TRUE, v_i = FALSE for all i except j => v_j = TRUE */
104  PROPRULE_INVALID /**< propagation was applied without a specific propagation rule */
105 };
106 typedef enum Proprule PROPRULE;
108 
109 /*
110  * Local methods
111  */
112 
113 /** installs rounding locks for the given variable in the given or constraint */
114 static
116  SCIP* scip, /**< SCIP data structure */
117  SCIP_CONS* cons, /**< or constraint */
118  SCIP_VAR* var /**< variable of constraint entry */
119  )
120 {
121  /* rounding in both directions may violate the constraint */
122  SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, TRUE) );
123 
124  return SCIP_OKAY;
125 }
126 
127 /** removes rounding locks for the given variable in the given or constraint */
128 static
130  SCIP* scip, /**< SCIP data structure */
131  SCIP_CONS* cons, /**< or constraint */
132  SCIP_VAR* var /**< variable of constraint entry */
133  )
134 {
135  /* rounding in both directions may violate the constraint */
136  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, TRUE) );
137 
138  return SCIP_OKAY;
139 }
140 
141 /** creates constraint handler data */
142 static
144  SCIP* scip, /**< SCIP data structure */
145  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
146  SCIP_EVENTHDLR* eventhdlr /**< event handler */
147  )
148 {
149  assert(scip != NULL);
150  assert(conshdlrdata != NULL);
151  assert(eventhdlr != NULL);
152 
153  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
154 
155  /* set event handler for catching events on watched variables */
156  (*conshdlrdata)->eventhdlr = eventhdlr;
157 
158  return SCIP_OKAY;
159 }
160 
161 /** frees constraint handler data */
162 static
164  SCIP* scip, /**< SCIP data structure */
165  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
166  )
167 {
168  assert(conshdlrdata != NULL);
169  assert(*conshdlrdata != NULL);
170 
171  SCIPfreeBlockMemory(scip, conshdlrdata);
172 
173  return SCIP_OKAY;
174 }
175 
176 /** gets number of LP rows needed for the LP relaxation of the constraint */
177 static
178 int consdataGetNRows(
179  SCIP_CONSDATA* consdata /**< constraint data */
180  )
181 {
182  assert(consdata != NULL);
183 
184  return consdata->nvars + 1;
185 }
186 
187 /** catches events for the watched variable at given position */
188 static
190  SCIP* scip, /**< SCIP data structure */
191  SCIP_CONSDATA* consdata, /**< or constraint data */
192  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
193  int pos, /**< array position of variable to catch bound change events for */
194  int* filterpos /**< pointer to store position of event filter entry */
195  )
196 {
197  assert(consdata != NULL);
198  assert(consdata->vars != NULL);
199  assert(eventhdlr != NULL);
200  assert(0 <= pos && pos < consdata->nvars);
201  assert(filterpos != NULL);
202 
203  /* catch tightening events for upper bound and relaxed events for lower bounds on watched variable */
205  eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
206 
207  return SCIP_OKAY;
208 }
209 
210 
211 /** drops events for the watched variable at given position */
212 static
214  SCIP* scip, /**< SCIP data structure */
215  SCIP_CONSDATA* consdata, /**< or constraint data */
216  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
217  int pos, /**< array position of watched variable to drop bound change events for */
218  int filterpos /**< position of event filter entry */
219  )
220 {
221  assert(consdata != NULL);
222  assert(consdata->vars != NULL);
223  assert(eventhdlr != NULL);
224  assert(0 <= pos && pos < consdata->nvars);
225  assert(filterpos >= 0);
226 
227  /* drop tightening events for upper bound and relaxed events for lower bounds on watched variable */
229  eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
230 
231  return SCIP_OKAY;
232 }
233 
234 /** catches needed events on all variables of constraint, except the special ones for watched variables */
235 static
237  SCIP* scip, /**< SCIP data structure */
238  SCIP_CONSDATA* consdata, /**< or constraint data */
239  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
240  )
241 {
242  int i;
243 
244  assert(consdata != NULL);
245 
246  /* catch bound change events for both bounds on resultant variable */
247  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->resvar, SCIP_EVENTTYPE_BOUNDCHANGED,
248  eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
249 
250  /* catch tightening events for lower bound and relaxed events for upper bounds on operator variables */
251  for( i = 0; i < consdata->nvars; ++i )
252  {
254  eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
255  }
256 
257  return SCIP_OKAY;
258 }
259 
260 /** drops events on all variables of constraint, except the special ones for watched variables */
261 static
263  SCIP* scip, /**< SCIP data structure */
264  SCIP_CONSDATA* consdata, /**< or constraint data */
265  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
266  )
267 {
268  int i;
269 
270  assert(consdata != NULL);
271 
272  /* drop bound change events for both bounds on resultant variable */
273  SCIP_CALL( SCIPdropVarEvent(scip, consdata->resvar, SCIP_EVENTTYPE_BOUNDCHANGED,
274  eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
275 
276  /* drop tightening events for lower bound and relaxed events for upper bounds on operator variables */
277  for( i = 0; i < consdata->nvars; ++i )
278  {
280  eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
281  }
282 
283  return SCIP_OKAY;
284 }
285 
286 /** stores the given variable numbers as watched variables, and updates the event processing */
287 static
289  SCIP* scip, /**< SCIP data structure */
290  SCIP_CONSDATA* consdata, /**< or constraint data */
291  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
292  int watchedvar1, /**< new first watched variable */
293  int watchedvar2 /**< new second watched variable */
294  )
295 {
296  assert(consdata != NULL);
297  assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
298  assert(watchedvar1 != -1 || watchedvar2 == -1);
299  assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
300  assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
301 
302  /* if one watched variable is equal to the old other watched variable, just switch positions */
303  if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
304  {
305  int tmp;
306 
307  tmp = consdata->watchedvar1;
308  consdata->watchedvar1 = consdata->watchedvar2;
309  consdata->watchedvar2 = tmp;
310  tmp = consdata->filterpos1;
311  consdata->filterpos1 = consdata->filterpos2;
312  consdata->filterpos2 = tmp;
313  }
314  assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
315  assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
316 
317  /* drop events on old watched variables */
318  if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
319  {
320  assert(consdata->filterpos1 != -1);
321  SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
322  }
323  if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
324  {
325  assert(consdata->filterpos2 != -1);
326  SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
327  }
328 
329  /* catch events on new watched variables */
330  if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
331  {
332  SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar1, &consdata->filterpos1) );
333  }
334  if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
335  {
336  SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar2, &consdata->filterpos2) );
337  }
338 
339  /* set the new watched variables */
340  consdata->watchedvar1 = watchedvar1;
341  consdata->watchedvar2 = watchedvar2;
342 
343  return SCIP_OKAY;
344 }
345 
346 /** ensures, that the vars array can store at least num entries */
347 static
349  SCIP* scip, /**< SCIP data structure */
350  SCIP_CONSDATA* consdata, /**< linear constraint data */
351  int num /**< minimum number of entries to store */
352  )
353 {
354  assert(consdata != NULL);
355  assert(consdata->nvars <= consdata->varssize);
356 
357  if( num > consdata->varssize )
358  {
359  int newsize;
360 
361  newsize = SCIPcalcMemGrowSize(scip, num);
362  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
363  consdata->varssize = newsize;
364  }
365  assert(num <= consdata->varssize);
366 
367  return SCIP_OKAY;
368 }
369 
370 /** creates constraint data for or constraint */
371 static
373  SCIP* scip, /**< SCIP data structure */
374  SCIP_CONSDATA** consdata, /**< pointer to store the constraint data */
375  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
376  int nvars, /**< number of variables in the or operation */
377  SCIP_VAR** vars, /**< variables in or operation */
378  SCIP_VAR* resvar /**< resultant variable */
379  )
380 {
381  assert(consdata != NULL);
382  assert(nvars == 0 || vars != NULL);
383  assert(resvar != NULL);
384 
385  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
386  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
387  (*consdata)->resvar = resvar;
388  (*consdata)->rows = NULL;
389  (*consdata)->nvars = nvars;
390  (*consdata)->varssize = nvars;
391  (*consdata)->rowssize = 0;
392  (*consdata)->watchedvar1 = -1;
393  (*consdata)->watchedvar2 = -1;
394  (*consdata)->filterpos1 = -1;
395  (*consdata)->filterpos2 = -1;
396  (*consdata)->propagated = FALSE;
397  (*consdata)->nofixedone = FALSE;
398  (*consdata)->impladded = FALSE;
399  (*consdata)->opimpladded = FALSE;
400 
401  /* get transformed variables, if we are in the transformed problem */
402  if( SCIPisTransformed(scip) )
403  {
404  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
405  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->resvar, &(*consdata)->resvar) );
406 
407  /* catch needed events on variables */
408  SCIP_CALL( consdataCatchEvents(scip, *consdata, eventhdlr) );
409  }
410 
411  return SCIP_OKAY;
412 }
413 
414 /** releases LP rows of constraint data and frees rows array */
415 static
417  SCIP* scip, /**< SCIP data structure */
418  SCIP_CONSDATA* consdata /**< constraint data */
419  )
420 {
421  int r;
422 
423  assert(consdata != NULL);
424 
425  if( consdata->rows != NULL )
426  {
427  int nrows;
428 
429  nrows = consdataGetNRows(consdata);
430 
431  for( r = 0; r < nrows; ++r )
432  {
433  SCIP_CALL( SCIPreleaseRow(scip, &consdata->rows[r]) );
434  }
435  SCIPfreeBlockMemoryArray(scip, &consdata->rows, consdata->rowssize);
436  }
437 
438  return SCIP_OKAY;
439 }
440 
441 /** frees constraint data for or constraint */
442 static
444  SCIP* scip, /**< SCIP data structure */
445  SCIP_CONSDATA** consdata, /**< pointer to the constraint data */
446  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
447  )
448 {
449  assert(consdata != NULL);
450  assert(*consdata != NULL);
451 
452  if( SCIPisTransformed(scip) )
453  {
454  /* drop events for watched variables */
455  SCIP_CALL( consdataSwitchWatchedvars(scip, *consdata, eventhdlr, -1, -1) );
456 
457  /* drop all other events on variables */
458  SCIP_CALL( consdataDropEvents(scip, *consdata, eventhdlr) );
459  }
460  else
461  {
462  assert((*consdata)->watchedvar1 == -1);
463  assert((*consdata)->watchedvar2 == -1);
464  }
465 
466  /* release and free the rows */
467  SCIP_CALL( consdataFreeRows(scip, *consdata) );
468 
469  SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->varssize);
470  SCIPfreeBlockMemory(scip, consdata);
471 
472  return SCIP_OKAY;
473 }
474 
475 /** prints or constraint to file stream */
476 static
478  SCIP* scip, /**< SCIP data structure */
479  SCIP_CONSDATA* consdata, /**< or constraint data */
480  FILE* file /**< output file (or NULL for standard output) */
481  )
482 {
483  assert(consdata != NULL);
484 
485  /* print resultant */
486  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->resvar, TRUE) );
487 
488  /* start the variable list */
489  SCIPinfoMessage(scip, file, " == or(");
490 
491  /* print variable list */
492  SCIP_CALL( SCIPwriteVarsList(scip, file, consdata->vars, consdata->nvars, TRUE, ',') );
493 
494  /* close the variable list */
495  SCIPinfoMessage(scip, file, ")");
496 
497  return SCIP_OKAY;
498 }
499 
500 /** adds coefficient in or constraint */
501 static
503  SCIP* scip, /**< SCIP data structure */
504  SCIP_CONS* cons, /**< linear constraint */
505  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
506  SCIP_VAR* var /**< variable to add to the constraint */
507  )
508 {
509  SCIP_CONSDATA* consdata;
510  SCIP_Bool transformed;
511 
512  assert(var != NULL);
513 
514  consdata = SCIPconsGetData(cons);
515  assert(consdata != NULL);
516  assert(consdata->rows == NULL);
517 
518  /* are we in the transformed problem? */
519  transformed = SCIPconsIsTransformed(cons);
520 
521  /* always use transformed variables in transformed constraints */
522  if( transformed )
523  {
524  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
525  }
526  assert(var != NULL);
527  assert(transformed == SCIPvarIsTransformed(var));
528 
529  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
530  consdata->vars[consdata->nvars] = var;
531  consdata->nvars++;
532 
533  /* if we are in transformed problem, catch the variable's events */
534  if( transformed )
535  {
536  /* catch bound change events of variable */
538  eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
539  }
540 
541  /* install the rounding locks for the new variable */
542  SCIP_CALL( lockRounding(scip, cons, var) );
543 
544  /**@todo update LP rows */
545  if( consdata->rows != NULL )
546  {
547  SCIPerrorMessage("cannot add coefficients to or constraint after LP relaxation was created\n");
548  return SCIP_INVALIDCALL;
549  }
550 
551  return SCIP_OKAY;
552 }
553 
554 /** deletes coefficient at given position from or constraint data */
555 static
557  SCIP* scip, /**< SCIP data structure */
558  SCIP_CONS* cons, /**< or constraint */
559  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
560  int pos /**< position of coefficient to delete */
561  )
562 {
563  SCIP_CONSDATA* consdata;
564 
565  assert(eventhdlr != NULL);
566 
567  consdata = SCIPconsGetData(cons);
568  assert(consdata != NULL);
569  assert(0 <= pos && pos < consdata->nvars);
570  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
571 
572  /* remove the rounding locks of the variable */
573  SCIP_CALL( unlockRounding(scip, cons, consdata->vars[pos]) );
574 
575  if( SCIPconsIsTransformed(cons) )
576  {
577  /* drop bound change events of variable */
579  eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
580  }
581 
582  if( SCIPconsIsTransformed(cons) )
583  {
584  /* if the position is watched, stop watching the position */
585  if( consdata->watchedvar1 == pos )
586  {
587  SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar2, -1) );
588  }
589  if( consdata->watchedvar2 == pos )
590  {
591  SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar1, -1) );
592  }
593  }
594  assert(pos != consdata->watchedvar1);
595  assert(pos != consdata->watchedvar2);
596 
597  /* move the last variable to the free slot */
598  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
599  consdata->nvars--;
600 
601  /* if the last variable (that moved) was watched, update the watched position */
602  if( consdata->watchedvar1 == consdata->nvars )
603  consdata->watchedvar1 = pos;
604  if( consdata->watchedvar2 == consdata->nvars )
605  consdata->watchedvar2 = pos;
606 
607  consdata->propagated = FALSE;
608 
609  return SCIP_OKAY;
610 }
611 
612 /** deletes all zero-fixed variables */
613 static
615  SCIP* scip, /**< SCIP data structure */
616  SCIP_CONS* cons, /**< or constraint */
617  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
618  )
619 {
620  SCIP_CONSDATA* consdata;
621  SCIP_VAR* var;
622  int v;
623 
624  consdata = SCIPconsGetData(cons);
625  assert(consdata != NULL);
626  assert(consdata->nvars == 0 || consdata->vars != NULL);
627 
628  v = 0;
629  while( v < consdata->nvars )
630  {
631  var = consdata->vars[v];
632  assert(SCIPvarIsBinary(var));
633 
634  if( SCIPvarGetUbGlobal(var) < 0.5 )
635  {
636  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), 0.0));
637  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
638  }
639  else
640  {
641  SCIP_VAR* repvar;
642  SCIP_Bool negated;
643 
644  /* get binary representative of variable */
645  SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
646 
647  /* check, if the variable should be replaced with the representative */
648  if( repvar != var )
649  {
650  /* delete old (aggregated) variable */
651  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
652 
653  /* add representative instead */
654  SCIP_CALL( addCoef(scip, cons, eventhdlr, repvar) );
655  }
656  else
657  ++v;
658  }
659  }
660 
661  SCIPdebugMsg(scip, "after fixings: ");
662  SCIPdebug( SCIP_CALL(consdataPrint(scip, consdata, NULL)) );
663  SCIPdebugMsgPrint(scip, "\n");
664 
665  return SCIP_OKAY;
666 }
667 
668 /** creates LP rows corresponding to or constraint:
669  * - for each operator variable vi: resvar - vi >= 0
670  * - one additional row: resvar - v1 - ... - vn <= 0
671  */
672 static
674  SCIP* scip, /**< SCIP data structure */
675  SCIP_CONS* cons /**< constraint to check */
676  )
677 {
678  SCIP_CONSDATA* consdata;
679  char rowname[SCIP_MAXSTRLEN];
680  int nvars;
681  int i;
682 
683  consdata = SCIPconsGetData(cons);
684  assert(consdata != NULL);
685  assert(consdata->rows == NULL);
686 
687  nvars = consdata->nvars;
688 
689  /* get memory for rows */
690  consdata->rowssize = consdataGetNRows(consdata);
691  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->rows, consdata->rowssize) );
692  assert(consdata->rowssize == nvars+1);
693 
694  /* create operator rows */
695  for( i = 0; i < nvars; ++i )
696  {
697  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), i);
698  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[i], SCIPconsGetHdlr(cons), rowname, 0.0, SCIPinfinity(scip),
700  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i], consdata->resvar, 1.0) );
701  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i], consdata->vars[i], -1.0) );
702  }
703 
704  /* create additional row */
705  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_add", SCIPconsGetName(cons));
706  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[nvars], SCIPconsGetHdlr(cons), rowname, -SCIPinfinity(scip), 0.0,
708  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[nvars], consdata->resvar, 1.0) );
709  SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[nvars], nvars, consdata->vars, -1.0) );
710 
711  return SCIP_OKAY;
712 }
713 
714 /** adds linear relaxation of or constraint to the LP */
715 static
717  SCIP* scip, /**< SCIP data structure */
718  SCIP_CONS* cons, /**< constraint to check */
719  SCIP_Bool* infeasible /**< pointer to store whether an infeasibility was detected */
720  )
721 {
722  SCIP_CONSDATA* consdata;
723  int r;
724  int nrows;
725 
726  consdata = SCIPconsGetData(cons);
727  assert(consdata != NULL);
728 
729  if( consdata->rows == NULL )
730  {
731  SCIP_CALL( createRelaxation(scip, cons) );
732  }
733  assert( consdata->rows != NULL );
734 
735  nrows = consdataGetNRows(consdata);
736 
737  for( r = 0; r < nrows && !(*infeasible); ++r )
738  {
739  if( !SCIProwIsInLP(consdata->rows[r]) )
740  {
741  SCIP_CALL( SCIPaddCut(scip, NULL, consdata->rows[r], FALSE, infeasible) );
742  }
743  }
744 
745  return SCIP_OKAY;
746 }
747 
748 /** checks or constraint for feasibility of given solution: returns TRUE iff constraint is feasible */
749 static
751  SCIP* scip, /**< SCIP data structure */
752  SCIP_CONS* cons, /**< constraint to check */
753  SCIP_SOL* sol, /**< solution to check, NULL for current solution */
754  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
755  SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
756  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
757  )
758 {
759  SCIP_CONSDATA* consdata;
760  SCIP_Bool mustcheck;
761  int r;
762 
763  assert(violated != NULL);
764 
765  consdata = SCIPconsGetData(cons);
766  assert(consdata != NULL);
767 
768  *violated = FALSE;
769 
770  /* check, if we can skip this feasibility check, because all rows are in the LP and doesn't have to be checked */
771  mustcheck = checklprows;
772  mustcheck = mustcheck || (consdata->rows == NULL);
773  if( !mustcheck )
774  {
775  int nrows;
776 
777  assert(consdata->rows != NULL);
778 
779  nrows = consdataGetNRows(consdata);
780 
781  for( r = 0; r < nrows; ++r )
782  {
783  mustcheck = !SCIProwIsInLP(consdata->rows[r]);
784  if( mustcheck )
785  break;
786  }
787  }
788 
789  /* check feasibility of constraint if necessary */
790  if( mustcheck )
791  {
792  SCIP_Real solval;
793  int i;
794 
795  /* increase age of constraint; age is reset to zero, if a violation was found only in case we are in
796  * enforcement
797  */
798  if( sol == NULL )
799  {
800  SCIP_CALL( SCIPincConsAge(scip, cons) );
801  }
802 
803  /* check, if all operator variables are FALSE */
804  for( i = 0; i < consdata->nvars; ++i )
805  {
806  solval = SCIPgetSolVal(scip, sol, consdata->vars[i]);
807  assert(SCIPisFeasIntegral(scip, solval));
808  if( solval > 0.5 )
809  break;
810  }
811 
812  /* if all operator variables are FALSE, the resultant has to be FALSE, otherwise, the resultant has to be TRUE */
813  solval = SCIPgetSolVal(scip, sol, consdata->resvar);
814  assert(SCIPisFeasIntegral(scip, solval));
815 
816  if( (i == consdata->nvars) != (solval < 0.5) )
817  {
818  *violated = TRUE;
819 
820  /* only reset constraint age if we are in enforcement */
821  if( sol == NULL )
822  {
823  SCIP_CALL( SCIPresetConsAge(scip, cons) );
824  }
825 
826  if( printreason )
827  {
828  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
829  SCIPinfoMessage(scip, NULL, ";\nviolation:\n");
830  if( i == consdata->nvars )
831  {
832  SCIPinfoMessage(scip, NULL, " all operands are FALSE and resultant <%s> = TRUE\n",
833  SCIPvarGetName(consdata->resvar));
834  }
835  else
836  {
837  SCIPinfoMessage(scip, NULL, " operand <%s> = TRUE and resultant <%s> = FALSE\n",
838  SCIPvarGetName(consdata->vars[i-1]), SCIPvarGetName(consdata->resvar));
839  }
840  }
841  }
842  }
843 
844  return SCIP_OKAY;
845 }
846 
847 /** separates current LP solution */
848 static
850  SCIP* scip, /**< SCIP data structure */
851  SCIP_CONS* cons, /**< constraint to check */
852  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
853  SCIP_Bool* separated /**< pointer to store whether a cut was found */
854  )
855 {
856  SCIP_CONSDATA* consdata;
857  SCIP_Real feasibility;
858  int r;
859  int nrows;
860 
861  assert(separated != NULL);
862 
863  consdata = SCIPconsGetData(cons);
864  assert(consdata != NULL);
865 
866  *separated = FALSE;
867 
868  /* create all necessary rows for the linear relaxation */
869  if( consdata->rows == NULL )
870  {
871  SCIP_CALL( createRelaxation(scip, cons) );
872  }
873  assert(consdata->rows != NULL);
874 
875  nrows = consdataGetNRows(consdata);
876 
877  /* test all rows for feasibility and add infeasible rows */
878  for( r = 0; r < nrows; ++r )
879  {
880  if( !SCIProwIsInLP(consdata->rows[r]) )
881  {
882  feasibility = SCIPgetRowSolFeasibility(scip, consdata->rows[r], sol);
883  if( SCIPisFeasNegative(scip, feasibility) )
884  {
885  SCIP_Bool infeasible;
886 
887  SCIP_CALL( SCIPaddCut(scip, sol, consdata->rows[r], FALSE, &infeasible) );
888  assert( ! infeasible );
889  *separated = TRUE;
890  }
891  }
892  }
893 
894  return SCIP_OKAY;
895 }
896 
897 /** analyzes conflicting FALSE assignment to resultant of given constraint, and adds conflict constraint to problem */
898 static
900  SCIP* scip, /**< SCIP data structure */
901  SCIP_CONS* cons, /**< or constraint that detected the conflict */
902  int truepos /**< position of operand that is fixed to TRUE */
903  )
904 {
905  SCIP_CONSDATA* consdata;
906 
907  /* conflict analysis can only be applied in solving stage and if it is applicable */
909  return SCIP_OKAY;
910 
911  consdata = SCIPconsGetData(cons);
912  assert(consdata != NULL);
913  assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
914  assert(0 <= truepos && truepos < consdata->nvars);
915  assert(SCIPvarGetLbLocal(consdata->vars[truepos]) > 0.5);
916 
917  /* initialize conflict analysis, and add resultant and single operand variable to conflict candidate queue */
919 
920  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
921  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[truepos]) );
922 
923  /* analyze the conflict */
924  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
925 
926  return SCIP_OKAY;
927 }
928 
929 /** analyzes conflicting TRUE assignment to resultant of given constraint, and adds conflict constraint to problem */
930 static
932  SCIP* scip, /**< SCIP data structure */
933  SCIP_CONS* cons /**< or constraint that detected the conflict */
934  )
935 {
936  SCIP_CONSDATA* consdata;
937  int v;
938 
939  assert(!SCIPconsIsModifiable(cons));
940 
941  /* conflict analysis can only be applied in solving stage and if it is applicable */
943  return SCIP_OKAY;
944 
945  consdata = SCIPconsGetData(cons);
946  assert(consdata != NULL);
947  assert(SCIPvarGetLbLocal(consdata->resvar) > 0.5);
948 
949  /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
951 
952  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
953  for( v = 0; v < consdata->nvars; ++v )
954  {
955  assert(SCIPvarGetUbLocal(consdata->vars[v]) < 0.5);
956  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
957  }
958 
959  /* analyze the conflict */
960  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
961 
962  return SCIP_OKAY;
963 }
964 
965 /** propagates constraint with the following rules:
966  * (1) v_i = TRUE => r = TRUE
967  * (2) r = FALSE => v_i = FALSE for all i
968  * (3) v_i = FALSE for all i => r = FALSE
969  * (4) r = TRUE, v_i = FALSE for all i except j => v_j = TRUE
970  */
971 static
973  SCIP* scip, /**< SCIP data structure */
974  SCIP_CONS* cons, /**< or constraint to be processed */
975  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
976  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
977  int* nfixedvars /**< pointer to add up the number of found domain reductions */
978  )
979 {
980  SCIP_CONSDATA* consdata;
981  SCIP_VAR* resvar;
982  SCIP_VAR** vars;
983  int nvars;
984  int watchedvar1;
985  int watchedvar2;
986  int i;
987  SCIP_Bool infeasible;
988  SCIP_Bool tightened;
989 
990  assert(cutoff != NULL);
991  assert(nfixedvars != NULL);
992 
993  consdata = SCIPconsGetData(cons);
994  assert(consdata != NULL);
995 
996  resvar = consdata->resvar;
997  vars = consdata->vars;
998  nvars = consdata->nvars;
999 
1000  /* don't process the constraint, if none of the operator variables was fixed to TRUE, and if the watched variables
1001  * and the resultant weren't fixed to any value since last propagation call
1002  */
1003  if( consdata->propagated )
1004  {
1005  assert(consdata->nofixedone);
1006  assert(SCIPisFeasEQ(scip, SCIPvarGetUbLocal(resvar), 1.0));
1007  return SCIP_OKAY;
1008  }
1009 
1010  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
1011  if( !SCIPinRepropagation(scip) )
1012  {
1013  SCIP_CALL( SCIPincConsAge(scip, cons) );
1014  }
1015 
1016  /* if one of the operator variables was fixed to TRUE, the resultant can be fixed to TRUE (rule (1)) */
1017  if( !consdata->nofixedone )
1018  {
1019  for( i = 0; i < nvars && SCIPvarGetLbLocal(vars[i]) < 0.5; ++i ) /* search fixed operator */
1020  {}
1021  if( i < nvars )
1022  {
1023  SCIPdebugMsg(scip, "constraint <%s>: operator var <%s> fixed to 1.0 -> fix resultant <%s> to 1.0\n",
1024  SCIPconsGetName(cons), SCIPvarGetName(vars[i]), SCIPvarGetName(resvar));
1025  SCIP_CALL( SCIPinferBinvarCons(scip, resvar, TRUE, cons, (int)PROPRULE_1, &infeasible, &tightened) );
1026  if( infeasible )
1027  {
1028  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1029  SCIP_CALL( analyzeConflictZero(scip, cons, i) );
1030  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1031  *cutoff = TRUE;
1032  }
1033  else
1034  {
1035  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1036  if( tightened )
1037  {
1038  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1039  (*nfixedvars)++;
1040  }
1041  }
1042 
1043  return SCIP_OKAY;
1044  }
1045  else
1046  consdata->nofixedone = TRUE;
1047  }
1048  assert(consdata->nofixedone);
1049 
1050  /* if resultant is fixed to FALSE, all operator variables can be fixed to FALSE (rule (2)) */
1051  if( SCIPvarGetUbLocal(resvar) < 0.5 )
1052  {
1053  for( i = 0; i < nvars && !(*cutoff); ++i )
1054  {
1055  SCIPdebugMsg(scip, "constraint <%s>: resultant var <%s> fixed to 0.0 -> fix operator var <%s> to 0.0\n",
1056  SCIPconsGetName(cons), SCIPvarGetName(resvar), SCIPvarGetName(vars[i]));
1057  SCIP_CALL( SCIPinferBinvarCons(scip, vars[i], FALSE, cons, (int)PROPRULE_2, &infeasible, &tightened) );
1058  if( infeasible )
1059  {
1060  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1061  SCIP_CALL( analyzeConflictZero(scip, cons, i) );
1062  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1063  *cutoff = TRUE;
1064  }
1065  else if( tightened )
1066  {
1067  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1068  (*nfixedvars)++;
1069  }
1070  }
1071 
1072  if( !(*cutoff) )
1073  {
1074  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1075  }
1076 
1077  return SCIP_OKAY;
1078  }
1079 
1080  /* rules (3) and (4) can only be applied, if we know all operator variables */
1081  if( SCIPconsIsModifiable(cons) )
1082  return SCIP_OKAY;
1083 
1084  /* rules (3) and (4) cannot be applied, if we have at least two unfixed variables left;
1085  * that means, we only have to watch (i.e. capture events) of two variables, and switch to other variables
1086  * if these ones get fixed
1087  */
1088  watchedvar1 = consdata->watchedvar1;
1089  watchedvar2 = consdata->watchedvar2;
1090 
1091  /* check, if watched variables are still unfixed */
1092  if( watchedvar1 != -1 )
1093  {
1094  assert(SCIPvarGetLbLocal(vars[watchedvar1]) < 0.5); /* otherwise, rule (1) could be applied */
1095  if( SCIPvarGetUbLocal(vars[watchedvar1]) < 0.5 )
1096  watchedvar1 = -1;
1097  }
1098  if( watchedvar2 != -1 )
1099  {
1100  assert(SCIPvarGetLbLocal(vars[watchedvar2]) < 0.5); /* otherwise, rule (1) could be applied */
1101  if( SCIPvarGetUbLocal(vars[watchedvar2]) < 0.5 )
1102  watchedvar2 = -1;
1103  }
1104 
1105  /* if only one watched variable is still unfixed, make it the first one */
1106  if( watchedvar1 == -1 )
1107  {
1108  watchedvar1 = watchedvar2;
1109  watchedvar2 = -1;
1110  }
1111  assert(watchedvar1 != -1 || watchedvar2 == -1);
1112 
1113  /* if the watched variables are invalid (fixed), find new ones if existing */
1114  if( watchedvar2 == -1 )
1115  {
1116  for( i = 0; i < nvars; ++i )
1117  {
1118  assert(SCIPvarGetLbLocal(vars[i]) < 0.5); /* otherwise, rule (1) could be applied */
1119  if( SCIPvarGetUbLocal(vars[i]) > 0.5 )
1120  {
1121  if( watchedvar1 == -1 )
1122  {
1123  assert(watchedvar2 == -1);
1124  watchedvar1 = i;
1125  }
1126  else if( watchedvar1 != i )
1127  {
1128  watchedvar2 = i;
1129  break;
1130  }
1131  }
1132  }
1133  }
1134  assert(watchedvar1 != -1 || watchedvar2 == -1);
1135 
1136  /* if all variables are fixed to FALSE, the resultant can also be fixed to FALSE (rule (3)) */
1137  if( watchedvar1 == -1 )
1138  {
1139  assert(watchedvar2 == -1);
1140 
1141  SCIPdebugMsg(scip, "constraint <%s>: all operator vars fixed to 0.0 -> fix resultant <%s> to 0.0\n",
1142  SCIPconsGetName(cons), SCIPvarGetName(resvar));
1143  SCIP_CALL( SCIPinferBinvarCons(scip, resvar, FALSE, cons, (int)PROPRULE_3, &infeasible, &tightened) );
1144  if( infeasible )
1145  {
1146  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1147  SCIP_CALL( analyzeConflictOne(scip, cons) );
1148  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1149  *cutoff = TRUE;
1150  }
1151  else
1152  {
1153  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1154  if( tightened )
1155  {
1156  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1157  (*nfixedvars)++;
1158  }
1159  }
1160 
1161  return SCIP_OKAY;
1162  }
1163 
1164  /* if resultant is fixed to TRUE, and only one operator variable is not fixed to FALSE, this operator variable
1165  * can be fixed to TRUE (rule (4))
1166  */
1167  if( SCIPvarGetLbLocal(resvar) > 0.5 && watchedvar2 == -1 )
1168  {
1169  assert(watchedvar1 != -1);
1170 
1171  SCIPdebugMsg(scip, "constraint <%s>: resultant <%s> fixed to 1.0, only one unfixed operand -> fix operand <%s> to 1.0\n",
1172  SCIPconsGetName(cons), SCIPvarGetName(resvar), SCIPvarGetName(vars[watchedvar1]));
1173  SCIP_CALL( SCIPinferBinvarCons(scip, vars[watchedvar1], TRUE, cons, (int)PROPRULE_4, &infeasible, &tightened) );
1174  if( infeasible )
1175  {
1176  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1177  SCIP_CALL( analyzeConflictOne(scip, cons) );
1178  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1179  *cutoff = TRUE;
1180  }
1181  else
1182  {
1183  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1184  if( tightened )
1185  {
1186  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1187  (*nfixedvars)++;
1188  }
1189  }
1190 
1191  return SCIP_OKAY;
1192  }
1193 
1194  /* switch to the new watched variables */
1195  SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, watchedvar1, watchedvar2) );
1196 
1197  /* mark the constraint propagated */
1198  consdata->propagated = TRUE;
1199 
1200  return SCIP_OKAY;
1201 }
1202 
1203 /** resolves a conflict on the given variable by supplying the variables needed for applying the corresponding
1204  * propagation rule (see propagateCons()):
1205  * (1) v_i = TRUE => r = TRUE
1206  * (2) r = FALSE => v_i = FALSE for all i
1207  * (3) v_i = FALSE for all i => r = FALSE
1208  * (4) r = TRUE, v_i = FALSE for all i except j => v_j = TRUE
1209  */
1210 static
1212  SCIP* scip, /**< SCIP data structure */
1213  SCIP_CONS* cons, /**< constraint that inferred the bound change */
1214  SCIP_VAR* infervar, /**< variable that was deduced */
1215  PROPRULE proprule, /**< propagation rule that deduced the value */
1216  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1217  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
1218  )
1219 {
1220  SCIP_CONSDATA* consdata;
1221  SCIP_VAR** vars;
1222  int nvars;
1223  int i;
1224 
1225  assert(result != NULL);
1226 
1227  consdata = SCIPconsGetData(cons);
1228  assert(consdata != NULL);
1229  vars = consdata->vars;
1230  nvars = consdata->nvars;
1231 
1232  switch( proprule )
1233  {
1234  case PROPRULE_1:
1235  /* the resultant was infered to TRUE, because one operand variable was TRUE */
1236  assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
1237  assert(infervar == consdata->resvar);
1238  for( i = 0; i < nvars; ++i )
1239  {
1240  if( SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5 )
1241  {
1242  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
1243  break;
1244  }
1245  }
1246  assert(i < nvars);
1247  *result = SCIP_SUCCESS;
1248  break;
1249 
1250  case PROPRULE_2:
1251  /* the operand variable was infered to FALSE, because the resultant was FALSE */
1252  assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
1253  assert(SCIPgetVarUbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) < 0.5);
1254  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1255  *result = SCIP_SUCCESS;
1256  break;
1257 
1258  case PROPRULE_3:
1259  /* the resultant was infered to FALSE, because all operand variables were FALSE */
1260  assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
1261  assert(infervar == consdata->resvar);
1262  for( i = 0; i < nvars; ++i )
1263  {
1264  assert(SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5);
1265  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
1266  }
1267  *result = SCIP_SUCCESS;
1268  break;
1269 
1270  case PROPRULE_4:
1271  /* the operand variable was infered to TRUE, because the resultant was TRUE and all other operands were FALSE */
1272  assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
1273  assert(SCIPgetVarLbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) > 0.5);
1274  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1275  for( i = 0; i < nvars; ++i )
1276  {
1277  if( vars[i] != infervar )
1278  {
1279  assert(SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5);
1280  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
1281  }
1282  }
1283  *result = SCIP_SUCCESS;
1284  break;
1285 
1286  case PROPRULE_INVALID:
1287  default:
1288  SCIPerrorMessage("invalid inference information %d in or constraint <%s>\n", proprule, SCIPconsGetName(cons));
1289  return SCIP_INVALIDDATA;
1290  }
1291 
1292  return SCIP_OKAY;
1293 }
1294 
1295 /** upgrades unmodifiable or constraint into an and constraint on negated variables */
1296 static
1298  SCIP* scip, /**< SCIP data structure */
1299  SCIP_CONS* cons, /**< constraint that inferred the bound change */
1300  int* nupgdconss /**< pointer to count the number of constraint upgrades */
1301  )
1302 {
1303  SCIP_CONSDATA* consdata;
1304  SCIP_VAR** negvars;
1305  SCIP_VAR* negresvar;
1306  SCIP_CONS* andcons;
1307  int i;
1308 
1309  assert(nupgdconss != NULL);
1310 
1311  /* we cannot upgrade a modifiable constraint, since we don't know what additional variables to expect */
1312  if( SCIPconsIsModifiable(cons) )
1313  return SCIP_OKAY;
1314 
1315  SCIPdebugMsg(scip, "upgrading or constraint <%s> into equivalent and constraint on negated variables\n",
1316  SCIPconsGetName(cons));
1317 
1318  consdata = SCIPconsGetData(cons);
1319  assert(consdata != NULL);
1320 
1321  /* get the negated versions of the variables */
1322  SCIP_CALL( SCIPallocBufferArray(scip, &negvars, consdata->nvars) );
1323  for( i = 0; i < consdata->nvars; ++i )
1324  {
1325  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[i], &negvars[i]) );
1326  }
1327  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->resvar, &negresvar) );
1328 
1329  /* create and add the and constraint */
1330  SCIP_CALL( SCIPcreateConsAnd(scip, &andcons, SCIPconsGetName(cons), negresvar, consdata->nvars, negvars,
1334  SCIP_CALL( SCIPaddCons(scip, andcons) );
1335  SCIP_CALL( SCIPreleaseCons(scip, &andcons) );
1336 
1337  /* delete the or constraint */
1338  SCIP_CALL( SCIPdelCons(scip, cons) );
1339 
1340  /* free temporary memory */
1341  SCIPfreeBufferArray(scip, &negvars);
1342 
1343  (*nupgdconss)++;
1344 
1345  return SCIP_OKAY;
1346 }
1347 
1348 
1349 /*
1350  * Callback methods of constraint handler
1351  */
1352 
1353 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1354 static
1355 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOr)
1356 { /*lint --e{715}*/
1357  assert(scip != NULL);
1358  assert(conshdlr != NULL);
1359  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1360 
1361  /* call inclusion method of constraint handler */
1363 
1364  *valid = TRUE;
1365 
1366  return SCIP_OKAY;
1367 }
1368 
1369 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
1370 static
1371 SCIP_DECL_CONSFREE(consFreeOr)
1372 { /*lint --e{715}*/
1373  SCIP_CONSHDLRDATA* conshdlrdata;
1374 
1375  /* free constraint handler data */
1376  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1377  assert(conshdlrdata != NULL);
1378 
1379  SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
1380 
1381  SCIPconshdlrSetData(conshdlr, NULL);
1382 
1383  return SCIP_OKAY;
1384 }
1385 
1386 
1387 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
1388 static
1389 SCIP_DECL_CONSEXITSOL(consExitsolOr)
1390 { /*lint --e{715}*/
1391  SCIP_CONSDATA* consdata;
1392  int c;
1393 
1394  /* release and free the rows of all constraints */
1395  for( c = 0; c < nconss; ++c )
1396  {
1397  consdata = SCIPconsGetData(conss[c]);
1398  SCIP_CALL( consdataFreeRows(scip, consdata) );
1399  }
1400 
1401  return SCIP_OKAY;
1402 }
1403 
1404 
1405 /** frees specific constraint data */
1406 static
1407 SCIP_DECL_CONSDELETE(consDeleteOr)
1408 { /*lint --e{715}*/
1409  SCIP_CONSHDLRDATA* conshdlrdata;
1410 
1411  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1412  assert(conshdlrdata != NULL);
1413 
1414  SCIP_CALL( consdataFree(scip, consdata, conshdlrdata->eventhdlr) );
1415 
1416  return SCIP_OKAY;
1417 }
1418 
1419 
1420 /** transforms constraint data into data belonging to the transformed problem */
1421 static
1422 SCIP_DECL_CONSTRANS(consTransOr)
1423 { /*lint --e{715}*/
1424  SCIP_CONSHDLRDATA* conshdlrdata;
1425  SCIP_CONSDATA* sourcedata;
1426  SCIP_CONSDATA* targetdata;
1427 
1428  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1429  assert(conshdlrdata != NULL);
1430 
1431  sourcedata = SCIPconsGetData(sourcecons);
1432  assert(sourcedata != NULL);
1433 
1434  /* create target constraint data */
1435  SCIP_CALL( consdataCreate(scip, &targetdata, conshdlrdata->eventhdlr,
1436  sourcedata->nvars, sourcedata->vars, sourcedata->resvar) );
1437 
1438  /* create target constraint */
1439  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
1440  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
1441  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
1442  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
1443  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1444 
1445  return SCIP_OKAY;
1446 }
1447 
1448 
1449 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
1450 static
1451 SCIP_DECL_CONSINITLP(consInitlpOr)
1452 { /*lint --e{715}*/
1453  int i;
1454 
1455  *infeasible = FALSE;
1456 
1457  for( i = 0; i < nconss && !(*infeasible); i++ )
1458  {
1459  assert(SCIPconsIsInitial(conss[i]));
1460  SCIP_CALL( addRelaxation(scip, conss[i], infeasible) );
1461  }
1462 
1463  return SCIP_OKAY;
1464 }
1465 
1466 
1467 /** separation method of constraint handler for LP solutions */
1468 static
1469 SCIP_DECL_CONSSEPALP(consSepalpOr)
1470 { /*lint --e{715}*/
1471  SCIP_Bool separated;
1472  int c;
1473 
1474  *result = SCIP_DIDNOTFIND;
1475 
1476  /* separate all useful constraints */
1477  for( c = 0; c < nusefulconss; ++c )
1478  {
1479  SCIP_CALL( separateCons(scip, conss[c], NULL, &separated) );
1480  if( separated )
1481  *result = SCIP_SEPARATED;
1482  }
1483 
1484  /* combine constraints to get more cuts */
1485  /**@todo combine constraints to get further cuts */
1486 
1487  return SCIP_OKAY;
1488 }
1489 
1490 
1491 /** separation method of constraint handler for arbitrary primal solutions */
1492 static
1493 SCIP_DECL_CONSSEPASOL(consSepasolOr)
1494 { /*lint --e{715}*/
1495  SCIP_Bool separated;
1496  int c;
1497 
1498  *result = SCIP_DIDNOTFIND;
1499 
1500  /* separate all useful constraints */
1501  for( c = 0; c < nusefulconss; ++c )
1502  {
1503  SCIP_CALL( separateCons(scip, conss[c], sol, &separated) );
1504  if( separated )
1505  *result = SCIP_SEPARATED;
1506  }
1507 
1508  /* combine constraints to get more cuts */
1509  /**@todo combine constraints to get further cuts */
1510 
1511  return SCIP_OKAY;
1512 }
1513 
1514 
1515 /** constraint enforcing method of constraint handler for LP solutions */
1516 static
1517 SCIP_DECL_CONSENFOLP(consEnfolpOr)
1518 { /*lint --e{715}*/
1519  SCIP_Bool violated;
1520  int i;
1521 
1522  /* method is called only for integral solutions, because the enforcing priority is negative */
1523  for( i = 0; i < nconss; i++ )
1524  {
1525  SCIP_CALL( checkCons(scip, conss[i], NULL, FALSE, FALSE, &violated) );
1526  if( violated )
1527  {
1528  SCIP_Bool separated;
1529 
1530  SCIP_CALL( separateCons(scip, conss[i], NULL, &separated) );
1531  assert(separated); /* because the solution is integral, the separation always finds a cut */
1532  *result = SCIP_SEPARATED;
1533  return SCIP_OKAY;
1534  }
1535  }
1536  *result = SCIP_FEASIBLE;
1537 
1538  return SCIP_OKAY;
1539 }
1540 
1541 
1542 /** constraint enforcing method of constraint handler for relaxation solutions */
1543 static
1544 SCIP_DECL_CONSENFORELAX(consEnforelaxOr)
1545 { /*lint --e{715}*/
1546  SCIP_Bool violated;
1547  int i;
1548 
1549  /* method is called only for integral solutions, because the enforcing priority is negative */
1550  for( i = 0; i < nconss; i++ )
1551  {
1552  SCIP_CALL( checkCons(scip, conss[i], sol, FALSE, FALSE, &violated) );
1553  if( violated )
1554  {
1555  SCIP_Bool separated;
1556 
1557  SCIP_CALL( separateCons(scip, conss[i], sol, &separated) );
1558  assert(separated); /* because the solution is integral, the separation always finds a cut */
1559  *result = SCIP_SEPARATED;
1560  return SCIP_OKAY;
1561  }
1562  }
1563  *result = SCIP_FEASIBLE;
1564 
1565  return SCIP_OKAY;
1566 }
1567 
1568 
1569 /** constraint enforcing method of constraint handler for pseudo solutions */
1570 static
1571 SCIP_DECL_CONSENFOPS(consEnfopsOr)
1572 { /*lint --e{715}*/
1573  SCIP_Bool violated;
1574  int i;
1575 
1576  /* method is called only for integral solutions, because the enforcing priority is negative */
1577  for( i = 0; i < nconss; i++ )
1578  {
1579  SCIP_CALL( checkCons(scip, conss[i], NULL, TRUE, FALSE, &violated) );
1580  if( violated )
1581  {
1582  *result = SCIP_INFEASIBLE;
1583  return SCIP_OKAY;
1584  }
1585  }
1586  *result = SCIP_FEASIBLE;
1587 
1588  return SCIP_OKAY;
1589 }
1590 
1591 
1592 /** feasibility check method of constraint handler for integral solutions */
1593 static
1594 SCIP_DECL_CONSCHECK(consCheckOr)
1595 { /*lint --e{715}*/
1596  int i;
1597 
1598  *result = SCIP_FEASIBLE;
1599 
1600  /* method is called only for integral solutions, because the enforcing priority is negative */
1601  for( i = 0; i < nconss && (*result == SCIP_FEASIBLE || completely); i++ )
1602  {
1603  SCIP_Bool violated = FALSE;
1604 
1605  SCIP_CALL( checkCons(scip, conss[i], sol, checklprows, printreason, &violated) );
1606 
1607  if( violated )
1608  *result = SCIP_INFEASIBLE;
1609  }
1610 
1611  return SCIP_OKAY;
1612 }
1613 
1614 
1615 /** domain propagation method of constraint handler */
1616 static
1617 SCIP_DECL_CONSPROP(consPropOr)
1618 { /*lint --e{715}*/
1619  SCIP_CONSHDLRDATA* conshdlrdata;
1620  SCIP_Bool cutoff;
1621  int nfixedvars;
1622  int c;
1623 
1624  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1625  assert(conshdlrdata != NULL);
1626 
1627  cutoff = FALSE;
1628  nfixedvars = 0;
1629 
1630  /* propagate all useful constraints */
1631  for( c = 0; c < nusefulconss && !cutoff; ++c )
1632  {
1633  SCIP_CALL( propagateCons(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &nfixedvars) );
1634  }
1635 
1636  /* return the correct result */
1637  if( cutoff )
1638  *result = SCIP_CUTOFF;
1639  else if( nfixedvars > 0 )
1640  *result = SCIP_REDUCEDDOM;
1641  else
1642  *result = SCIP_DIDNOTFIND;
1643 
1644  return SCIP_OKAY;
1645 }
1646 
1647 
1648 /** presolving method of constraint handler */
1649 static
1650 SCIP_DECL_CONSPRESOL(consPresolOr)
1651 { /*lint --e{715}*/
1652  SCIP_CONSHDLRDATA* conshdlrdata;
1653  SCIP_CONS* cons;
1654  SCIP_CONSDATA* consdata;
1655  SCIP_Bool cutoff;
1656  SCIP_Bool redundant;
1657  SCIP_Bool aggregated;
1658  int oldnfixedvars;
1659  int oldnaggrvars;
1660  int oldnupgdconss;
1661  int c;
1662 
1663  assert(result != NULL);
1664 
1665  *result = SCIP_DIDNOTFIND;
1666  oldnfixedvars = *nfixedvars;
1667  oldnaggrvars = *naggrvars;
1668  oldnupgdconss = *nupgdconss;
1669 
1670  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1671  assert(conshdlrdata != NULL);
1672 
1673  /* process constraints */
1674  cutoff = FALSE;
1675  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
1676  {
1677  cons = conss[c];
1678  assert(cons != NULL);
1679  consdata = SCIPconsGetData(cons);
1680  assert(consdata != NULL);
1681 
1682  /* force presolving the constraint in the initial round */
1683  if( nrounds == 0 )
1684  consdata->propagated = FALSE;
1685 
1686  /* propagate constraint */
1687  SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars) );
1688 
1689  /* remove all variables that are fixed to one */
1690  SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr) );
1691 
1692  /* transform or constraints into and constraints on the negated variables in order to improve
1693  * the pairwise constraint presolving possibilities
1694  */
1695  SCIP_CALL( upgradeCons(scip, cons, nupgdconss) );
1696 
1697  if( !cutoff && !SCIPconsIsDeleted(cons) && !SCIPconsIsModifiable(cons) )
1698  {
1699  assert(consdata->nvars >= 1); /* otherwise, propagateCons() has deleted the constraint */
1700 
1701  /* if only one variable is left, the resultant has to be equal to this single variable */
1702  if( consdata->nvars == 1 )
1703  {
1704  SCIPdebugMsg(scip, "or constraint <%s> has only one variable not fixed to 0.0\n", SCIPconsGetName(cons));
1705 
1706  assert(consdata->vars != NULL);
1707  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->vars[0]), 0.0));
1708  assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(consdata->vars[0]), 1.0));
1709 
1710  /* aggregate variables: resultant - operand == 0 */
1711  SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, consdata->vars[0], 1.0, -1.0, 0.0,
1712  &cutoff, &redundant, &aggregated) );
1713  assert(redundant || SCIPdoNotAggr(scip));
1714 
1715  if( aggregated )
1716  {
1717  assert(redundant);
1718  (*naggrvars)++;
1719  }
1720 
1721  if( redundant )
1722  {
1723  /* delete constraint */
1724  SCIP_CALL( SCIPdelCons(scip, cons) );
1725  (*ndelconss)++;
1726  }
1727  }
1728  else if( !consdata->impladded )
1729  {
1730  int i;
1731 
1732  /* add implications: resultant == 0 -> all operands == 0 */
1733  for( i = 0; i < consdata->nvars && !cutoff; ++i )
1734  {
1735  int nimplbdchgs;
1736 
1737  SCIP_CALL( SCIPaddVarImplication(scip, consdata->resvar, FALSE, consdata->vars[i],
1738  SCIP_BOUNDTYPE_UPPER, 0.0, &cutoff, &nimplbdchgs) );
1739  *nchgbds += nimplbdchgs;
1740  }
1741  consdata->impladded = TRUE;
1742  }
1743 
1744  /* if in r = x or y, the resultant is fixed to one, add implication x = 0 -> y = 1 */
1745  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 2 && !consdata->opimpladded
1746  && SCIPvarGetLbGlobal(consdata->resvar) > 0.5 )
1747  {
1748  int nimplbdchgs;
1749 
1750  SCIP_CALL( SCIPaddVarImplication(scip, consdata->vars[0], FALSE, consdata->vars[1],
1751  SCIP_BOUNDTYPE_LOWER, 1.0, &cutoff, &nimplbdchgs) );
1752  (*nchgbds) += nimplbdchgs;
1753  consdata->opimpladded = TRUE;
1754  }
1755  }
1756  }
1757 
1758  /* return the correct result code */
1759  if( cutoff )
1760  *result = SCIP_CUTOFF;
1761  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nupgdconss > oldnupgdconss )
1762  *result = SCIP_SUCCESS;
1763 
1764  return SCIP_OKAY;
1765 }
1766 
1767 
1768 /** propagation conflict resolving method of constraint handler */
1769 static
1770 SCIP_DECL_CONSRESPROP(consRespropOr)
1771 { /*lint --e{715}*/
1772  SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, bdchgidx, result) );
1773 
1774  return SCIP_OKAY;
1775 }
1776 
1777 
1778 /** variable rounding lock method of constraint handler */
1779 static
1780 SCIP_DECL_CONSLOCK(consLockOr)
1781 { /*lint --e{715}*/
1782  SCIP_CONSDATA* consdata;
1783  int i;
1784 
1785  consdata = SCIPconsGetData(cons);
1786  assert(consdata != NULL);
1787 
1788  /* lock resultant variable */
1789  SCIP_CALL( SCIPaddVarLocks(scip, consdata->resvar, nlockspos + nlocksneg, nlockspos + nlocksneg) );
1790 
1791  /* lock all operand variables */
1792  for( i = 0; i < consdata->nvars; ++i )
1793  {
1794  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos + nlocksneg, nlockspos + nlocksneg) );
1795  }
1796 
1797  return SCIP_OKAY;
1798 }
1799 
1800 
1801 /** constraint display method of constraint handler */
1802 static
1803 SCIP_DECL_CONSPRINT(consPrintOr)
1804 { /*lint --e{715}*/
1805 
1806  assert( scip != NULL );
1807  assert( conshdlr != NULL );
1808  assert( cons != NULL );
1809 
1810  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
1811 
1812  return SCIP_OKAY;
1813 }
1814 
1815 /** constraint copying method of constraint handler */
1816 static
1817 SCIP_DECL_CONSCOPY(consCopyOr)
1818 { /*lint --e{715}*/
1819  SCIP_VAR** sourcevars;
1820  SCIP_VAR** vars;
1821  SCIP_VAR* sourceresvar;
1822  SCIP_VAR* resvar;
1823  int nvars;
1824  int v;
1825 
1826  assert(valid != NULL);
1827  (*valid) = TRUE;
1828  resvar = NULL;
1829 
1830  /* get variables that need to be copied */
1831  sourceresvar = SCIPgetResultantOr(sourcescip, sourcecons);
1832  sourcevars = SCIPgetVarsOr(sourcescip, sourcecons);
1833  nvars = SCIPgetNVarsOr(sourcescip, sourcecons);
1834 
1835  /* allocate buffer array */
1836  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
1837 
1838  /* map operand variables to active variables of the target SCIP */
1839  for( v = 0; v < nvars && *valid; ++v )
1840  {
1841  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &vars[v], varmap, consmap, global, valid) );
1842  assert(!(*valid) || vars[v] != NULL);
1843  }
1844 
1845  /* map resultant to active variable of the target SCIP */
1846  if( *valid )
1847  {
1848  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourceresvar, &resvar, varmap, consmap, global, valid) );
1849  assert(!(*valid) || resvar != NULL);
1850 
1851  if( *valid )
1852  {
1853  assert(resvar != NULL);
1854  SCIP_CALL( SCIPcreateConsOr(scip, cons, SCIPconsGetName(sourcecons), resvar, nvars, vars,
1855  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1856  }
1857  }
1858 
1859  /* free buffer array */
1860  SCIPfreeBufferArray(scip, &vars);
1861 
1862  return SCIP_OKAY;
1863 }
1864 
1865 /** constraint parsing method of constraint handler */
1866 static
1867 SCIP_DECL_CONSPARSE(consParseOr)
1868 { /*lint --e{715}*/
1869  SCIP_VAR** vars;
1870  SCIP_VAR* resvar;
1871  char* strcopy;
1872  char* token;
1873  char* saveptr;
1874  char* endptr;
1875  int requiredsize;
1876  int varssize;
1877  int nvars;
1878 
1879  SCIPdebugMsg(scip, "parse <%s> as or constraint\n", str);
1880 
1881  /* copy string for truncating it */
1882  SCIP_CALL( SCIPduplicateBufferArray(scip, &strcopy, str, (int)(strlen(str)+1)));
1883 
1884  /* cutoff "or" form the constraint string */
1885  token = SCIPstrtok(strcopy, "=", &saveptr );
1886 
1887  /* parse variable name */
1888  SCIP_CALL( SCIPparseVarName(scip, token, &resvar, &endptr) );
1889 
1890  if( resvar == NULL )
1891  {
1892  SCIPdebugMsg(scip, "resultant variable %s does not exist \n", token);
1893  *success = FALSE;
1894  }
1895  else
1896  {
1897  /* cutoff "or" form the constraint string */
1898  (void) SCIPstrtok(NULL, "(", &saveptr );
1899 
1900  /* cutoff ")" form the constraint string */
1901  token = SCIPstrtok(NULL, ")", &saveptr );
1902 
1903  varssize = 100;
1904  nvars = 0;
1905 
1906  /* allocate buffer array for variables */
1907  SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
1908 
1909  /* parse string */
1910  SCIP_CALL( SCIPparseVarsList(scip, token, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
1911 
1912  if( *success )
1913  {
1914  /* check if the size of the variable array was great enough */
1915  if( varssize < requiredsize )
1916  {
1917  /* reallocate memory */
1918  varssize = requiredsize;
1919  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
1920 
1921  /* parse string again with the correct size of the variable array */
1922  SCIP_CALL( SCIPparseVarsList(scip, token, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
1923  }
1924 
1925  assert(*success);
1926  assert(varssize >= requiredsize);
1927 
1928  /* create and constraint */
1929  SCIP_CALL( SCIPcreateConsOr(scip, cons, name, resvar, nvars, vars,
1930  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1931  }
1932 
1933  /* free variable buffer */
1934  SCIPfreeBufferArray(scip, &vars);
1935  }
1936 
1937  /* free string buffer */
1938  SCIPfreeBufferArray(scip, &strcopy);
1939 
1940  return SCIP_OKAY;
1941 }
1942 
1943 /** constraint method of constraint handler which returns the variables (if possible) */
1944 static
1945 SCIP_DECL_CONSGETVARS(consGetVarsOr)
1946 { /*lint --e{715}*/
1947  SCIP_CONSDATA* consdata;
1948 
1949  consdata = SCIPconsGetData(cons);
1950  assert(consdata != NULL);
1951 
1952  if( varssize < consdata->nvars + 1 )
1953  (*success) = FALSE;
1954  else
1955  {
1956  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
1957  vars[consdata->nvars] = consdata->resvar;
1958  (*success) = TRUE;
1959  }
1960 
1961  return SCIP_OKAY;
1962 }
1963 
1964 /** constraint method of constraint handler which returns the number of variable (if possible) */
1965 static
1966 SCIP_DECL_CONSGETNVARS(consGetNVarsOr)
1967 { /*lint --e{715}*/
1968  SCIP_CONSDATA* consdata;
1969 
1970  assert(cons != NULL);
1971 
1972  consdata = SCIPconsGetData(cons);
1973  assert(consdata != NULL);
1974 
1975  (*nvars) = consdata->nvars + 1;
1976  (*success) = TRUE;
1977 
1978  return SCIP_OKAY;
1979 }
1980 
1981 
1982 /*
1983  * Callback methods of event handler
1984  */
1985 
1986 static
1987 SCIP_DECL_EVENTEXEC(eventExecOr)
1988 { /*lint --e{715}*/
1989  SCIP_CONSDATA* consdata;
1990 
1991  assert(eventhdlr != NULL);
1992  assert(eventdata != NULL);
1993  assert(event != NULL);
1994 
1995  consdata = (SCIP_CONSDATA*)eventdata;
1996  assert(consdata != NULL);
1997 
1998  /* check, if the variable was fixed to one */
2000  consdata->nofixedone = FALSE;
2001 
2002  consdata->propagated = FALSE;
2003 
2004  return SCIP_OKAY;
2005 }
2006 
2007 
2008 /*
2009  * constraint specific interface methods
2010  */
2011 
2012 /** creates the handler for or constraints and includes it in SCIP */
2014  SCIP* scip /**< SCIP data structure */
2015  )
2016 {
2017  SCIP_CONSHDLRDATA* conshdlrdata;
2018  SCIP_CONSHDLR* conshdlr;
2019  SCIP_EVENTHDLR* eventhdlr;
2020 
2021  /* create event handler for events on variables */
2023  eventExecOr, NULL) );
2024 
2025  /* create constraint handler data */
2026  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
2027 
2028  /* include constraint handler */
2031  consEnfolpOr, consEnfopsOr, consCheckOr, consLockOr,
2032  conshdlrdata) );
2033  assert(conshdlr != NULL);
2034 
2035  /* set non-fundamental callbacks via specific setter functions */
2036  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOr, consCopyOr) );
2037  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOr) );
2038  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolOr) );
2039  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeOr) );
2040  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsOr) );
2041  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsOr) );
2042  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpOr) );
2043  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseOr) );
2045  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOr) );
2046  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropOr, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
2048  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOr) );
2049  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOr, consSepasolOr, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY,
2050  CONSHDLR_DELAYSEPA) );
2051  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOr) );
2052  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxOr) );
2053 
2054  return SCIP_OKAY;
2055 }
2056 
2057 /** creates and captures an or constraint
2058  *
2059  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2060  */
2062  SCIP* scip, /**< SCIP data structure */
2063  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2064  const char* name, /**< name of constraint */
2065  SCIP_VAR* resvar, /**< resultant variable of the operation */
2066  int nvars, /**< number of operator variables in the constraint */
2067  SCIP_VAR** vars, /**< array with operator variables of constraint */
2068  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2069  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2070  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2071  * Usually set to TRUE. */
2072  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2073  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2074  SCIP_Bool check, /**< should the constraint be checked for feasibility?
2075  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2076  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2077  * Usually set to TRUE. */
2078  SCIP_Bool local, /**< is constraint only valid locally?
2079  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2080  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
2081  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
2082  * adds coefficients to this constraint. */
2083  SCIP_Bool dynamic, /**< is constraint subject to aging?
2084  * Usually set to FALSE. Set to TRUE for own cuts which
2085  * are separated as constraints. */
2086  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2087  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2088  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2089  * if it may be moved to a more global node?
2090  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2091  )
2092 {
2093  SCIP_CONSHDLR* conshdlr;
2094  SCIP_CONSHDLRDATA* conshdlrdata;
2095  SCIP_CONSDATA* consdata;
2096 
2097  /* find the or constraint handler */
2098  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2099  if( conshdlr == NULL )
2100  {
2101  SCIPerrorMessage("or constraint handler not found\n");
2102  return SCIP_PLUGINNOTFOUND;
2103  }
2104 
2105  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2106  assert(conshdlrdata != NULL);
2107 
2108  /* create constraint data */
2109  SCIP_CALL( consdataCreate(scip, &consdata, conshdlrdata->eventhdlr, nvars, vars, resvar) );
2110 
2111  /* create constraint */
2112  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
2113  local, modifiable, dynamic, removable, stickingatnode) );
2114 
2115  return SCIP_OKAY;
2116 }
2117 
2118 /** creates and captures an or constraint
2119  * in its most basic variant, i. e., with all constraint flags set to their default values
2120  *
2121  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2122  */
2124  SCIP* scip, /**< SCIP data structure */
2125  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2126  const char* name, /**< name of constraint */
2127  SCIP_VAR* resvar, /**< resultant variable of the operation */
2128  int nvars, /**< number of operator variables in the constraint */
2129  SCIP_VAR** vars /**< array with operator variables of constraint */
2130  )
2131 {
2132  SCIP_CALL( SCIPcreateConsOr(scip, cons, name, resvar, nvars, vars, TRUE, TRUE, TRUE, TRUE, TRUE,
2133  FALSE, FALSE, FALSE, FALSE, FALSE) );
2134 
2135  return SCIP_OKAY;
2136 }
2137 
2138 /** gets number of variables in or constraint */
2139 int SCIPgetNVarsOr(
2140  SCIP* scip, /**< SCIP data structure */
2141  SCIP_CONS* cons /**< constraint data */
2142  )
2143 {
2144  SCIP_CONSDATA* consdata;
2145 
2146  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2147  {
2148  SCIPerrorMessage("constraint is not an or constraint\n");
2149  SCIPABORT();
2150  return -1; /*lint !e527*/
2151  }
2152 
2153  consdata = SCIPconsGetData(cons);
2154  assert(consdata != NULL);
2155 
2156  return consdata->nvars;
2157 }
2158 
2159 /** gets array of variables in or constraint */
2161  SCIP* scip, /**< SCIP data structure */
2162  SCIP_CONS* cons /**< constraint data */
2163  )
2164 {
2165  SCIP_CONSDATA* consdata;
2166 
2167  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2168  {
2169  SCIPerrorMessage("constraint is not an or constraint\n");
2170  SCIPABORT();
2171  return NULL; /*lint !e527*/
2172  }
2173 
2174  consdata = SCIPconsGetData(cons);
2175  assert(consdata != NULL);
2176 
2177  return consdata->vars;
2178 }
2179 
2180 /** gets the resultant variable in or constraint */
2182  SCIP* scip, /**< SCIP data structure */
2183  SCIP_CONS* cons /**< constraint data */
2184  )
2185 {
2186  SCIP_CONSDATA* consdata;
2187 
2188  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2189  {
2190  SCIPerrorMessage("constraint is not a or constraint\n");
2191  SCIPABORT();
2192  return NULL; /*lint !e527*/
2193  }
2194 
2195  consdata = SCIPconsGetData(cons);
2196  assert(consdata != NULL);
2197 
2198  return consdata->resvar;
2199 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define CONSHDLR_DELAYSEPA
Definition: cons_or.c:54
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21909
SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
Definition: scip.c:30360
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4143
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:27934
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:21898
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:6228
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip.c:40508
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_or.c:557
static SCIP_RETCODE conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_or.c:164
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21892
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool *violated)
Definition: cons_or.c:751
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19263
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46086
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:814
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_or.c:717
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8140
static SCIP_RETCODE consdataCatchWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int *filterpos)
Definition: cons_or.c:190
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:6251
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition: scip.c:18733
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_or.c:478
static SCIP_DECL_CONSLOCK(consLockOr)
Definition: cons_or.c:1781
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19123
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_or.c:130
static SCIP_DECL_CONSINITLP(consInitlpOr)
Definition: cons_or.c:1452
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:40275
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6541
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17166
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:6481
#define SCIP_MAXSTRLEN
Definition: def.h:215
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip.c:5973
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:27962
#define EVENTHDLR_NAME
Definition: cons_or.c:61
#define CONSHDLR_EAGERFREQ
Definition: cons_or.c:50
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12481
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:45601
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30288
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17222
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:26950
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8526
static SCIP_RETCODE upgradeCons(SCIP *scip, SCIP_CONS *cons, int *nupgdconss)
Definition: cons_or.c:1298
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:18575
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip.c:17656
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16732
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:46175
#define FALSE
Definition: def.h:64
static SCIP_RETCODE consdataDropWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int filterpos)
Definition: cons_or.c:214
static SCIP_RETCODE consdataSwitchWatchedvars(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
Definition: cons_or.c:289
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:5831
SCIP_RETCODE SCIPcreateConsBasicOr(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars)
Definition: cons_or.c:2124
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:45816
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
static SCIP_DECL_CONSCHECK(consCheckOr)
Definition: cons_or.c:1595
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_or.c:144
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
enum Proprule PROPRULE
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:21255
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8160
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
Definition: cons_or.c:1212
static SCIP_DECL_CONSPROP(consPropOr)
Definition: cons_or.c:1618
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8190
static SCIP_DECL_CONSSEPALP(consSepalpOr)
Definition: cons_or.c:1470
static SCIP_DECL_CONSPARSE(consParseOr)
Definition: cons_or.c:1868
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:26717
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:21907
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:5885
Constraint handler for AND constraints, .
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:21933
enum Proprule PROPRULE
Definition: cons_or.c:107
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:21937
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:21890
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1010
static SCIP_DECL_CONSENFOPS(consEnfopsOr)
Definition: cons_or.c:1572
#define CONSHDLR_ENFOPRIORITY
Definition: cons_or.c:46
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8150
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:108
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:6274
#define SCIPdebugMsgPrint
Definition: scip.h:452
#define SCIPdebugMsg
Definition: scip.h:451
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:18616
SCIP_RETCODE SCIPcreateConsOr(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, 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_or.c:2062
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:6458
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:7942
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1336
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:27146
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:16522
#define CONSHDLR_MAXPREROUNDS
Definition: cons_or.c:53
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:64
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:26695
static SCIP_RETCODE createRelaxation(SCIP *scip, SCIP_CONS *cons)
Definition: cons_or.c:674
Constraint handler for "or" constraints, .
#define CONSHDLR_SEPAPRIORITY
Definition: cons_or.c:45
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17176
static SCIP_DECL_CONSCOPY(consCopyOr)
Definition: cons_or.c:1818
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:21904
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr, int nvars, SCIP_VAR **vars, SCIP_VAR *resvar)
Definition: cons_or.c:373
SCIP_RETCODE SCIPparseVarsList(SCIP *scip, const char *str, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize, char **endptr, char delimiter, SCIP_Bool *success)
Definition: scip.c:17733
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:5997
static SCIP_RETCODE consdataCatchEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_or.c:237
SCIP_RETCODE SCIPcreateConsAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, 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_and.c:4948
#define CONSHDLR_NAME
Definition: cons_or.c:43
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
#define CONSHDLR_DELAYPROP
Definition: cons_or.c:55
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12410
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:13111
SCIP_RETCODE SCIPaddVarImplication(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:23687
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21383
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7881
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8100
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16552
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:6022
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4133
#define NULL
Definition: lpi_spx1.cpp:137
static SCIP_DECL_CONSPRESOL(consPresolOr)
Definition: cons_or.c:1651
static SCIP_DECL_CONSPRINT(consPrintOr)
Definition: cons_or.c:1804
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:66
#define CONSHDLR_CHECKPRIORITY
Definition: cons_or.c:47
#define SCIP_CALL(x)
Definition: def.h:306
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:63
static SCIP_DECL_CONSFREE(consFreeOr)
Definition: cons_or.c:1372
static SCIP_DECL_CONSGETVARS(consGetVarsOr)
Definition: cons_or.c:1946
SCIP_VAR ** SCIPgetVarsOr(SCIP *scip, SCIP_CONS *cons)
Definition: cons_or.c:2161
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:27097
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8120
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOr)
Definition: cons_or.c:1356
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:6297
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:33869
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
#define CONSHDLR_PRESOLTIMING
Definition: cons_or.c:59
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21925
public data structures and miscellaneous methods
static int consdataGetNRows(SCIP_CONSDATA *consdata)
Definition: cons_or.c:179
#define SCIP_Bool
Definition: def.h:61
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
int SCIPgetNVarsOr(SCIP *scip, SCIP_CONS *cons)
Definition: cons_or.c:2140
#define EVENTHDLR_DESC
Definition: cons_or.c:62
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:30022
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:28652
static SCIP_DECL_CONSENFORELAX(consEnforelaxOr)
Definition: cons_or.c:1545
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7901
static SCIP_RETCODE consdataDropEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_or.c:263
static SCIP_DECL_CONSSEPASOL(consSepasolOr)
Definition: cons_or.c:1494
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8010
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8080
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8050
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:40321
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *separated)
Definition: cons_or.c:850
static SCIP_DECL_CONSDELETE(consDeleteOr)
Definition: cons_or.c:1408
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21309
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:6435
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
static SCIP_DECL_EVENTEXEC(eventExecOr)
Definition: cons_or.c:1988
Proprule
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:35033
static SCIP_RETCODE consdataFreeRows(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_or.c:417
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_or.c:444
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_or.c:973
#define CONSHDLR_DESC
Definition: cons_or.c:44
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30160
SCIP_RETCODE SCIPwriteVarsList(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_Bool type, char delimiter)
Definition: scip.c:17415
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1911
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7911
SCIP_VAR * SCIPgetResultantOr(SCIP *scip, SCIP_CONS *cons)
Definition: cons_or.c:2182
static SCIP_DECL_CONSRESPROP(consRespropOr)
Definition: cons_or.c:1771
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27323
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_or.c:116
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:6190
static SCIP_DECL_CONSEXITSOL(consExitsolOr)
Definition: cons_or.c:1390
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
Definition: cons_or.c:503
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip.c:25250
#define SCIP_Real
Definition: def.h:135
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8130
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1138
static SCIP_DECL_CONSTRANS(consTransOr)
Definition: cons_or.c:1423
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:6504
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8070
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip.c:25414
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8060
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:30736
#define CONSHDLR_NEEDSCONS
Definition: cons_or.c:56
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_or.c:349
#define CONSHDLR_PROP_TIMING
Definition: cons_or.c:58
static SCIP_RETCODE analyzeConflictZero(SCIP *scip, SCIP_CONS *cons, int truepos)
Definition: cons_or.c:900
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
SCIP_RETCODE SCIPincludeConshdlrOr(SCIP *scip)
Definition: cons_or.c:2014
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17232
static SCIP_RETCODE analyzeConflictOne(SCIP *scip, SCIP_CONS *cons)
Definition: cons_or.c:932
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:46187
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16694
#define CONSHDLR_PROPFREQ
Definition: cons_or.c:49
static SCIP_DECL_CONSENFOLP(consEnfolpOr)
Definition: cons_or.c:1518
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_or.c:615
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:6118
#define SCIPABORT()
Definition: def.h:278
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip.c:17353
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:9298
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38007
SCIP_RETCODE SCIPinferBinvarCons(SCIP *scip, SCIP_VAR *var, SCIP_Bool fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22634
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:18663
static SCIP_DECL_CONSGETNVARS(consGetNVarsOr)
Definition: cons_or.c:1967
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:21929
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5931
#define CONSHDLR_SEPAFREQ
Definition: cons_or.c:48