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