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-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_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( SCIPaddRow(scip, 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  /* update constraint violation in solution */
826  else
827  SCIPupdateSolConsViolation(scip, sol, 1.0, 1.0);
828 
829  if( printreason )
830  {
831  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
832  SCIPinfoMessage(scip, NULL, ";\nviolation:\n");
833  if( i == consdata->nvars )
834  {
835  SCIPinfoMessage(scip, NULL, " all operands are FALSE and resultant <%s> = TRUE\n",
836  SCIPvarGetName(consdata->resvar));
837  }
838  else
839  {
840  SCIPinfoMessage(scip, NULL, " operand <%s> = TRUE and resultant <%s> = FALSE\n",
841  SCIPvarGetName(consdata->vars[i-1]), SCIPvarGetName(consdata->resvar));
842  }
843  }
844  }
845  }
846 
847  return SCIP_OKAY;
848 }
849 
850 /** separates current LP solution */
851 static
853  SCIP* scip, /**< SCIP data structure */
854  SCIP_CONS* cons, /**< constraint to check */
855  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
856  SCIP_Bool* separated /**< pointer to store whether a cut was found */
857  )
858 {
859  SCIP_CONSDATA* consdata;
860  SCIP_Real feasibility;
861  int r;
862  int nrows;
863 
864  assert(separated != NULL);
865 
866  consdata = SCIPconsGetData(cons);
867  assert(consdata != NULL);
868 
869  *separated = FALSE;
870 
871  /* create all necessary rows for the linear relaxation */
872  if( consdata->rows == NULL )
873  {
874  SCIP_CALL( createRelaxation(scip, cons) );
875  }
876  assert(consdata->rows != NULL);
877 
878  nrows = consdataGetNRows(consdata);
879 
880  /* test all rows for feasibility and add infeasible rows */
881  for( r = 0; r < nrows; ++r )
882  {
883  if( !SCIProwIsInLP(consdata->rows[r]) )
884  {
885  feasibility = SCIPgetRowSolFeasibility(scip, consdata->rows[r], sol);
886  if( SCIPisFeasNegative(scip, feasibility) )
887  {
888  SCIP_Bool infeasible;
889 
890  SCIP_CALL( SCIPaddRow(scip, consdata->rows[r], FALSE, &infeasible) );
891  assert( ! infeasible );
892  *separated = TRUE;
893  }
894  }
895  }
896 
897  return SCIP_OKAY;
898 }
899 
900 /** analyzes conflicting FALSE assignment to resultant of given constraint, and adds conflict constraint to problem */
901 static
903  SCIP* scip, /**< SCIP data structure */
904  SCIP_CONS* cons, /**< or constraint that detected the conflict */
905  int truepos /**< position of operand that is fixed to TRUE */
906  )
907 {
908  SCIP_CONSDATA* consdata;
909 
910  /* conflict analysis can only be applied in solving stage and if it is applicable */
912  return SCIP_OKAY;
913 
914  consdata = SCIPconsGetData(cons);
915  assert(consdata != NULL);
916  assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
917  assert(0 <= truepos && truepos < consdata->nvars);
918  assert(SCIPvarGetLbLocal(consdata->vars[truepos]) > 0.5);
919 
920  /* initialize conflict analysis, and add resultant and single operand variable to conflict candidate queue */
922 
923  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
924  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[truepos]) );
925 
926  /* analyze the conflict */
927  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
928 
929  return SCIP_OKAY;
930 }
931 
932 /** analyzes conflicting TRUE assignment to resultant of given constraint, and adds conflict constraint to problem */
933 static
935  SCIP* scip, /**< SCIP data structure */
936  SCIP_CONS* cons /**< or constraint that detected the conflict */
937  )
938 {
939  SCIP_CONSDATA* consdata;
940  int v;
941 
942  assert(!SCIPconsIsModifiable(cons));
943 
944  /* conflict analysis can only be applied in solving stage and if it is applicable */
946  return SCIP_OKAY;
947 
948  consdata = SCIPconsGetData(cons);
949  assert(consdata != NULL);
950  assert(SCIPvarGetLbLocal(consdata->resvar) > 0.5);
951 
952  /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
954 
955  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
956  for( v = 0; v < consdata->nvars; ++v )
957  {
958  assert(SCIPvarGetUbLocal(consdata->vars[v]) < 0.5);
959  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
960  }
961 
962  /* analyze the conflict */
963  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
964 
965  return SCIP_OKAY;
966 }
967 
968 /** propagates constraint with the following rules:
969  * (1) v_i = TRUE => r = TRUE
970  * (2) r = FALSE => v_i = FALSE for all i
971  * (3) v_i = FALSE for all i => r = FALSE
972  * (4) r = TRUE, v_i = FALSE for all i except j => v_j = TRUE
973  */
974 static
976  SCIP* scip, /**< SCIP data structure */
977  SCIP_CONS* cons, /**< or constraint to be processed */
978  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
979  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
980  int* nfixedvars /**< pointer to add up the number of found domain reductions */
981  )
982 {
983  SCIP_CONSDATA* consdata;
984  SCIP_VAR* resvar;
985  SCIP_VAR** vars;
986  int nvars;
987  int watchedvar1;
988  int watchedvar2;
989  int i;
990  SCIP_Bool infeasible;
991  SCIP_Bool tightened;
992 
993  assert(cutoff != NULL);
994  assert(nfixedvars != NULL);
995 
996  consdata = SCIPconsGetData(cons);
997  assert(consdata != NULL);
998 
999  resvar = consdata->resvar;
1000  vars = consdata->vars;
1001  nvars = consdata->nvars;
1002 
1003  /* don't process the constraint, if none of the operator variables was fixed to TRUE, and if the watched variables
1004  * and the resultant weren't fixed to any value since last propagation call
1005  */
1006  if( consdata->propagated )
1007  {
1008  assert(consdata->nofixedone);
1009  assert(SCIPisFeasEQ(scip, SCIPvarGetUbLocal(resvar), 1.0));
1010  return SCIP_OKAY;
1011  }
1012 
1013  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
1014  if( !SCIPinRepropagation(scip) )
1015  {
1016  SCIP_CALL( SCIPincConsAge(scip, cons) );
1017  }
1018 
1019  /* if one of the operator variables was fixed to TRUE, the resultant can be fixed to TRUE (rule (1)) */
1020  if( !consdata->nofixedone )
1021  {
1022  for( i = 0; i < nvars && SCIPvarGetLbLocal(vars[i]) < 0.5; ++i ) /* search fixed operator */
1023  {}
1024  if( i < nvars )
1025  {
1026  SCIPdebugMsg(scip, "constraint <%s>: operator var <%s> fixed to 1.0 -> fix resultant <%s> to 1.0\n",
1027  SCIPconsGetName(cons), SCIPvarGetName(vars[i]), SCIPvarGetName(resvar));
1028  SCIP_CALL( SCIPinferBinvarCons(scip, resvar, TRUE, cons, (int)PROPRULE_1, &infeasible, &tightened) );
1029  if( infeasible )
1030  {
1031  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1032  SCIP_CALL( analyzeConflictZero(scip, cons, i) );
1033  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1034  *cutoff = TRUE;
1035  }
1036  else
1037  {
1038  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1039  if( tightened )
1040  {
1041  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1042  (*nfixedvars)++;
1043  }
1044  }
1045 
1046  return SCIP_OKAY;
1047  }
1048  else
1049  consdata->nofixedone = TRUE;
1050  }
1051  assert(consdata->nofixedone);
1052 
1053  /* if resultant is fixed to FALSE, all operator variables can be fixed to FALSE (rule (2)) */
1054  if( SCIPvarGetUbLocal(resvar) < 0.5 )
1055  {
1056  for( i = 0; i < nvars && !(*cutoff); ++i )
1057  {
1058  SCIPdebugMsg(scip, "constraint <%s>: resultant var <%s> fixed to 0.0 -> fix operator var <%s> to 0.0\n",
1059  SCIPconsGetName(cons), SCIPvarGetName(resvar), SCIPvarGetName(vars[i]));
1060  SCIP_CALL( SCIPinferBinvarCons(scip, vars[i], FALSE, cons, (int)PROPRULE_2, &infeasible, &tightened) );
1061  if( infeasible )
1062  {
1063  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1064  SCIP_CALL( analyzeConflictZero(scip, cons, i) );
1065  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1066  *cutoff = TRUE;
1067  }
1068  else if( tightened )
1069  {
1070  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1071  (*nfixedvars)++;
1072  }
1073  }
1074 
1075  if( !(*cutoff) )
1076  {
1077  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1078  }
1079 
1080  return SCIP_OKAY;
1081  }
1082 
1083  /* rules (3) and (4) can only be applied, if we know all operator variables */
1084  if( SCIPconsIsModifiable(cons) )
1085  return SCIP_OKAY;
1086 
1087  /* rules (3) and (4) cannot be applied, if we have at least two unfixed variables left;
1088  * that means, we only have to watch (i.e. capture events) of two variables, and switch to other variables
1089  * if these ones get fixed
1090  */
1091  watchedvar1 = consdata->watchedvar1;
1092  watchedvar2 = consdata->watchedvar2;
1093 
1094  /* check, if watched variables are still unfixed */
1095  if( watchedvar1 != -1 )
1096  {
1097  assert(SCIPvarGetLbLocal(vars[watchedvar1]) < 0.5); /* otherwise, rule (1) could be applied */
1098  if( SCIPvarGetUbLocal(vars[watchedvar1]) < 0.5 )
1099  watchedvar1 = -1;
1100  }
1101  if( watchedvar2 != -1 )
1102  {
1103  assert(SCIPvarGetLbLocal(vars[watchedvar2]) < 0.5); /* otherwise, rule (1) could be applied */
1104  if( SCIPvarGetUbLocal(vars[watchedvar2]) < 0.5 )
1105  watchedvar2 = -1;
1106  }
1107 
1108  /* if only one watched variable is still unfixed, make it the first one */
1109  if( watchedvar1 == -1 )
1110  {
1111  watchedvar1 = watchedvar2;
1112  watchedvar2 = -1;
1113  }
1114  assert(watchedvar1 != -1 || watchedvar2 == -1);
1115 
1116  /* if the watched variables are invalid (fixed), find new ones if existing */
1117  if( watchedvar2 == -1 )
1118  {
1119  for( i = 0; i < nvars; ++i )
1120  {
1121  assert(SCIPvarGetLbLocal(vars[i]) < 0.5); /* otherwise, rule (1) could be applied */
1122  if( SCIPvarGetUbLocal(vars[i]) > 0.5 )
1123  {
1124  if( watchedvar1 == -1 )
1125  {
1126  assert(watchedvar2 == -1);
1127  watchedvar1 = i;
1128  }
1129  else if( watchedvar1 != i )
1130  {
1131  watchedvar2 = i;
1132  break;
1133  }
1134  }
1135  }
1136  }
1137  assert(watchedvar1 != -1 || watchedvar2 == -1);
1138 
1139  /* if all variables are fixed to FALSE, the resultant can also be fixed to FALSE (rule (3)) */
1140  if( watchedvar1 == -1 )
1141  {
1142  assert(watchedvar2 == -1);
1143 
1144  SCIPdebugMsg(scip, "constraint <%s>: all operator vars fixed to 0.0 -> fix resultant <%s> to 0.0\n",
1145  SCIPconsGetName(cons), SCIPvarGetName(resvar));
1146  SCIP_CALL( SCIPinferBinvarCons(scip, resvar, FALSE, cons, (int)PROPRULE_3, &infeasible, &tightened) );
1147  if( infeasible )
1148  {
1149  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1150  SCIP_CALL( analyzeConflictOne(scip, cons) );
1151  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1152  *cutoff = TRUE;
1153  }
1154  else
1155  {
1156  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1157  if( tightened )
1158  {
1159  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1160  (*nfixedvars)++;
1161  }
1162  }
1163 
1164  return SCIP_OKAY;
1165  }
1166 
1167  /* if resultant is fixed to TRUE, and only one operator variable is not fixed to FALSE, this operator variable
1168  * can be fixed to TRUE (rule (4))
1169  */
1170  if( SCIPvarGetLbLocal(resvar) > 0.5 && watchedvar2 == -1 )
1171  {
1172  assert(watchedvar1 != -1);
1173 
1174  SCIPdebugMsg(scip, "constraint <%s>: resultant <%s> fixed to 1.0, only one unfixed operand -> fix operand <%s> to 1.0\n",
1175  SCIPconsGetName(cons), SCIPvarGetName(resvar), SCIPvarGetName(vars[watchedvar1]));
1176  SCIP_CALL( SCIPinferBinvarCons(scip, vars[watchedvar1], TRUE, cons, (int)PROPRULE_4, &infeasible, &tightened) );
1177  if( infeasible )
1178  {
1179  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1180  SCIP_CALL( analyzeConflictOne(scip, cons) );
1181  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1182  *cutoff = TRUE;
1183  }
1184  else
1185  {
1186  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1187  if( tightened )
1188  {
1189  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1190  (*nfixedvars)++;
1191  }
1192  }
1193 
1194  return SCIP_OKAY;
1195  }
1196 
1197  /* switch to the new watched variables */
1198  SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, watchedvar1, watchedvar2) );
1199 
1200  /* mark the constraint propagated */
1201  consdata->propagated = TRUE;
1202 
1203  return SCIP_OKAY;
1204 }
1205 
1206 /** resolves a conflict on the given variable by supplying the variables needed for applying the corresponding
1207  * propagation rule (see propagateCons()):
1208  * (1) v_i = TRUE => r = TRUE
1209  * (2) r = FALSE => v_i = FALSE for all i
1210  * (3) v_i = FALSE for all i => r = FALSE
1211  * (4) r = TRUE, v_i = FALSE for all i except j => v_j = TRUE
1212  */
1213 static
1215  SCIP* scip, /**< SCIP data structure */
1216  SCIP_CONS* cons, /**< constraint that inferred the bound change */
1217  SCIP_VAR* infervar, /**< variable that was deduced */
1218  PROPRULE proprule, /**< propagation rule that deduced the value */
1219  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1220  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
1221  )
1222 {
1223  SCIP_CONSDATA* consdata;
1224  SCIP_VAR** vars;
1225  int nvars;
1226  int i;
1227 
1228  assert(result != NULL);
1229 
1230  consdata = SCIPconsGetData(cons);
1231  assert(consdata != NULL);
1232  vars = consdata->vars;
1233  nvars = consdata->nvars;
1234 
1235  switch( proprule )
1236  {
1237  case PROPRULE_1:
1238  /* the resultant was infered to TRUE, because one operand variable was TRUE */
1239  assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
1240  assert(infervar == consdata->resvar);
1241  for( i = 0; i < nvars; ++i )
1242  {
1243  if( SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) > 0.5 )
1244  {
1245  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
1246  break;
1247  }
1248  }
1249  assert(i < nvars);
1250  *result = SCIP_SUCCESS;
1251  break;
1252 
1253  case PROPRULE_2:
1254  /* the operand variable was infered to FALSE, because the resultant was FALSE */
1255  assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
1256  assert(SCIPgetVarUbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) < 0.5);
1257  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1258  *result = SCIP_SUCCESS;
1259  break;
1260 
1261  case PROPRULE_3:
1262  /* the resultant was infered to FALSE, because all operand variables were FALSE */
1263  assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
1264  assert(infervar == consdata->resvar);
1265  for( i = 0; i < nvars; ++i )
1266  {
1267  assert(SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5);
1268  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
1269  }
1270  *result = SCIP_SUCCESS;
1271  break;
1272 
1273  case PROPRULE_4:
1274  /* the operand variable was infered to TRUE, because the resultant was TRUE and all other operands were FALSE */
1275  assert(SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5);
1276  assert(SCIPgetVarLbAtIndex(scip, consdata->resvar, bdchgidx, FALSE) > 0.5);
1277  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1278  for( i = 0; i < nvars; ++i )
1279  {
1280  if( vars[i] != infervar )
1281  {
1282  assert(SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) < 0.5);
1283  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
1284  }
1285  }
1286  *result = SCIP_SUCCESS;
1287  break;
1288 
1289  case PROPRULE_INVALID:
1290  default:
1291  SCIPerrorMessage("invalid inference information %d in or constraint <%s>\n", proprule, SCIPconsGetName(cons));
1292  return SCIP_INVALIDDATA;
1293  }
1294 
1295  return SCIP_OKAY;
1296 }
1297 
1298 /** upgrades unmodifiable or constraint into an and constraint on negated variables */
1299 static
1301  SCIP* scip, /**< SCIP data structure */
1302  SCIP_CONS* cons, /**< constraint that inferred the bound change */
1303  int* nupgdconss /**< pointer to count the number of constraint upgrades */
1304  )
1305 {
1306  SCIP_CONSDATA* consdata;
1307  SCIP_VAR** negvars;
1308  SCIP_VAR* negresvar;
1309  SCIP_CONS* andcons;
1310  int i;
1311 
1312  assert(nupgdconss != NULL);
1313 
1314  /* we cannot upgrade a modifiable constraint, since we don't know what additional variables to expect */
1315  if( SCIPconsIsModifiable(cons) )
1316  return SCIP_OKAY;
1317 
1318  SCIPdebugMsg(scip, "upgrading or constraint <%s> into equivalent and constraint on negated variables\n",
1319  SCIPconsGetName(cons));
1320 
1321  consdata = SCIPconsGetData(cons);
1322  assert(consdata != NULL);
1323 
1324  /* get the negated versions of the variables */
1325  SCIP_CALL( SCIPallocBufferArray(scip, &negvars, consdata->nvars) );
1326  for( i = 0; i < consdata->nvars; ++i )
1327  {
1328  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[i], &negvars[i]) );
1329  }
1330  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->resvar, &negresvar) );
1331 
1332  /* create and add the and constraint */
1333  SCIP_CALL( SCIPcreateConsAnd(scip, &andcons, SCIPconsGetName(cons), negresvar, consdata->nvars, negvars,
1337  SCIP_CALL( SCIPaddCons(scip, andcons) );
1338  SCIP_CALL( SCIPreleaseCons(scip, &andcons) );
1339 
1340  /* delete the or constraint */
1341  SCIP_CALL( SCIPdelCons(scip, cons) );
1342 
1343  /* free temporary memory */
1344  SCIPfreeBufferArray(scip, &negvars);
1345 
1346  (*nupgdconss)++;
1347 
1348  return SCIP_OKAY;
1349 }
1350 
1351 
1352 /*
1353  * Callback methods of constraint handler
1354  */
1355 
1356 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1357 static
1358 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOr)
1359 { /*lint --e{715}*/
1360  assert(scip != NULL);
1361  assert(conshdlr != NULL);
1362  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1363 
1364  /* call inclusion method of constraint handler */
1366 
1367  *valid = TRUE;
1368 
1369  return SCIP_OKAY;
1370 }
1371 
1372 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
1373 static
1374 SCIP_DECL_CONSFREE(consFreeOr)
1375 { /*lint --e{715}*/
1376  SCIP_CONSHDLRDATA* conshdlrdata;
1377 
1378  /* free constraint handler data */
1379  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1380  assert(conshdlrdata != NULL);
1381 
1382  SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
1383 
1384  SCIPconshdlrSetData(conshdlr, NULL);
1385 
1386  return SCIP_OKAY;
1387 }
1388 
1389 
1390 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
1391 static
1392 SCIP_DECL_CONSEXITSOL(consExitsolOr)
1393 { /*lint --e{715}*/
1394  SCIP_CONSDATA* consdata;
1395  int c;
1396 
1397  /* release and free the rows of all constraints */
1398  for( c = 0; c < nconss; ++c )
1399  {
1400  consdata = SCIPconsGetData(conss[c]);
1401  SCIP_CALL( consdataFreeRows(scip, consdata) );
1402  }
1403 
1404  return SCIP_OKAY;
1405 }
1406 
1407 
1408 /** frees specific constraint data */
1409 static
1410 SCIP_DECL_CONSDELETE(consDeleteOr)
1411 { /*lint --e{715}*/
1412  SCIP_CONSHDLRDATA* conshdlrdata;
1413 
1414  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1415  assert(conshdlrdata != NULL);
1416 
1417  SCIP_CALL( consdataFree(scip, consdata, conshdlrdata->eventhdlr) );
1418 
1419  return SCIP_OKAY;
1420 }
1421 
1422 
1423 /** transforms constraint data into data belonging to the transformed problem */
1424 static
1425 SCIP_DECL_CONSTRANS(consTransOr)
1426 { /*lint --e{715}*/
1427  SCIP_CONSHDLRDATA* conshdlrdata;
1428  SCIP_CONSDATA* sourcedata;
1429  SCIP_CONSDATA* targetdata;
1430 
1431  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1432  assert(conshdlrdata != NULL);
1433 
1434  sourcedata = SCIPconsGetData(sourcecons);
1435  assert(sourcedata != NULL);
1436 
1437  /* create target constraint data */
1438  SCIP_CALL( consdataCreate(scip, &targetdata, conshdlrdata->eventhdlr,
1439  sourcedata->nvars, sourcedata->vars, sourcedata->resvar) );
1440 
1441  /* create target constraint */
1442  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
1443  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
1444  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
1445  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
1446  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1447 
1448  return SCIP_OKAY;
1449 }
1450 
1451 
1452 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
1453 static
1454 SCIP_DECL_CONSINITLP(consInitlpOr)
1455 { /*lint --e{715}*/
1456  int i;
1457 
1458  *infeasible = FALSE;
1459 
1460  for( i = 0; i < nconss && !(*infeasible); i++ )
1461  {
1462  assert(SCIPconsIsInitial(conss[i]));
1463  SCIP_CALL( addRelaxation(scip, conss[i], infeasible) );
1464  }
1465 
1466  return SCIP_OKAY;
1467 }
1468 
1469 
1470 /** separation method of constraint handler for LP solutions */
1471 static
1472 SCIP_DECL_CONSSEPALP(consSepalpOr)
1473 { /*lint --e{715}*/
1474  SCIP_Bool separated;
1475  int c;
1476 
1477  *result = SCIP_DIDNOTFIND;
1478 
1479  /* separate all useful constraints */
1480  for( c = 0; c < nusefulconss; ++c )
1481  {
1482  SCIP_CALL( separateCons(scip, conss[c], NULL, &separated) );
1483  if( separated )
1484  *result = SCIP_SEPARATED;
1485  }
1486 
1487  /* combine constraints to get more cuts */
1488  /**@todo combine constraints to get further cuts */
1489 
1490  return SCIP_OKAY;
1491 }
1492 
1493 
1494 /** separation method of constraint handler for arbitrary primal solutions */
1495 static
1496 SCIP_DECL_CONSSEPASOL(consSepasolOr)
1497 { /*lint --e{715}*/
1498  SCIP_Bool separated;
1499  int c;
1500 
1501  *result = SCIP_DIDNOTFIND;
1502 
1503  /* separate all useful constraints */
1504  for( c = 0; c < nusefulconss; ++c )
1505  {
1506  SCIP_CALL( separateCons(scip, conss[c], sol, &separated) );
1507  if( separated )
1508  *result = SCIP_SEPARATED;
1509  }
1510 
1511  /* combine constraints to get more cuts */
1512  /**@todo combine constraints to get further cuts */
1513 
1514  return SCIP_OKAY;
1515 }
1516 
1517 
1518 /** constraint enforcing method of constraint handler for LP solutions */
1519 static
1520 SCIP_DECL_CONSENFOLP(consEnfolpOr)
1521 { /*lint --e{715}*/
1522  SCIP_Bool violated;
1523  int i;
1524 
1525  /* method is called only for integral solutions, because the enforcing priority is negative */
1526  for( i = 0; i < nconss; i++ )
1527  {
1528  SCIP_CALL( checkCons(scip, conss[i], NULL, FALSE, FALSE, &violated) );
1529  if( violated )
1530  {
1531  SCIP_Bool separated;
1532 
1533  SCIP_CALL( separateCons(scip, conss[i], NULL, &separated) );
1534  assert(separated); /* because the solution is integral, the separation always finds a cut */
1535  *result = SCIP_SEPARATED;
1536  return SCIP_OKAY;
1537  }
1538  }
1539  *result = SCIP_FEASIBLE;
1540 
1541  return SCIP_OKAY;
1542 }
1543 
1544 
1545 /** constraint enforcing method of constraint handler for relaxation solutions */
1546 static
1547 SCIP_DECL_CONSENFORELAX(consEnforelaxOr)
1548 { /*lint --e{715}*/
1549  SCIP_Bool violated;
1550  int i;
1551 
1552  /* method is called only for integral solutions, because the enforcing priority is negative */
1553  for( i = 0; i < nconss; i++ )
1554  {
1555  SCIP_CALL( checkCons(scip, conss[i], sol, FALSE, FALSE, &violated) );
1556  if( violated )
1557  {
1558  SCIP_Bool separated;
1559 
1560  SCIP_CALL( separateCons(scip, conss[i], sol, &separated) );
1561  assert(separated); /* because the solution is integral, the separation always finds a cut */
1562  *result = SCIP_SEPARATED;
1563  return SCIP_OKAY;
1564  }
1565  }
1566  *result = SCIP_FEASIBLE;
1567 
1568  return SCIP_OKAY;
1569 }
1570 
1571 
1572 /** constraint enforcing method of constraint handler for pseudo solutions */
1573 static
1574 SCIP_DECL_CONSENFOPS(consEnfopsOr)
1575 { /*lint --e{715}*/
1576  SCIP_Bool violated;
1577  int i;
1578 
1579  /* method is called only for integral solutions, because the enforcing priority is negative */
1580  for( i = 0; i < nconss; i++ )
1581  {
1582  SCIP_CALL( checkCons(scip, conss[i], NULL, TRUE, FALSE, &violated) );
1583  if( violated )
1584  {
1585  *result = SCIP_INFEASIBLE;
1586  return SCIP_OKAY;
1587  }
1588  }
1589  *result = SCIP_FEASIBLE;
1590 
1591  return SCIP_OKAY;
1592 }
1593 
1594 
1595 /** feasibility check method of constraint handler for integral solutions */
1596 static
1597 SCIP_DECL_CONSCHECK(consCheckOr)
1598 { /*lint --e{715}*/
1599  int i;
1600 
1601  *result = SCIP_FEASIBLE;
1602 
1603  /* method is called only for integral solutions, because the enforcing priority is negative */
1604  for( i = 0; i < nconss && (*result == SCIP_FEASIBLE || completely); i++ )
1605  {
1606  SCIP_Bool violated = FALSE;
1607 
1608  SCIP_CALL( checkCons(scip, conss[i], sol, checklprows, printreason, &violated) );
1609 
1610  if( violated )
1611  *result = SCIP_INFEASIBLE;
1612  }
1613 
1614  return SCIP_OKAY;
1615 }
1616 
1617 
1618 /** domain propagation method of constraint handler */
1619 static
1620 SCIP_DECL_CONSPROP(consPropOr)
1621 { /*lint --e{715}*/
1622  SCIP_CONSHDLRDATA* conshdlrdata;
1623  SCIP_Bool cutoff;
1624  int nfixedvars;
1625  int c;
1626 
1627  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1628  assert(conshdlrdata != NULL);
1629 
1630  cutoff = FALSE;
1631  nfixedvars = 0;
1632 
1633  /* propagate all useful constraints */
1634  for( c = 0; c < nusefulconss && !cutoff; ++c )
1635  {
1636  SCIP_CALL( propagateCons(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &nfixedvars) );
1637  }
1638 
1639  /* return the correct result */
1640  if( cutoff )
1641  *result = SCIP_CUTOFF;
1642  else if( nfixedvars > 0 )
1643  *result = SCIP_REDUCEDDOM;
1644  else
1645  *result = SCIP_DIDNOTFIND;
1646 
1647  return SCIP_OKAY;
1648 }
1649 
1650 
1651 /** presolving method of constraint handler */
1652 static
1653 SCIP_DECL_CONSPRESOL(consPresolOr)
1654 { /*lint --e{715}*/
1655  SCIP_CONSHDLRDATA* conshdlrdata;
1656  SCIP_CONS* cons;
1657  SCIP_CONSDATA* consdata;
1658  SCIP_Bool cutoff;
1659  SCIP_Bool redundant;
1660  SCIP_Bool aggregated;
1661  int oldnfixedvars;
1662  int oldnaggrvars;
1663  int oldnupgdconss;
1664  int c;
1665 
1666  assert(result != NULL);
1667 
1668  *result = SCIP_DIDNOTFIND;
1669  oldnfixedvars = *nfixedvars;
1670  oldnaggrvars = *naggrvars;
1671  oldnupgdconss = *nupgdconss;
1672 
1673  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1674  assert(conshdlrdata != NULL);
1675 
1676  /* process constraints */
1677  cutoff = FALSE;
1678  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
1679  {
1680  cons = conss[c];
1681  assert(cons != NULL);
1682  consdata = SCIPconsGetData(cons);
1683  assert(consdata != NULL);
1684 
1685  /* force presolving the constraint in the initial round */
1686  if( nrounds == 0 )
1687  consdata->propagated = FALSE;
1688 
1689  /* propagate constraint */
1690  SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars) );
1691 
1692  /* remove all variables that are fixed to one */
1693  SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr) );
1694 
1695  /* transform or constraints into and constraints on the negated variables in order to improve
1696  * the pairwise constraint presolving possibilities
1697  */
1698  SCIP_CALL( upgradeCons(scip, cons, nupgdconss) );
1699 
1700  if( !cutoff && !SCIPconsIsDeleted(cons) && !SCIPconsIsModifiable(cons) )
1701  {
1702  assert(consdata->nvars >= 1); /* otherwise, propagateCons() has deleted the constraint */
1703 
1704  /* if only one variable is left, the resultant has to be equal to this single variable */
1705  if( consdata->nvars == 1 )
1706  {
1707  SCIPdebugMsg(scip, "or constraint <%s> has only one variable not fixed to 0.0\n", SCIPconsGetName(cons));
1708 
1709  assert(consdata->vars != NULL);
1710  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->vars[0]), 0.0));
1711  assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(consdata->vars[0]), 1.0));
1712 
1713  /* aggregate variables: resultant - operand == 0 */
1714  SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, consdata->vars[0], 1.0, -1.0, 0.0,
1715  &cutoff, &redundant, &aggregated) );
1716  assert(redundant || SCIPdoNotAggr(scip));
1717 
1718  if( aggregated )
1719  {
1720  assert(redundant);
1721  (*naggrvars)++;
1722  }
1723 
1724  if( redundant )
1725  {
1726  /* delete constraint */
1727  SCIP_CALL( SCIPdelCons(scip, cons) );
1728  (*ndelconss)++;
1729  }
1730  }
1731  else if( !consdata->impladded )
1732  {
1733  int i;
1734 
1735  /* add implications: resultant == 0 -> all operands == 0 */
1736  for( i = 0; i < consdata->nvars && !cutoff; ++i )
1737  {
1738  int nimplbdchgs;
1739 
1740  SCIP_CALL( SCIPaddVarImplication(scip, consdata->resvar, FALSE, consdata->vars[i],
1741  SCIP_BOUNDTYPE_UPPER, 0.0, &cutoff, &nimplbdchgs) );
1742  *nchgbds += nimplbdchgs;
1743  }
1744  consdata->impladded = TRUE;
1745  }
1746 
1747  /* if in r = x or y, the resultant is fixed to one, add implication x = 0 -> y = 1 */
1748  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 2 && !consdata->opimpladded
1749  && SCIPvarGetLbGlobal(consdata->resvar) > 0.5 )
1750  {
1751  int nimplbdchgs;
1752 
1753  SCIP_CALL( SCIPaddVarImplication(scip, consdata->vars[0], FALSE, consdata->vars[1],
1754  SCIP_BOUNDTYPE_LOWER, 1.0, &cutoff, &nimplbdchgs) );
1755  (*nchgbds) += nimplbdchgs;
1756  consdata->opimpladded = TRUE;
1757  }
1758  }
1759  }
1760 
1761  /* return the correct result code */
1762  if( cutoff )
1763  *result = SCIP_CUTOFF;
1764  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nupgdconss > oldnupgdconss )
1765  *result = SCIP_SUCCESS;
1766 
1767  return SCIP_OKAY;
1768 }
1769 
1770 
1771 /** propagation conflict resolving method of constraint handler */
1772 static
1773 SCIP_DECL_CONSRESPROP(consRespropOr)
1774 { /*lint --e{715}*/
1775  SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, bdchgidx, result) );
1776 
1777  return SCIP_OKAY;
1778 }
1779 
1780 
1781 /** variable rounding lock method of constraint handler */
1782 static
1783 SCIP_DECL_CONSLOCK(consLockOr)
1784 { /*lint --e{715}*/
1785  SCIP_CONSDATA* consdata;
1786  int i;
1787 
1788  consdata = SCIPconsGetData(cons);
1789  assert(consdata != NULL);
1790 
1791  /* lock resultant variable */
1792  SCIP_CALL( SCIPaddVarLocks(scip, consdata->resvar, nlockspos + nlocksneg, nlockspos + nlocksneg) );
1793 
1794  /* lock all operand variables */
1795  for( i = 0; i < consdata->nvars; ++i )
1796  {
1797  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos + nlocksneg, nlockspos + nlocksneg) );
1798  }
1799 
1800  return SCIP_OKAY;
1801 }
1802 
1803 
1804 /** constraint display method of constraint handler */
1805 static
1806 SCIP_DECL_CONSPRINT(consPrintOr)
1807 { /*lint --e{715}*/
1808 
1809  assert( scip != NULL );
1810  assert( conshdlr != NULL );
1811  assert( cons != NULL );
1812 
1813  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
1814 
1815  return SCIP_OKAY;
1816 }
1817 
1818 /** constraint copying method of constraint handler */
1819 static
1820 SCIP_DECL_CONSCOPY(consCopyOr)
1821 { /*lint --e{715}*/
1822  SCIP_VAR** sourcevars;
1823  SCIP_VAR** vars;
1824  SCIP_VAR* sourceresvar;
1825  SCIP_VAR* resvar;
1826  int nvars;
1827  int v;
1828 
1829  assert(valid != NULL);
1830  (*valid) = TRUE;
1831  resvar = NULL;
1832 
1833  /* get variables that need to be copied */
1834  sourceresvar = SCIPgetResultantOr(sourcescip, sourcecons);
1835  sourcevars = SCIPgetVarsOr(sourcescip, sourcecons);
1836  nvars = SCIPgetNVarsOr(sourcescip, sourcecons);
1837 
1838  if( nvars == -1 )
1839  return SCIP_INVALIDCALL;
1840 
1841  /* allocate buffer array */
1842  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
1843 
1844  /* map operand variables to active variables of the target SCIP */
1845  for( v = 0; v < nvars && *valid; ++v )
1846  {
1847  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &vars[v], varmap, consmap, global, valid) );
1848  assert(!(*valid) || vars[v] != NULL);
1849  }
1850 
1851  /* map resultant to active variable of the target SCIP */
1852  if( *valid )
1853  {
1854  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourceresvar, &resvar, varmap, consmap, global, valid) );
1855  assert(!(*valid) || resvar != NULL);
1856 
1857  if( *valid )
1858  {
1859  assert(resvar != NULL);
1860  SCIP_CALL( SCIPcreateConsOr(scip, cons, SCIPconsGetName(sourcecons), resvar, nvars, vars,
1861  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1862  }
1863  }
1864 
1865  /* free buffer array */
1866  SCIPfreeBufferArray(scip, &vars);
1867 
1868  return SCIP_OKAY;
1869 }
1870 
1871 /** constraint parsing method of constraint handler */
1872 static
1873 SCIP_DECL_CONSPARSE(consParseOr)
1874 { /*lint --e{715}*/
1875  SCIP_VAR** vars;
1876  SCIP_VAR* resvar;
1877  char* strcopy;
1878  char* token;
1879  char* saveptr;
1880  char* endptr;
1881  int requiredsize;
1882  int varssize;
1883  int nvars;
1884 
1885  SCIPdebugMsg(scip, "parse <%s> as or constraint\n", str);
1886 
1887  /* copy string for truncating it */
1888  SCIP_CALL( SCIPduplicateBufferArray(scip, &strcopy, str, (int)(strlen(str)+1)));
1889 
1890  /* cutoff "or" form the constraint string */
1891  token = SCIPstrtok(strcopy, "=", &saveptr );
1892 
1893  /* parse variable name */
1894  SCIP_CALL( SCIPparseVarName(scip, token, &resvar, &endptr) );
1895 
1896  if( resvar == NULL )
1897  {
1898  SCIPdebugMsg(scip, "resultant variable %s does not exist \n", token);
1899  *success = FALSE;
1900  }
1901  else
1902  {
1903  /* cutoff "or" form the constraint string */
1904  (void) SCIPstrtok(NULL, "(", &saveptr );
1905 
1906  /* cutoff ")" form the constraint string */
1907  token = SCIPstrtok(NULL, ")", &saveptr );
1908 
1909  varssize = 100;
1910  nvars = 0;
1911 
1912  /* allocate buffer array for variables */
1913  SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
1914 
1915  /* parse string */
1916  SCIP_CALL( SCIPparseVarsList(scip, token, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
1917 
1918  if( *success )
1919  {
1920  /* check if the size of the variable array was great enough */
1921  if( varssize < requiredsize )
1922  {
1923  /* reallocate memory */
1924  varssize = requiredsize;
1925  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
1926 
1927  /* parse string again with the correct size of the variable array */
1928  SCIP_CALL( SCIPparseVarsList(scip, token, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
1929  }
1930 
1931  assert(*success);
1932  assert(varssize >= requiredsize);
1933 
1934  /* create and constraint */
1935  SCIP_CALL( SCIPcreateConsOr(scip, cons, name, resvar, nvars, vars,
1936  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1937  }
1938 
1939  /* free variable buffer */
1940  SCIPfreeBufferArray(scip, &vars);
1941  }
1942 
1943  /* free string buffer */
1944  SCIPfreeBufferArray(scip, &strcopy);
1945 
1946  return SCIP_OKAY;
1947 }
1948 
1949 /** constraint method of constraint handler which returns the variables (if possible) */
1950 static
1951 SCIP_DECL_CONSGETVARS(consGetVarsOr)
1952 { /*lint --e{715}*/
1953  SCIP_CONSDATA* consdata;
1954 
1955  consdata = SCIPconsGetData(cons);
1956  assert(consdata != NULL);
1957 
1958  if( varssize < consdata->nvars + 1 )
1959  (*success) = FALSE;
1960  else
1961  {
1962  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
1963  vars[consdata->nvars] = consdata->resvar;
1964  (*success) = TRUE;
1965  }
1966 
1967  return SCIP_OKAY;
1968 }
1969 
1970 /** constraint method of constraint handler which returns the number of variable (if possible) */
1971 static
1972 SCIP_DECL_CONSGETNVARS(consGetNVarsOr)
1973 { /*lint --e{715}*/
1974  SCIP_CONSDATA* consdata;
1975 
1976  assert(cons != NULL);
1977 
1978  consdata = SCIPconsGetData(cons);
1979  assert(consdata != NULL);
1980 
1981  (*nvars) = consdata->nvars + 1;
1982  (*success) = TRUE;
1983 
1984  return SCIP_OKAY;
1985 }
1986 
1987 
1988 /*
1989  * Callback methods of event handler
1990  */
1991 
1992 static
1993 SCIP_DECL_EVENTEXEC(eventExecOr)
1994 { /*lint --e{715}*/
1995  SCIP_CONSDATA* consdata;
1996 
1997  assert(eventhdlr != NULL);
1998  assert(eventdata != NULL);
1999  assert(event != NULL);
2000 
2001  consdata = (SCIP_CONSDATA*)eventdata;
2002  assert(consdata != NULL);
2003 
2004  /* check, if the variable was fixed to one */
2006  consdata->nofixedone = FALSE;
2007 
2008  consdata->propagated = FALSE;
2009 
2010  return SCIP_OKAY;
2011 }
2012 
2013 
2014 /*
2015  * constraint specific interface methods
2016  */
2017 
2018 /** creates the handler for or constraints and includes it in SCIP */
2020  SCIP* scip /**< SCIP data structure */
2021  )
2022 {
2023  SCIP_CONSHDLRDATA* conshdlrdata;
2024  SCIP_CONSHDLR* conshdlr;
2025  SCIP_EVENTHDLR* eventhdlr;
2026 
2027  /* create event handler for events on variables */
2029  eventExecOr, NULL) );
2030 
2031  /* create constraint handler data */
2032  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
2033 
2034  /* include constraint handler */
2037  consEnfolpOr, consEnfopsOr, consCheckOr, consLockOr,
2038  conshdlrdata) );
2039  assert(conshdlr != NULL);
2040 
2041  /* set non-fundamental callbacks via specific setter functions */
2042  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOr, consCopyOr) );
2043  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOr) );
2044  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolOr) );
2045  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeOr) );
2046  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsOr) );
2047  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsOr) );
2048  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpOr) );
2049  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseOr) );
2051  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOr) );
2052  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropOr, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
2054  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOr) );
2055  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOr, consSepasolOr, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY,
2056  CONSHDLR_DELAYSEPA) );
2057  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOr) );
2058  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxOr) );
2059 
2060  return SCIP_OKAY;
2061 }
2062 
2063 /** creates and captures an or constraint
2064  *
2065  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2066  */
2068  SCIP* scip, /**< SCIP data structure */
2069  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2070  const char* name, /**< name of constraint */
2071  SCIP_VAR* resvar, /**< resultant variable of the operation */
2072  int nvars, /**< number of operator variables in the constraint */
2073  SCIP_VAR** vars, /**< array with operator variables of constraint */
2074  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2075  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2076  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2077  * Usually set to TRUE. */
2078  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2079  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2080  SCIP_Bool check, /**< should the constraint be checked for feasibility?
2081  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2082  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2083  * Usually set to TRUE. */
2084  SCIP_Bool local, /**< is constraint only valid locally?
2085  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2086  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
2087  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
2088  * adds coefficients to this constraint. */
2089  SCIP_Bool dynamic, /**< is constraint subject to aging?
2090  * Usually set to FALSE. Set to TRUE for own cuts which
2091  * are separated as constraints. */
2092  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2093  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2094  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2095  * if it may be moved to a more global node?
2096  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2097  )
2098 {
2099  SCIP_CONSHDLR* conshdlr;
2100  SCIP_CONSHDLRDATA* conshdlrdata;
2101  SCIP_CONSDATA* consdata;
2102 
2103  /* find the or constraint handler */
2104  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2105  if( conshdlr == NULL )
2106  {
2107  SCIPerrorMessage("or constraint handler not found\n");
2108  return SCIP_PLUGINNOTFOUND;
2109  }
2110 
2111  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2112  assert(conshdlrdata != NULL);
2113 
2114  /* create constraint data */
2115  SCIP_CALL( consdataCreate(scip, &consdata, conshdlrdata->eventhdlr, nvars, vars, resvar) );
2116 
2117  /* create constraint */
2118  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
2119  local, modifiable, dynamic, removable, stickingatnode) );
2120 
2121  return SCIP_OKAY;
2122 }
2123 
2124 /** creates and captures an or constraint
2125  * in its most basic variant, i. e., with all constraint flags set to their default values
2126  *
2127  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2128  */
2130  SCIP* scip, /**< SCIP data structure */
2131  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2132  const char* name, /**< name of constraint */
2133  SCIP_VAR* resvar, /**< resultant variable of the operation */
2134  int nvars, /**< number of operator variables in the constraint */
2135  SCIP_VAR** vars /**< array with operator variables of constraint */
2136  )
2137 {
2138  SCIP_CALL( SCIPcreateConsOr(scip, cons, name, resvar, nvars, vars, TRUE, TRUE, TRUE, TRUE, TRUE,
2139  FALSE, FALSE, FALSE, FALSE, FALSE) );
2140 
2141  return SCIP_OKAY;
2142 }
2143 
2144 /** gets number of variables in or constraint */
2145 int SCIPgetNVarsOr(
2146  SCIP* scip, /**< SCIP data structure */
2147  SCIP_CONS* cons /**< constraint data */
2148  )
2149 {
2150  SCIP_CONSDATA* consdata;
2151 
2152  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2153  {
2154  SCIPerrorMessage("constraint is not an or constraint\n");
2155  SCIPABORT();
2156  return -1; /*lint !e527*/
2157  }
2158 
2159  consdata = SCIPconsGetData(cons);
2160  assert(consdata != NULL);
2161 
2162  return consdata->nvars;
2163 }
2164 
2165 /** gets array of variables in or constraint */
2167  SCIP* scip, /**< SCIP data structure */
2168  SCIP_CONS* cons /**< constraint data */
2169  )
2170 {
2171  SCIP_CONSDATA* consdata;
2172 
2173  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2174  {
2175  SCIPerrorMessage("constraint is not an or constraint\n");
2176  SCIPABORT();
2177  return NULL; /*lint !e527*/
2178  }
2179 
2180  consdata = SCIPconsGetData(cons);
2181  assert(consdata != NULL);
2182 
2183  return consdata->vars;
2184 }
2185 
2186 /** gets the resultant variable in or constraint */
2188  SCIP* scip, /**< SCIP data structure */
2189  SCIP_CONS* cons /**< constraint data */
2190  )
2191 {
2192  SCIP_CONSDATA* consdata;
2193 
2194  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2195  {
2196  SCIPerrorMessage("constraint is not a or constraint\n");
2197  SCIPABORT();
2198  return NULL; /*lint !e527*/
2199  }
2200 
2201  consdata = SCIPconsGetData(cons);
2202  assert(consdata != NULL);
2203 
2204  return consdata->resvar;
2205 }
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:22604
SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
Definition: scip.c:30740
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4143
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28372
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:22593
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:6291
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip.c:41459
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:22587
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:19649
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:821
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:8245
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:6314
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition: scip.c:19115
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:1784
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19509
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:1455
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:41226
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:6544
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip.c:6036
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28400
#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:12663
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:46813
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30668
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:27388
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8611
static SCIP_RETCODE upgradeCons(SCIP *scip, SCIP_CONS *cons, int *nupgdconss)
Definition: cons_or.c:1301
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:18957
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip.c:18038
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16842
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47387
#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:5894
SCIP_RETCODE SCIPcreateConsBasicOr(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars)
Definition: cons_or.c:2130
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
static SCIP_DECL_CONSCHECK(consCheckOr)
Definition: cons_or.c:1598
#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:21660
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8265
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
Definition: cons_or.c:1215
static SCIP_DECL_CONSPROP(consPropOr)
Definition: cons_or.c:1621
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8295
static SCIP_DECL_CONSSEPALP(consSepalpOr)
Definition: cons_or.c:1473
static SCIP_DECL_CONSPARSE(consParseOr)
Definition: cons_or.c:1874
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:27155
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
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:5948
Constraint handler for AND constraints, .
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:22628
enum Proprule PROPRULE
Definition: cons_or.c:107
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1017
static SCIP_DECL_CONSENFOPS(consEnfopsOr)
Definition: cons_or.c:1575
#define CONSHDLR_ENFOPRIORITY
Definition: cons_or.c:46
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8255
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:108
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:6337
#define SCIPdebugMsgPrint
Definition: scip.h:456
#define SCIPdebugMsg
Definition: scip.h:455
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:18998
SCIP_RETCODE 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:2068
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:6521
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:8047
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1343
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:27584
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:16695
#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:27133
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:17286
static SCIP_DECL_CONSCOPY(consCopyOr)
Definition: cons_or.c:1821
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:22599
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:18115
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:6060
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:4968
#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:12591
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:13297
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:24094
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21788
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7986
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8205
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:6085
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4133
static SCIP_DECL_CONSPRESOL(consPresolOr)
Definition: cons_or.c:1654
static SCIP_DECL_CONSPRINT(consPrintOr)
Definition: cons_or.c:1807
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:66
#define CONSHDLR_CHECKPRIORITY
Definition: cons_or.c:47
#define SCIP_CALL(x)
Definition: def.h:350
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:63
static SCIP_DECL_CONSFREE(consFreeOr)
Definition: cons_or.c:1375
static SCIP_DECL_CONSGETVARS(consGetVarsOr)
Definition: cons_or.c:1952
SCIP_VAR ** SCIPgetVarsOr(SCIP *scip, SCIP_CONS *cons)
Definition: cons_or.c:2167
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:27535
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8225
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOr)
Definition: cons_or.c:1359
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:34661
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:6360
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
#define CONSHDLR_PRESOLTIMING
Definition: cons_or.c:59
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
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:2146
#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:30402
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:29091
static SCIP_DECL_CONSENFORELAX(consEnforelaxOr)
Definition: cons_or.c:1548
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8006
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:1497
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8115
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8185
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8155
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:41272
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *separated)
Definition: cons_or.c:853
static SCIP_DECL_CONSDELETE(consDeleteOr)
Definition: cons_or.c:1411
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21714
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:6498
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
static SCIP_DECL_EVENTEXEC(eventExecOr)
Definition: cons_or.c:1994
Proprule
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:35836
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:976
#define CONSHDLR_DESC
Definition: cons_or.c:44
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30540
SCIP_RETCODE SCIPwriteVarsList(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_Bool type, char delimiter)
Definition: scip.c:17797
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1920
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8016
SCIP_VAR * SCIPgetResultantOr(SCIP *scip, SCIP_CONS *cons)
Definition: cons_or.c:2188
static SCIP_DECL_CONSRESPROP(consRespropOr)
Definition: cons_or.c:1774
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27761
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:6253
static SCIP_DECL_CONSEXITSOL(consExitsolOr)
Definition: cons_or.c:1393
void SCIPupdateSolConsViolation(SCIP *scip, SCIP_SOL *sol, SCIP_Real absviol, SCIP_Real relviol)
Definition: scip.c:13790
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:25684
#define SCIP_Real
Definition: def.h:149
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8235
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
static SCIP_DECL_CONSTRANS(consTransOr)
Definition: cons_or.c:1426
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:6567
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8175
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip.c:25848
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8165
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:31134
#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:903
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
SCIP_RETCODE SCIPincludeConshdlrOr(SCIP *scip)
Definition: cons_or.c:2020
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17342
static SCIP_RETCODE analyzeConflictOne(SCIP *scip, SCIP_CONS *cons)
Definition: cons_or.c:935
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47399
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16804
#define CONSHDLR_PROPFREQ
Definition: cons_or.c:49
static SCIP_DECL_CONSENFOLP(consEnfolpOr)
Definition: cons_or.c:1521
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:6181
#define SCIPABORT()
Definition: def.h:322
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip.c:17735
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:9969
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
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:23039
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:19045
static SCIP_DECL_CONSGETNVARS(consGetNVarsOr)
Definition: cons_or.c:1973
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:22624
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5994
#define CONSHDLR_SEPAFREQ
Definition: cons_or.c:48