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