Scippy

SCIP

Solving Constraint Integer Programs

cons_and.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-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_and.c
17  * @brief Constraint handler for AND-constraints, \f$r = x_1 \wedge x_2 \wedge \dots \wedge x_n\f$
18  * @author Tobias Achterberg
19  * @author Stefan Heinz
20  * @author Michael Winkler
21  *
22  * This constraint handler deals with AND-constraint. These are constraint of the form:
23  *
24  * \f[
25  * r = x_1 \wedge x_2 \wedge \dots \wedge x_n
26  * \f]
27  *
28  * where \f$x_i\f$ is a binary variable for all \f$i\f$. Hence, \f$r\f$ is also of binary type. The variable \f$r\f$ is
29  * called resultant and the \f$x\f$'s operators.
30  */
31 
32 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33 
34 #include <assert.h>
35 #include <string.h>
36 
37 #include "scip/cons_and.h"
38 #include "scip/cons_linear.h"
39 #include "scip/cons_logicor.h"
40 #include "scip/cons_setppc.h"
41 #include "scip/cons_nonlinear.h"
42 #include "scip/cons_setppc.h"
44 #include "scip/pub_misc.h"
45 #include "scip/debug.h"
46 
47 
48 /* constraint handler properties */
49 #define CONSHDLR_NAME "and"
50 #define CONSHDLR_DESC "constraint handler for AND-constraints: r = and(x1, ..., xn)"
51 #define CONSHDLR_SEPAPRIORITY +850100 /**< priority of the constraint handler for separation */
52 #define CONSHDLR_ENFOPRIORITY -850100 /**< priority of the constraint handler for constraint enforcing */
53 #define CONSHDLR_CHECKPRIORITY -850100 /**< priority of the constraint handler for checking feasibility */
54 #define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
55 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
56 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
57  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
58 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
59 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
60 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
61 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
62 
63 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE)
64 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
65 
66 #define EVENTHDLR_NAME "and"
67 #define EVENTHDLR_DESC "bound change event handler for AND-constraints"
68 
69 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
70 #define DEFAULT_LINEARIZE FALSE /**< should constraint get linearized and removed? */
71 #define DEFAULT_ENFORCECUTS TRUE /**< should cuts be separated during LP enforcing? */
72 #define DEFAULT_AGGRLINEARIZATION FALSE /**< should an aggregated linearization be used? */
73 #define DEFAULT_UPGRRESULTANT TRUE /**< should all binary resultant variables be upgraded to implicit binary variables */
74 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving be performed? */
75 
76 #define HASHSIZE_ANDCONS 131101 /**< minimal size of hash table in and constraint tables */
77 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
78 #define NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
79 #define MINGAINPERNMINCOMPARISONS 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
80 #define EXPRGRAPHREFORM_PRIORITY 100000 /**< priority of expression graph node reformulation method */
81 
82 /* @todo maybe use event SCIP_EVENTTYPE_VARUNLOCKED to decide for another dual-presolving run on a constraint */
83 
84 /*
85  * Data structures
86  */
87 
88 /** constraint data for AND-constraints */
89 struct SCIP_ConsData
90 {
91  SCIP_VAR** vars; /**< variables in the AND-constraint */
92  SCIP_VAR* resvar; /**< resultant variable */
93  SCIP_ROW** rows; /**< rows for linear relaxation of AND-constraint */
94  SCIP_ROW* aggrrow; /**< aggregated row for linear relaxation of AND-constraint */
95  int nvars; /**< number of variables in AND-constraint */
96  int varssize; /**< size of vars array */
97  int nrows; /**< number of rows for linear relaxation of AND-constraint */
98  int watchedvar1; /**< position of first watched operator variable */
99  int watchedvar2; /**< position of second watched operator variable */
100  int filterpos1; /**< event filter position of first watched operator variable */
101  int filterpos2; /**< event filter position of second watched operator variable */
102  unsigned int propagated:1; /**< is constraint already preprocessed/propagated? */
103  unsigned int nofixedzero:1; /**< is none of the operator variables fixed to FALSE? */
104  unsigned int impladded:1; /**< were the implications of the constraint already added? */
105  unsigned int opimpladded:1; /**< was the implication for 2 operands with fixed resultant added? */
106  unsigned int sorted:1; /**< are the constraint's variables sorted? */
107  unsigned int changed:1; /**< was constraint changed since last pair preprocessing round? */
108  unsigned int merged:1; /**< are the constraint's equal variables already merged? */
109  unsigned int checkwhenupgr:1; /**< if AND-constraint is upgraded to an logicor constraint or the and-
110  * constraint is linearized, should the check flag be set to true, even
111  * if the AND-constraint has a check flag set to false? */
112  unsigned int notremovablewhenupgr:1;/**< if AND-constraint is upgraded to an logicor constraint or the and-
113  * constraint is linearized, should the removable flag be set to false,
114  * even if the AND-constraint has a removable flag set to true? */
115 };
116 
117 /** constraint handler data */
118 struct SCIP_ConshdlrData
119 {
120  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events on watched variables */
121  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
122  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
123  SCIP_Bool linearize; /**< should constraint get linearized and removed? */
124  SCIP_Bool enforcecuts; /**< should cuts be separated during LP enforcing? */
125  SCIP_Bool aggrlinearization; /**< should an aggregated linearization be used? */
126  SCIP_Bool upgrresultant; /**< upgrade binary resultant variable to an implicit binary variable */
127  SCIP_Bool dualpresolving; /**< should dual presolving be performed? */
128 };
129 
130 
131 /*
132  * Propagation rules
133  */
134 
135 enum Proprule
136 {
137  PROPRULE_INVALID = 0, /**< propagation was applied without a specific propagation rule */
138  PROPRULE_1 = 1, /**< v_i = FALSE => r = FALSE */
139  PROPRULE_2 = 2, /**< r = TRUE => v_i = TRUE for all i */
140  PROPRULE_3 = 3, /**< v_i = TRUE for all i => r = TRUE */
141  PROPRULE_4 = 4 /**< r = FALSE, v_i = TRUE for all i except j => v_j = FALSE */
142 };
143 typedef enum Proprule PROPRULE;
145 
146 /*
147  * Local methods
148  */
149 
150 /** installs rounding locks for the given variable in the given AND-constraint */
151 static
153  SCIP* scip, /**< SCIP data structure */
154  SCIP_CONS* cons, /**< AND-constraint */
155  SCIP_VAR* var /**< variable of constraint entry */
156  )
157 {
158  /* rounding in both directions may violate the constraint */
159  SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, TRUE) );
160 
161  return SCIP_OKAY;
162 }
163 
164 /** removes rounding locks for the given variable in the given AND-constraint */
165 static
167  SCIP* scip, /**< SCIP data structure */
168  SCIP_CONS* cons, /**< AND-constraint */
169  SCIP_VAR* var /**< variable of constraint entry */
170  )
171 {
172  /* rounding in both directions may violate the constraint */
173  SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, TRUE) );
174 
175  return SCIP_OKAY;
176 }
177 
178 /** creates constraint handler data */
179 static
181  SCIP* scip, /**< SCIP data structure */
182  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
183  SCIP_EVENTHDLR* eventhdlr /**< event handler */
184  )
185 {
186  assert(scip != NULL);
187  assert(conshdlrdata != NULL);
188  assert(eventhdlr != NULL);
189 
190  SCIP_CALL( SCIPallocMemory(scip, conshdlrdata) );
191 
192  /* set event handler for catching bound change events on variables */
193  (*conshdlrdata)->eventhdlr = eventhdlr;
194 
195  return SCIP_OKAY;
196 }
197 
198 /** frees constraint handler data */
199 static
201  SCIP* scip, /**< SCIP data structure */
202  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
203  )
204 {
205  assert(conshdlrdata != NULL);
206  assert(*conshdlrdata != NULL);
207 
208  SCIPfreeMemory(scip, conshdlrdata);
209 
210  return SCIP_OKAY;
211 }
212 
213 /** catches events for the watched variable at given position */
214 static
216  SCIP* scip, /**< SCIP data structure */
217  SCIP_CONSDATA* consdata, /**< AND-constraint data */
218  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
219  int pos, /**< array position of variable to catch bound change events for */
220  int* filterpos /**< pointer to store position of event filter entry */
221  )
222 {
223  assert(consdata != NULL);
224  assert(consdata->vars != NULL);
225  assert(eventhdlr != NULL);
226  assert(0 <= pos && pos < consdata->nvars);
227  assert(filterpos != NULL);
228 
229  /* catch tightening events for lower bound and relaxed events for upper bounds on watched variable */
231  eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
232 
233  return SCIP_OKAY;
234 }
235 
236 
237 /** drops events for the watched variable at given position */
238 static
240  SCIP* scip, /**< SCIP data structure */
241  SCIP_CONSDATA* consdata, /**< AND-constraint data */
242  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
243  int pos, /**< array position of watched variable to drop bound change events for */
244  int filterpos /**< position of event filter entry */
245  )
246 {
247  assert(consdata != NULL);
248  assert(consdata->vars != NULL);
249  assert(eventhdlr != NULL);
250  assert(0 <= pos && pos < consdata->nvars);
251  assert(filterpos >= 0);
252 
253  /* drop tightening events for lower bound and relaxed events for upper bounds on watched variable */
255  eventhdlr, (SCIP_EVENTDATA*)consdata, filterpos) );
256 
257  return SCIP_OKAY;
258 }
259 
260 /** catches needed events on all variables of constraint, except the special ones for watched variables */
261 static
263  SCIP* scip, /**< SCIP data structure */
264  SCIP_CONSDATA* consdata, /**< AND-constraint data */
265  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
266  )
267 {
268  int i;
269 
270  assert(consdata != NULL);
271 
272  /* catch bound change events for both bounds on resultant variable */
273  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->resvar, SCIP_EVENTTYPE_BOUNDCHANGED,
274  eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
275 
276  /* catch tightening events for upper bound and relaxed events for lower bounds on operator variables */
277  for( i = 0; i < consdata->nvars; ++i )
278  {
280  eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
281  }
282 
283  return SCIP_OKAY;
284 }
285 
286 /** drops events on all variables of constraint, except the special ones for watched variables */
287 static
289  SCIP* scip, /**< SCIP data structure */
290  SCIP_CONSDATA* consdata, /**< AND-constraint data */
291  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
292  )
293 {
294  int i;
295 
296  assert(consdata != NULL);
297 
298  /* drop bound change events for both bounds on resultant variable */
299  SCIP_CALL( SCIPdropVarEvent(scip, consdata->resvar, SCIP_EVENTTYPE_BOUNDCHANGED,
300  eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
301 
302  /* drop tightening events for upper bound and relaxed events for lower bounds on operator variables */
303  for( i = 0; i < consdata->nvars; ++i )
304  {
306  eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
307  }
308 
309  return SCIP_OKAY;
310 }
311 
312 /** stores the given variable numbers as watched variables, and updates the event processing */
313 static
315  SCIP* scip, /**< SCIP data structure */
316  SCIP_CONSDATA* consdata, /**< AND-constraint data */
317  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
318  int watchedvar1, /**< new first watched variable */
319  int watchedvar2 /**< new second watched variable */
320  )
321 {
322  assert(consdata != NULL);
323  assert(watchedvar1 == -1 || watchedvar1 != watchedvar2);
324  assert(watchedvar1 != -1 || watchedvar2 == -1);
325  assert(watchedvar1 == -1 || (0 <= watchedvar1 && watchedvar1 < consdata->nvars));
326  assert(watchedvar2 == -1 || (0 <= watchedvar2 && watchedvar2 < consdata->nvars));
327 
328  /* if one watched variable is equal to the old other watched variable, just switch positions */
329  if( watchedvar1 == consdata->watchedvar2 || watchedvar2 == consdata->watchedvar1 )
330  {
331  int tmp;
332 
333  tmp = consdata->watchedvar1;
334  consdata->watchedvar1 = consdata->watchedvar2;
335  consdata->watchedvar2 = tmp;
336  tmp = consdata->filterpos1;
337  consdata->filterpos1 = consdata->filterpos2;
338  consdata->filterpos2 = tmp;
339  }
340  assert(watchedvar1 == -1 || watchedvar1 != consdata->watchedvar2);
341  assert(watchedvar2 == -1 || watchedvar2 != consdata->watchedvar1);
342 
343  /* drop events on old watched variables */
344  if( consdata->watchedvar1 != -1 && consdata->watchedvar1 != watchedvar1 )
345  {
346  assert(consdata->filterpos1 != -1);
347  SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
348  }
349  if( consdata->watchedvar2 != -1 && consdata->watchedvar2 != watchedvar2 )
350  {
351  assert(consdata->filterpos2 != -1);
352  SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
353  }
354 
355  /* catch events on new watched variables */
356  if( watchedvar1 != -1 && watchedvar1 != consdata->watchedvar1 )
357  {
358  SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar1, &consdata->filterpos1) );
359  }
360  if( watchedvar2 != -1 && watchedvar2 != consdata->watchedvar2 )
361  {
362  SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar2, &consdata->filterpos2) );
363  }
364 
365  /* set the new watched variables */
366  consdata->watchedvar1 = watchedvar1;
367  consdata->watchedvar2 = watchedvar2;
368 
369  return SCIP_OKAY;
370 }
371 
372 /** ensures, that the vars array can store at least num entries */
373 static
375  SCIP* scip, /**< SCIP data structure */
376  SCIP_CONSDATA* consdata, /**< linear constraint data */
377  int num /**< minimum number of entries to store */
378  )
379 {
380  assert(consdata != NULL);
381  assert(consdata->nvars <= consdata->varssize);
382 
383  if( num > consdata->varssize )
384  {
385  int newsize;
386 
387  newsize = SCIPcalcMemGrowSize(scip, num);
388  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
389  consdata->varssize = newsize;
390  }
391  assert(num <= consdata->varssize);
392 
393  return SCIP_OKAY;
394 }
395 
396 /** creates constraint data for AND-constraint */
397 static
399  SCIP* scip, /**< SCIP data structure */
400  SCIP_CONSDATA** consdata, /**< pointer to store the constraint data */
401  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
402  int nvars, /**< number of variables in the AND-constraint */
403  SCIP_VAR** vars, /**< variables in AND-constraint */
404  SCIP_VAR* resvar, /**< resultant variable */
405  SCIP_Bool checkwhenupgr, /**< should an upgraded constraint be checked despite the fact that this
406  * AND-constraint will not be checked
407  */
408  SCIP_Bool notremovablewhenupgr/**< should an upgraded constraint be despite the fact that this
409  * AND-constraint will not be checked
410  */
411  )
412 {
413  int v;
414 
415  assert(consdata != NULL);
416  assert(nvars == 0 || vars != NULL);
417  assert(resvar != NULL);
418 
419  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
420  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
421  (*consdata)->resvar = resvar;
422  (*consdata)->rows = NULL;
423  (*consdata)->aggrrow = NULL;
424  (*consdata)->nvars = nvars;
425  (*consdata)->varssize = nvars;
426  (*consdata)->nrows = 0;
427  (*consdata)->watchedvar1 = -1;
428  (*consdata)->watchedvar2 = -1;
429  (*consdata)->filterpos1 = -1;
430  (*consdata)->filterpos2 = -1;
431  (*consdata)->propagated = FALSE;
432  (*consdata)->nofixedzero = FALSE;
433  (*consdata)->impladded = FALSE;
434  (*consdata)->opimpladded = FALSE;
435  (*consdata)->sorted = FALSE;
436  (*consdata)->changed = TRUE;
437  (*consdata)->merged = FALSE;
438  (*consdata)->checkwhenupgr = checkwhenupgr;
439  (*consdata)->notremovablewhenupgr = notremovablewhenupgr;
440 
441  /* get transformed variables, if we are in the transformed problem */
442  if( SCIPisTransformed(scip) )
443  {
444  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
445  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->resvar, &(*consdata)->resvar) );
446 
447  /* catch needed events on variables */
448  SCIP_CALL( consdataCatchEvents(scip, *consdata, eventhdlr) );
449  }
450 
451  assert(SCIPvarIsBinary((*consdata)->resvar));
452 
453  /* note: currently, this constraint handler does not handle multiaggregations (e.g. during propagation), hence we forbid
454  * multiaggregation from the beginning for the involved variables
455  */
457  {
458  for( v = 0; v < (*consdata)->nvars; ++v )
459  {
460  assert((*consdata)->vars[v] != NULL);
461  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars[v]) );
462  }
463  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->resvar) );
464  }
465 
466  /* capture vars */
467  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->resvar) );
468  for( v = 0; v < (*consdata)->nvars; v++ )
469  {
470  assert((*consdata)->vars[v] != NULL);
471  assert(SCIPvarIsBinary((*consdata)->vars[v]));
472  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
473  }
474 
475 
476  return SCIP_OKAY;
477 }
478 
479 /** releases LP rows of constraint data and frees rows array */
480 static
482  SCIP* scip, /**< SCIP data structure */
483  SCIP_CONSDATA* consdata /**< constraint data */
484  )
485 {
486  int r;
487 
488  assert(consdata != NULL);
489 
490  if( consdata->rows != NULL )
491  {
492  for( r = 0; r < consdata->nrows; ++r )
493  {
494  SCIP_CALL( SCIPreleaseRow(scip, &consdata->rows[r]) );
495  }
496  SCIPfreeBlockMemoryArray(scip, &consdata->rows, consdata->nrows);
497 
498  consdata->nrows = 0;
499  }
500 
501  if( consdata->aggrrow != NULL )
502  {
503  SCIP_CALL( SCIPreleaseRow(scip, &consdata->aggrrow) );
504  consdata->aggrrow = NULL;
505  }
506 
507  return SCIP_OKAY;
508 }
509 
510 /** frees constraint data for AND-constraint */
511 static
513  SCIP* scip, /**< SCIP data structure */
514  SCIP_CONSDATA** consdata, /**< pointer to the constraint data */
515  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
516  )
517 {
518  int v;
519 
520  assert(consdata != NULL);
521  assert(*consdata != NULL);
522 
523  if( SCIPisTransformed(scip) )
524  {
525  /* drop events for watched variables */
526  SCIP_CALL( consdataSwitchWatchedvars(scip, *consdata, eventhdlr, -1, -1) );
527 
528  /* drop all other events on variables */
529  SCIP_CALL( consdataDropEvents(scip, *consdata, eventhdlr) );
530  }
531  else
532  {
533  assert((*consdata)->watchedvar1 == -1);
534  assert((*consdata)->watchedvar2 == -1);
535  }
536 
537  /* release and free the rows */
538  SCIP_CALL( consdataFreeRows(scip, *consdata) );
539 
540  /* release vars */
541  for( v = 0; v < (*consdata)->nvars; v++ )
542  {
543  assert((*consdata)->vars[v] != NULL);
544  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
545  }
546  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->resvar)) );
547 
548 
549  SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->varssize);
550  SCIPfreeBlockMemory(scip, consdata);
551 
552  return SCIP_OKAY;
553 }
554 
555 /** prints AND-constraint to file stream */
556 static
558  SCIP* scip, /**< SCIP data structure */
559  SCIP_CONSDATA* consdata, /**< AND-constraint data */
560  FILE* file /**< output file (or NULL for standard output) */
561  )
562 {
563  assert(consdata != NULL);
564 
565  /* print resultant */
566  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->resvar, TRUE) );
567 
568  /* start the variable list */
569  SCIPinfoMessage(scip, file, " == and(");
570 
571  /* print variable list */
572  SCIP_CALL( SCIPwriteVarsList(scip, file, consdata->vars, consdata->nvars, TRUE, ',') );
573 
574  /* close the variable list */
575  SCIPinfoMessage(scip, file, ")");
576 
577  return SCIP_OKAY;
578 }
579 
580 /** adds coefficient to AND-constraint */
581 static
583  SCIP* scip, /**< SCIP data structure */
584  SCIP_CONS* cons, /**< linear constraint */
585  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
586  SCIP_VAR* var /**< variable to add to the constraint */
587  )
588 {
589  SCIP_CONSDATA* consdata;
590  SCIP_Bool transformed;
591 
592  assert(var != NULL);
593 
594  consdata = SCIPconsGetData(cons);
595  assert(consdata != NULL);
596  assert(consdata->rows == NULL);
597 
598  /* are we in the transformed problem? */
599  transformed = SCIPconsIsTransformed(cons);
600 
601  /* always use transformed variables in transformed constraints */
602  if( transformed )
603  {
604  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
605  }
606  assert(var != NULL);
607  assert(transformed == SCIPvarIsTransformed(var));
608 
609  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
610  consdata->vars[consdata->nvars] = var;
611  consdata->nvars++;
612  consdata->sorted = (consdata->nvars == 1);
613  consdata->changed = TRUE;
614  consdata->merged = FALSE;
615 
616  /* capture variable */
617  SCIP_CALL( SCIPcaptureVar(scip, var) );
618 
619  /* if we are in transformed problem, catch the variable's events */
620  if( transformed )
621  {
622  /* catch bound change events of variable */
624  eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
625  }
626 
627  /* install the rounding locks for the new variable */
628  SCIP_CALL( lockRounding(scip, cons, var) );
629 
630  /**@todo update LP rows */
631  if( consdata->rows != NULL )
632  {
633  SCIPerrorMessage("cannot add coefficients to AND-constraint after LP relaxation was created\n");
634  return SCIP_INVALIDCALL;
635  }
636 
637  return SCIP_OKAY;
638 }
639 
640 /** deletes coefficient at given position from AND-constraint data */
641 static
643  SCIP* scip, /**< SCIP data structure */
644  SCIP_CONS* cons, /**< AND-constraint */
645  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
646  int pos /**< position of coefficient to delete */
647  )
648 {
649  SCIP_CONSDATA* consdata;
650 
651  assert(eventhdlr != NULL);
652 
653  consdata = SCIPconsGetData(cons);
654  assert(consdata != NULL);
655  assert(0 <= pos && pos < consdata->nvars);
656  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(consdata->vars[pos]));
657 
658  /* remove the rounding locks of the variable */
659  SCIP_CALL( unlockRounding(scip, cons, consdata->vars[pos]) );
660 
661  if( SCIPconsIsTransformed(cons) )
662  {
663  /* drop bound change events of variable */
665  eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
666  }
667 
668  if( SCIPconsIsTransformed(cons) )
669  {
670  /* if the position is watched, stop watching the position */
671  if( consdata->watchedvar1 == pos )
672  {
673  SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar2, -1) );
674  }
675  if( consdata->watchedvar2 == pos )
676  {
677  SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, consdata->watchedvar1, -1) );
678  }
679  }
680  assert(pos != consdata->watchedvar1);
681  assert(pos != consdata->watchedvar2);
682 
683  /* release variable */
684  SCIP_CALL( SCIPreleaseVar(scip, &(consdata->vars[pos])) );
685 
686  /* move the last variable to the free slot */
687  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
688  consdata->nvars--;
689 
690  /* if the last variable (that moved) was watched, update the watched position */
691  if( consdata->watchedvar1 == consdata->nvars )
692  consdata->watchedvar1 = pos;
693  if( consdata->watchedvar2 == consdata->nvars )
694  consdata->watchedvar2 = pos;
695 
696  consdata->propagated = FALSE;
697  consdata->sorted = FALSE;
698  consdata->changed = TRUE;
699 
700  return SCIP_OKAY;
701 }
702 
703 /** sorts AND-constraint's variables by non-decreasing variable index */
704 static
705 void consdataSort(
706  SCIP_CONSDATA* consdata /**< constraint data */
707  )
708 {
709  assert(consdata != NULL);
710 
711  if( !consdata->sorted )
712  {
713  if( consdata->nvars <= 1 )
714  consdata->sorted = TRUE;
715  else
716  {
717  SCIP_VAR* var1 = NULL;
718  SCIP_VAR* var2 = NULL;
719 
720  /* remember watch variables */
721  if( consdata->watchedvar1 != -1 )
722  {
723  var1 = consdata->vars[consdata->watchedvar1];
724  assert(var1 != NULL);
725  consdata->watchedvar1 = -1;
726  if( consdata->watchedvar2 != -1 )
727  {
728  var2 = consdata->vars[consdata->watchedvar2];
729  assert(var2 != NULL);
730  consdata->watchedvar2 = -1;
731  }
732  }
733  assert(consdata->watchedvar1 == -1);
734  assert(consdata->watchedvar2 == -1);
735  assert(var1 != NULL || var2 == NULL);
736 
737  /* sort variables after index */
738  SCIPsortPtr((void**)consdata->vars, SCIPvarComp, consdata->nvars);
739  consdata->sorted = TRUE;
740 
741  /* correct watched variables */
742  if( var1 != NULL )
743  {
744  int pos;
745 #ifndef NDEBUG
746  SCIP_Bool found;
747 
748  found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
749  assert(found);
750 #else
751  SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
752 #endif
753  assert(pos >= 0 && pos < consdata->nvars);
754  consdata->watchedvar1 = pos;
755 
756  if( var2 != NULL )
757  {
758 #ifndef NDEBUG
759  found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
760  assert(found);
761 #else
762  SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
763 #endif
764  assert(pos >= 0 && pos < consdata->nvars);
765  consdata->watchedvar2 = pos;
766  }
767  }
768  }
769  }
770 
771 #ifdef SCIP_DEBUG
772  /* check sorting */
773  {
774  int v;
775 
776  for( v = 0; v < consdata->nvars; ++v )
777  {
778  assert(v == consdata->nvars-1 || SCIPvarCompare(consdata->vars[v], consdata->vars[v+1]) <= 0);
779  }
780  }
781 #endif
782 }
783 
784 /** deletes all one-fixed variables */
785 static
787  SCIP* scip, /**< SCIP data structure */
788  SCIP_CONS* cons, /**< AND-constraint */
789  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
790  int* nchgcoefs /**< pointer to add up the number of changed coefficients */
791  )
792 {
793  SCIP_CONSDATA* consdata;
794  SCIP_VAR* var;
795  int v;
796 
797  assert(scip != NULL);
798  assert(cons != NULL);
799  assert(eventhdlr != NULL);
800  assert(nchgcoefs != NULL);
801 
802  consdata = SCIPconsGetData(cons);
803  assert(consdata != NULL);
804  assert(consdata->nvars == 0 || consdata->vars != NULL);
805 
806  v = 0;
807  while( v < consdata->nvars )
808  {
809  var = consdata->vars[v];
810  assert(SCIPvarIsBinary(var));
811 
812  if( SCIPvarGetLbGlobal(var) > 0.5 )
813  {
814  assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), 1.0));
815  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
816  (*nchgcoefs)++;
817  }
818  else
819  {
820  SCIP_VAR* repvar;
821  SCIP_Bool negated;
822 
823  /* get binary representative of variable */
824  SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
825 
826  /* check, if the variable should be replaced with the representative */
827  if( repvar != var )
828  {
829  /* delete old (aggregated) variable */
830  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
831 
832  /* add representative instead */
833  SCIP_CALL( addCoef(scip, cons, eventhdlr, repvar) );
834  }
835  else
836  ++v;
837  }
838  }
839 
840 #if 0 /* does not work with pseudoboolean constraint handler, need to be fixed */
841  /* check, if the resultant should be replaced with the active representative */
842  if( !SCIPvarIsActive(consdata->resvar) )
843  {
844  SCIP_VAR* repvar;
845  SCIP_Bool negated;
846 
847  /* get binary representative of variable */
848  SCIP_CALL( SCIPgetBinvarRepresentative(scip, consdata->resvar, &repvar, &negated) );
849  assert(SCIPvarIsBinary(repvar));
850 
851  /* check, if the variable should be replaced with the representative */
852  if( repvar != consdata->resvar )
853  {
854  if( SCIPconsIsTransformed(cons) )
855  {
856  /* drop bound change events of old resultant */
857  SCIP_CALL( SCIPdropVarEvent(scip, consdata->resvar, SCIP_EVENTTYPE_BOUNDCHANGED,
858  eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
859 
860  /* catch bound change events of new resultant */
862  eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
863  }
864 
865  /* release old resultant */
866  SCIP_CALL( SCIPreleaseVar(scip, &(consdata->resvar)) );
867 
868  /* capture new resultant */
869  SCIP_CALL( SCIPcaptureVar(scip, repvar) );
870 
871  consdata->resvar = repvar;
872  consdata->changed = TRUE;
873  }
874  }
875 #endif
876 
877  SCIPdebugMessage("after fixings: ");
878  SCIPdebug( SCIP_CALL(consdataPrint(scip, consdata, NULL)) );
879  SCIPdebugPrintf("\n");
880 
881  return SCIP_OKAY;
882 }
883 
884 /** creates a linearization of the AND-constraint */
885 static
887  SCIP* scip, /**< SCIP data structure */
888  SCIP_CONS* cons /**< constraint to check */
889  )
890 {
891  SCIP_CONSDATA* consdata;
892  char rowname[SCIP_MAXSTRLEN];
893  int nvars;
894  int i;
895 
896  consdata = SCIPconsGetData(cons);
897  assert(consdata != NULL);
898  assert(consdata->rows == NULL);
899 
900  nvars = consdata->nvars;
901 
902  /* get memory for rows */
903  consdata->nrows = nvars + 1;
904  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->rows, consdata->nrows) );
905 
906  /* creates LP rows corresponding to AND-constraint:
907  * - one additional row: resvar - v1 - ... - vn >= 1-n
908  * - for each operator variable vi: resvar - vi <= 0
909  */
910 
911  /* create additional row */
912  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_add", SCIPconsGetName(cons));
913  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[0], SCIPconsGetHdlr(cons), rowname, -consdata->nvars + 1.0, SCIPinfinity(scip),
915  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[0], consdata->resvar, 1.0) );
916  SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->rows[0], nvars, consdata->vars, -1.0) );
917 
918  /* create operator rows */
919  for( i = 0; i < nvars; ++i )
920  {
921  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), i);
922  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[i+1], SCIPconsGetHdlr(cons), rowname, -SCIPinfinity(scip), 0.0,
924  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i+1], consdata->resvar, 1.0) );
925  SCIP_CALL( SCIPaddVarToRow(scip, consdata->rows[i+1], consdata->vars[i], -1.0) );
926  }
927 
928  return SCIP_OKAY;
929 }
930 
931 /** adds linear relaxation of AND-constraint to the LP */
932 static
934  SCIP* scip, /**< SCIP data structure */
935  SCIP_CONS* cons /**< constraint to check */
936  )
937 {
938  SCIP_CONSDATA* consdata;
939  SCIP_Bool infeasible;
940 
941 
942  /* in the root LP we only add the weaker relaxation which consists of two rows:
943  * - one additional row: resvar - v1 - ... - vn >= 1-n
944  * - aggregated row: n*resvar - v1 - ... - vn <= 0.0
945  *
946  * during separation we separate the stronger relaxation which consists of n+1 row:
947  * - one additional row: resvar - v1 - ... - vn >= 1-n
948  * - for each operator variable vi: resvar - vi <= 0.0
949  */
950 
951  consdata = SCIPconsGetData(cons);
952  assert(consdata != NULL);
953 
954  if( consdata->rows == NULL )
955  {
956  /* create the n+1 row relaxation */
957  SCIP_CALL( createRelaxation(scip, cons) );
958  }
959 
960  /* create the aggregated row */
961  if( consdata->aggrrow == NULL )
962  {
963  char rowname[SCIP_MAXSTRLEN];
964 
965  (void) SCIPsnprintf(rowname, SCIP_MAXSTRLEN, "%s_operators", SCIPconsGetName(cons));
966  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->aggrrow, SCIPconsGetHdlr(cons), rowname, -SCIPinfinity(scip), 0.0,
968  SCIP_CALL( SCIPaddVarToRow(scip, consdata->aggrrow, consdata->resvar, (SCIP_Real) consdata->nvars) );
969  SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->aggrrow, consdata->nvars, consdata->vars, -1.0) );
970  }
971 
972  /* insert aggregated LP row as cut */
973  if( !SCIProwIsInLP(consdata->aggrrow) )
974  {
975  SCIP_CALL( SCIPaddCut(scip, NULL, consdata->aggrrow, FALSE, &infeasible) );
976  assert(!infeasible); /* this function is only called by initlp() -> the cuts should be feasible */
977  }
978 
979  /* add additional row */
980  if( !SCIProwIsInLP(consdata->rows[0]) )
981  {
982  SCIP_CALL( SCIPaddCut(scip, NULL, consdata->rows[0], FALSE, &infeasible) );
983  assert( ! infeasible ); /* this function is only called by initlp() -> the cuts should be feasible */
984  }
985 
986  return SCIP_OKAY;
987 }
988 
989 /** checks AND-constraint for feasibility of given solution: returns TRUE iff constraint is feasible */
990 static
992  SCIP* scip, /**< SCIP data structure */
993  SCIP_CONS* cons, /**< constraint to check */
994  SCIP_SOL* sol, /**< solution to check, NULL for current solution */
995  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
996  SCIP_Bool printreason, /**< Should the reason for the violation be printed? */
997  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
998  )
999 {
1000  SCIP_CONSDATA* consdata;
1001  SCIP_Bool mustcheck;
1002  int r;
1003 
1004  assert(violated != NULL);
1005 
1006  consdata = SCIPconsGetData(cons);
1007  assert(consdata != NULL);
1008 
1009  *violated = FALSE;
1010 
1011  /* check whether we can skip this feasibility check, because all rows are in the LP and do not have to be checked */
1012  mustcheck = checklprows;
1013  mustcheck = mustcheck || (consdata->rows == NULL);
1014  if( !mustcheck )
1015  {
1016  assert(consdata->rows != NULL);
1017 
1018  for( r = 0; r < consdata->nrows; ++r )
1019  {
1020  mustcheck = !SCIProwIsInLP(consdata->rows[r]);
1021  if( mustcheck )
1022  break;
1023  }
1024  }
1025 
1026  /* check feasibility of constraint if necessary */
1027  if( mustcheck )
1028  {
1029  SCIP_Real solval;
1030  int i;
1031 
1032  /* increase age of constraint; age is reset to zero, if a violation was found only in case we are in
1033  * enforcement
1034  */
1035  if( sol == NULL )
1036  {
1037  SCIP_CALL( SCIPincConsAge(scip, cons) );
1038  }
1039 
1040  /* check, if all operator variables are TRUE */
1041  for( i = 0; i < consdata->nvars; ++i )
1042  {
1043  solval = SCIPgetSolVal(scip, sol, consdata->vars[i]);
1044 
1045  /* @todo If "upgraded resultants to varstatus implicit" is fully allowed, than the following assert does not hold
1046  * anymore, therefor we need to stop the check and return with the status not violated, because the
1047  * integrality condition of this violated operand needs to be enforced by another constraint.
1048  *
1049  * The above should be asserted by marking the constraint handler, for which the result needs to be
1050  * SCIP_SEPARATED if the origin was the CONSENFOPS or the CONSENFOLP callback or SCIP_INFEASIBLE if the
1051  * origin was CONSCHECK callback.
1052  *
1053  */
1054  assert(SCIPisFeasIntegral(scip, solval));
1055  if( solval < 0.5 )
1056  break;
1057  }
1058 
1059  /* if all operator variables are TRUE, the resultant has to be TRUE, otherwise, the resultant has to be FALSE;
1060  * in case of an implicit integer resultant variable, we need to ensure the integrality of the solution value
1061  */
1062  solval = SCIPgetSolVal(scip, sol, consdata->resvar);
1063  assert(SCIPvarGetType(consdata->resvar) == SCIP_VARTYPE_IMPLINT || SCIPisFeasIntegral(scip, solval));
1064 
1065  if( !SCIPisFeasIntegral(scip, solval) || (i == consdata->nvars) != (solval > 0.5) )
1066  {
1067  *violated = TRUE;
1068 
1069  /* only reset constraint age if we are in enforcement */
1070  if( sol == NULL )
1071  {
1072  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1073  }
1074 
1075  if( printreason )
1076  {
1077  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
1078  SCIPinfoMessage(scip, NULL, ";\n");
1079  SCIPinfoMessage(scip, NULL, "violation:");
1080  if( !SCIPisFeasIntegral(scip, solval) )
1081  {
1082  SCIPinfoMessage(scip, NULL, " resultant variable <%s> has fractional solution value %" SCIP_REAL_FORMAT "\n",
1083  SCIPvarGetName(consdata->resvar), solval);
1084  }
1085  else if( i == consdata->nvars )
1086  {
1087  SCIPinfoMessage(scip, NULL, " all operands are TRUE and resultant <%s> = FALSE\n",
1088  SCIPvarGetName(consdata->resvar));
1089  }
1090  else
1091  {
1092  SCIPinfoMessage(scip, NULL, " operand <%s> = FALSE and resultant <%s> = TRUE\n",
1093  SCIPvarGetName(consdata->vars[i]), SCIPvarGetName(consdata->resvar));
1094  }
1095  }
1096  }
1097  }
1098 
1099  return SCIP_OKAY;
1100 }
1101 
1102 /** separates given primal solution */
1103 static
1105  SCIP* scip, /**< SCIP data structure */
1106  SCIP_CONS* cons, /**< constraint to check */
1107  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
1108  SCIP_Bool* separated, /**< pointer to store whether a cut was found */
1109  SCIP_Bool* cutoff /**< whether a cutoff has been detected */
1110  )
1111 {
1112  SCIP_CONSDATA* consdata;
1113  SCIP_Real feasibility;
1114  int r;
1115 
1116  assert(separated != NULL);
1117  assert(cutoff != NULL);
1118 
1119  *separated = FALSE;
1120  *cutoff = FALSE;
1121 
1122  consdata = SCIPconsGetData(cons);
1123  assert(consdata != NULL);
1124 
1125  /* create all necessary rows for the linear relaxation */
1126  if( consdata->rows == NULL )
1127  {
1128  SCIP_CALL( createRelaxation(scip, cons) );
1129  }
1130  assert(consdata->rows != NULL);
1131 
1132  /* test all rows for feasibility and add infeasible rows */
1133  for( r = 0; r < consdata->nrows; ++r )
1134  {
1135  if( !SCIProwIsInLP(consdata->rows[r]) )
1136  {
1137  feasibility = SCIPgetRowSolFeasibility(scip, consdata->rows[r], sol);
1138  if( SCIPisFeasNegative(scip, feasibility) )
1139  {
1140  SCIP_CALL( SCIPaddCut(scip, sol, consdata->rows[r], FALSE, cutoff) );
1141  if ( *cutoff )
1142  return SCIP_OKAY;
1143  *separated = TRUE;
1144  }
1145  }
1146  }
1147 
1148  return SCIP_OKAY;
1149 }
1150 
1151 /** analyzes conflicting TRUE assignment to resultant of given constraint, and adds conflict constraint to problem */
1152 static
1154  SCIP* scip, /**< SCIP data structure */
1155  SCIP_CONS* cons, /**< AND-constraint that detected the conflict */
1156  int falsepos /**< position of operand that is fixed to FALSE */
1157  )
1158 {
1159  SCIP_CONSDATA* consdata;
1160 
1161  /* conflict analysis can only be applied in solving stage and if it turned on */
1163  return SCIP_OKAY;
1164 
1165  consdata = SCIPconsGetData(cons);
1166  assert(consdata != NULL);
1167  assert(SCIPvarGetLbLocal(consdata->resvar) > 0.5);
1168  assert(0 <= falsepos && falsepos < consdata->nvars);
1169  assert(SCIPvarGetUbLocal(consdata->vars[falsepos]) < 0.5);
1170 
1171  /* initialize conflict analysis, and add resultant and single operand variable to conflict candidate queue */
1173  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1174  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[falsepos]) );
1175 
1176  /* analyze the conflict */
1177  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
1178 
1179  return SCIP_OKAY;
1180 }
1181 
1182 /** analyzes conflicting FALSE assignment to resultant of given constraint, and adds conflict constraint to problem */
1183 static
1185  SCIP* scip, /**< SCIP data structure */
1186  SCIP_CONS* cons /**< or constraint that detected the conflict */
1187  )
1188 {
1189  SCIP_CONSDATA* consdata;
1190  int v;
1191 
1192  assert(!SCIPconsIsModifiable(cons));
1193 
1194  /* conflict analysis can only be applied in solving stage and if it is applicable */
1196  return SCIP_OKAY;
1197 
1198  consdata = SCIPconsGetData(cons);
1199  assert(consdata != NULL);
1200  assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
1201 
1202  /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
1204  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1205  for( v = 0; v < consdata->nvars; ++v )
1206  {
1207  assert(SCIPvarGetLbLocal(consdata->vars[v]) > 0.5);
1208  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
1209  }
1210 
1211  /* analyze the conflict */
1212  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
1213 
1214  return SCIP_OKAY;
1215 }
1216 
1217 /** tries to fix the given resultant to zero */
1218 static
1220  SCIP* scip, /**< SCIP data structure */
1221  SCIP_CONS* cons, /**< AND-constraint to be processed */
1222  SCIP_VAR* resvar, /**< resultant variable to fix to zero */
1223  int pos, /**< position of operand that is fixed to FALSE */
1224  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1225  int* nfixedvars /**< pointer to add up the number of found domain reductions */
1226  )
1227 {
1228  SCIP_Bool infeasible;
1229  SCIP_Bool tightened;
1230 
1231  SCIPdebugMessage("constraint <%s>: operator %d fixed to 0.0 -> fix resultant <%s> to 0.0\n",
1232  SCIPconsGetName(cons), pos, SCIPvarGetName(resvar));
1233 
1234  SCIP_CALL( SCIPinferBinvarCons(scip, resvar, FALSE, cons, (int)PROPRULE_1, &infeasible, &tightened) );
1235 
1236  if( infeasible )
1237  {
1238  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1239  SCIP_CALL( analyzeConflictOne(scip, cons, pos) );
1240  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1241  (*cutoff) = TRUE;
1242  }
1243  else
1244  {
1245  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1246  if( tightened )
1247  {
1248  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1249  (*nfixedvars)++;
1250  }
1251  }
1252 
1253  return SCIP_OKAY;
1254 }
1255 
1256 /** fix all operands to one */
1257 static
1259  SCIP* scip, /**< SCIP data structure */
1260  SCIP_CONS* cons, /**< AND-constraint to be processed */
1261  SCIP_VAR** vars, /**< array of operands */
1262  int nvars, /**< number of operands */
1263  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1264  int* nfixedvars /**< pointer to add up the number of found domain reductions */
1265  )
1266 {
1267  SCIP_Bool infeasible;
1268  SCIP_Bool tightened;
1269  int v;
1270 
1271  for( v = 0; v < nvars && !(*cutoff); ++v )
1272  {
1273  SCIPdebugMessage("constraint <%s>: resultant fixed to 1.0 -> fix operator var <%s> to 1.0\n",
1274  SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
1275 
1276  SCIP_CALL( SCIPinferBinvarCons(scip, vars[v], TRUE, cons, (int)PROPRULE_2, &infeasible, &tightened) );
1277 
1278  if( infeasible )
1279  {
1280  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1281  SCIP_CALL( analyzeConflictOne(scip, cons, v) );
1282  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1283  (*cutoff) = TRUE;
1284  }
1285  else if( tightened )
1286  {
1287  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1288  (*nfixedvars)++;
1289  }
1290  }
1291 
1292  if( !(*cutoff) )
1293  {
1294  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1295  }
1296 
1297  return SCIP_OKAY;
1298 }
1299 
1300 /** linearize AND-constraint due to a globally to zero fixed resultant; that is, creates, adds, and releases a logicor
1301  * constraint and remove the AND-constraint globally.
1302  *
1303  * Since the resultant is fixed to zero the AND-constraint collapses to linear constraint of the form:
1304  *
1305  * - \f$\sum_{i=0}^{n-1} v_i \leq n-1\f$
1306  *
1307  * This can be transformed into a logicor constraint of the form
1308  *
1309  * - \f$\sum_{i=0}^{n-1} ~v_i \geq 1\f$
1310  */
1311 static
1313  SCIP* scip, /**< SCIP data structure */
1314  SCIP_CONS* cons, /**< AND-constraint to linearize */
1315  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1316  int* nfixedvars, /**< pointer to add up the number of found domain reductions */
1317  int* nupgdconss /**< pointer to add up the number of upgraded constraints */
1318  )
1319 {
1320  SCIP_CONSDATA* consdata;
1321  SCIP_VAR** vars;
1322  SCIP_CONS* lincons;
1323  SCIP_Bool conscreated;
1324  int nvars;
1325 
1326  consdata = SCIPconsGetData(cons);
1327  assert(consdata != NULL);
1328 
1329  assert(!(*cutoff));
1330  assert(SCIPvarGetUbGlobal(consdata->resvar) < 0.5);
1331 
1332  nvars = consdata->nvars;
1333  conscreated = FALSE;
1334 
1335  /* allocate memory for variables for updated constraint */
1336  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
1337 
1338  /* if we only have two variables, we prefer a set packing constraint instead of a logicor constraint */
1339  if( nvars == 2 && !SCIPconsIsModifiable(cons) )
1340  {
1341  SCIP_Bool* negated;
1342  SCIP_Bool infeasible;
1343  SCIP_Bool tightened;
1344 
1345  /* get active representation */
1346  SCIP_CALL( SCIPallocBufferArray(scip, &negated, nvars) );
1347  SCIP_CALL( SCIPgetBinvarRepresentatives(scip, nvars, consdata->vars, vars, negated) );
1348  SCIPfreeBufferArray(scip, &negated);
1349 
1350  /* if one of the two operators is globally fixed to one it follows that the other has to be zero */
1351  if( SCIPvarGetLbGlobal(vars[0]) > 0.5 )
1352  {
1353  SCIP_CALL( SCIPfixVar(scip, vars[1], 0.0, &infeasible, &tightened) );
1354 
1355  if( infeasible )
1356  *cutoff = TRUE;
1357  else if( tightened )
1358  ++(*nfixedvars);
1359  }
1360  else if( SCIPvarGetLbGlobal(vars[1]) > 0.5 )
1361  {
1362  SCIP_CALL( SCIPfixVar(scip, vars[0], 0.0, &infeasible, &tightened) );
1363 
1364  if( infeasible )
1365  *cutoff = TRUE;
1366  else if( tightened )
1367  ++(*nfixedvars);
1368  }
1369  else if( SCIPvarGetUbGlobal(vars[0]) > 0.5 && SCIPvarGetUbGlobal(vars[1]) > 0.5 )
1370  {
1371  /* create, add, and release the setppc constraint */
1372  SCIP_CALL( SCIPcreateConsSetpack(scip, &lincons, SCIPconsGetName(cons), nvars, vars,
1374  consdata->checkwhenupgr || SCIPconsIsChecked(cons),
1376  !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
1377 
1378  conscreated = TRUE;
1379  }
1380  }
1381  else
1382  {
1383  int v;
1384 
1385  /* collect negated variables */
1386  for( v = 0; v < nvars; ++v )
1387  {
1388  SCIP_CALL( SCIPgetNegatedVar(scip, consdata->vars[v], &vars[v]) );
1389  }
1390 
1391  /* create, add, and release the logicor constraint */
1392  SCIP_CALL( SCIPcreateConsLogicor(scip, &lincons, SCIPconsGetName(cons), nvars, vars,
1394  consdata->checkwhenupgr || SCIPconsIsChecked(cons),
1396  !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
1397 
1398  conscreated = TRUE;
1399  }
1400 
1401  if( conscreated )
1402  {
1403  /* add and release new constraint */
1404  SCIPdebugPrintCons(scip, lincons, NULL); /*lint !e644*/
1405  SCIP_CALL( SCIPaddCons(scip, lincons) ); /*lint !e644*/
1406  SCIP_CALL( SCIPreleaseCons(scip, &lincons) ); /*lint !e644*/
1407 
1408  ++(*nupgdconss);
1409  }
1410 
1411  /* remove the AND-constraint globally */
1412  SCIP_CALL( SCIPdelCons(scip, cons) );
1413 
1414  /* delete temporary memory */
1415  SCIPfreeBufferArray(scip, &vars);
1416 
1417  return SCIP_OKAY;
1418 }
1419 
1420 /** the resultant is fixed to zero; in case all except one operator are fixed to TRUE the last operator has to fixed to FALSE */
1421 /** @note consdata->watchedvars might not be the same to the watchedvar parameters, because the update was not yet done */
1422 static
1424  SCIP* scip, /**< SCIP data structure */
1425  SCIP_CONS* cons, /**< AND-constraint to be processed */
1426  int watchedvar1, /**< maybe last unfixed variable position */
1427  int watchedvar2, /**< second watched position */
1428  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1429  int* nfixedvars /**< pointer to add up the number of found domain reductions */
1430  )
1431 {
1432  SCIP_CONSDATA* consdata;
1433 
1434  consdata = SCIPconsGetData(cons);
1435  assert(consdata != NULL);
1436  assert(SCIPvarGetUbLocal(consdata->resvar) < 0.5);
1437 
1438  if( watchedvar2 == -1 )
1439  {
1440  SCIP_Bool infeasible;
1441  SCIP_Bool tightened;
1442 
1443  assert(watchedvar1 != -1);
1444 
1445 #ifndef NDEBUG
1446  /* check that all variables regardless of wathcedvar1 are fixed to 1 */
1447  {
1448  int v;
1449 
1450  for( v = consdata->nvars - 1; v >= 0; --v )
1451  if( v != watchedvar1 )
1452  assert(SCIPvarGetLbLocal(consdata->vars[v]) > 0.5);
1453  }
1454 #endif
1455 
1456  SCIPdebugMessage("constraint <%s>: resultant <%s> fixed to 0.0, only one unfixed operand -> fix operand <%s> to 0.0\n",
1457  SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar), SCIPvarGetName(consdata->vars[watchedvar1]));
1458 
1459  SCIP_CALL( SCIPinferBinvarCons(scip, consdata->vars[watchedvar1], FALSE, cons, (int)PROPRULE_4, &infeasible, &tightened) );
1460 
1461  if( infeasible )
1462  {
1463  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1464  SCIP_CALL( analyzeConflictZero(scip, cons) );
1465  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1466  *cutoff = TRUE;
1467  }
1468  else
1469  {
1470  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1471  if( tightened )
1472  {
1473  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1474  (*nfixedvars)++;
1475  }
1476  }
1477  }
1478 
1479  return SCIP_OKAY;
1480 }
1481 
1482 /** replaces multiple occurrences of variables */
1483 static
1485  SCIP* scip, /**< SCIP data structure */
1486  SCIP_CONS* cons, /**< AND-constraint */
1487  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1488  unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
1489  int* nentries, /**< pointer for array size, if array will be to small it's corrected */
1490  int* nfixedvars, /**< pointer to store number of fixed variables */
1491  int* nchgcoefs, /**< pointer to store number of changed coefficients */
1492  int* ndelconss /**< pointer to store number of deleted constraints */
1493  )
1494 {
1495  SCIP_CONSDATA* consdata;
1496  SCIP_VAR** vars;
1497  SCIP_VAR* var;
1498  SCIP_VAR* probvar;
1499  int probidx;
1500  int nvars;
1501  int v;
1502 #ifndef NDEBUG
1503  int nbinvars;
1504  int nintvars;
1505  int nimplvars;
1506 #endif
1507 
1508  assert(scip != NULL);
1509  assert(cons != NULL);
1510  assert(eventhdlr != NULL);
1511  assert(*entries != NULL);
1512  assert(nentries != NULL);
1513  assert(nfixedvars != NULL);
1514  assert(nchgcoefs != NULL);
1515  assert(ndelconss != NULL);
1516 
1517  consdata = SCIPconsGetData(cons);
1518  assert(consdata != NULL);
1519 
1520  if( consdata->merged )
1521  return SCIP_OKAY;
1522 
1523  /* nothing to merge */
1524  if( consdata->nvars <= 1 )
1525  {
1526  consdata->merged = TRUE;
1527  return SCIP_OKAY;
1528  }
1529 
1530  vars = consdata->vars;
1531  nvars = consdata->nvars;
1532 
1533  assert(vars != NULL);
1534  assert(nvars >= 2);
1535 
1536 #ifndef NDEBUG
1537  nbinvars = SCIPgetNBinVars(scip);
1538  nintvars = SCIPgetNIntVars(scip);
1539  nimplvars = SCIPgetNImplVars(scip);
1540  assert(*nentries >= nbinvars + nintvars + nimplvars);
1541 #endif
1542 
1543  /* initialize entries array */
1544  for( v = nvars - 1; v >= 0; --v )
1545  {
1546  var = vars[v];
1547  assert(var != NULL);
1548  assert(SCIPvarIsActive(var) || (SCIPvarIsNegated(var) && SCIPvarIsActive(SCIPvarGetNegatedVar(var))));
1549 
1550  probvar = (SCIPvarIsActive(var) ? var : SCIPvarGetNegatedVar(var));
1551  assert(probvar != NULL);
1552 
1553  probidx = SCIPvarGetProbindex(probvar);
1554  assert(0 <= probidx);
1555 
1556  /* check variable type, either pure binary or an integer/implicit integer variable with 0/1 bounds */
1557  assert((probidx < nbinvars && SCIPvarGetType(probvar) == SCIP_VARTYPE_BINARY)
1558  || (SCIPvarIsBinary(probvar) &&
1559  ((probidx >= nbinvars && probidx < nbinvars + nintvars && SCIPvarGetType(probvar) == SCIP_VARTYPE_INTEGER) ||
1560  (probidx >= nbinvars + nintvars && probidx < nbinvars + nintvars + nimplvars &&
1561  SCIPvarGetType(probvar) == SCIP_VARTYPE_IMPLINT))));
1562 
1563  /* var is not active yet */
1564  (*entries)[probidx] = 0;
1565  }
1566 
1567  /* search for multiple variables; scan from back to front because deletion doesn't affect the order of the front
1568  * variables
1569  * @note don't reorder variables because we would loose the watched variables and filter position inforamtion
1570  */
1571  for( v = nvars - 1; v >= 0; --v )
1572  {
1573  var = vars[v];
1574  assert(var != NULL);
1575  assert(SCIPvarIsActive(var) || (SCIPvarIsNegated(var) && SCIPvarIsActive(SCIPvarGetNegatedVar(var))));
1576 
1577  probvar = (SCIPvarIsActive(var) ? var : SCIPvarGetNegatedVar(var));
1578  assert(probvar != NULL);
1579 
1580  probidx = SCIPvarGetProbindex(probvar);
1581  assert(0 <= probidx && probidx < *nentries);
1582 
1583  /* if var occurs first time in constraint init entries array */
1584  if( (*entries)[probidx] == 0 )
1585  {
1586  (*entries)[probidx] = (SCIPvarIsActive(var) ? 1 : 2);
1587  }
1588  /* if var occurs second time in constraint, first time it was not negated */
1589  else if( ((*entries)[probidx] == 1 && SCIPvarIsActive(var)) || ((*entries)[probidx] == 2 && !SCIPvarIsActive(var)) )
1590  {
1591  /* delete the multiple variable */
1592  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
1593  ++(*nchgcoefs);
1594  }
1595  else
1596  {
1597  SCIP_Bool infeasible;
1598  SCIP_Bool fixed;
1599 
1600  assert(((*entries)[probidx] == 1 && !SCIPvarIsActive(var)) || ((*entries)[probidx] == 2 && SCIPvarIsActive(var)));
1601 
1602  SCIPdebugMessage("AND-constraint <%s> is redundant: variable <%s> and its negation are present -> fix resultant <%s> = 0\n",
1603  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(consdata->resvar));
1604 
1605  /* negation of the variable is already present in the constraint: fix resultant to zero */
1606 #ifndef NDEBUG
1607  {
1608  int i;
1609  for( i = consdata->nvars - 1; i > v && var != SCIPvarGetNegatedVar(vars[i]); --i )
1610  {}
1611  assert(i > v);
1612  }
1613 #endif
1614 
1615  SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
1616  assert(!infeasible);
1617  if( fixed )
1618  ++(*nfixedvars);
1619 
1620  SCIP_CALL( SCIPdelCons(scip, cons) );
1621  break;
1622  }
1623  }
1624 
1625  consdata->merged = TRUE;
1626 
1627  return SCIP_OKAY;
1628 }
1629 
1630 /** propagates constraint with the following rules:
1631  * (1) v_i = FALSE => r = FALSE
1632  * (2) r = TRUE => v_i = TRUE for all i
1633  * (3) v_i = TRUE for all i => r = TRUE
1634  * (4) r = FALSE, v_i = TRUE for all i except j => v_j = FALSE
1635  *
1636  * additional if the resultant is fixed to zero during presolving or in the root node (globally), then the
1637  * AND-constraint is collapsed to a linear (logicor) constraint of the form
1638  * -> sum_{i=0}^{n-1} ~v_i >= 1
1639  */
1640 static
1642  SCIP* scip, /**< SCIP data structure */
1643  SCIP_CONS* cons, /**< AND-constraint to be processed */
1644  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1645  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1646  int* nfixedvars, /**< pointer to add up the number of found domain reductions */
1647  int* nupgdconss /**< pointer to add up the number of upgraded constraints */
1648  )
1649 {
1650  SCIP_CONSDATA* consdata;
1651  SCIP_VAR* resvar;
1652  SCIP_VAR** vars;
1653  int nvars;
1654  int watchedvar1;
1655  int watchedvar2;
1656  int i;
1657  SCIP_Bool infeasible;
1658  SCIP_Bool tightened;
1659 
1660  assert(cutoff != NULL);
1661  assert(nfixedvars != NULL);
1662 
1663  consdata = SCIPconsGetData(cons);
1664  assert(consdata != NULL);
1665 
1666  resvar = consdata->resvar;
1667  vars = consdata->vars;
1668  nvars = consdata->nvars;
1669 
1670  /* don't process the constraint, if none of the operator variables was fixed to FALSE, and if the watched variables
1671  * and the resultant weren't fixed to any value since last propagation call
1672  */
1673  if( consdata->propagated )
1674  {
1675  assert(consdata->nofixedzero);
1676  assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(resvar), 0.0));
1677  return SCIP_OKAY;
1678  }
1679 
1680  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
1681  if( !SCIPinRepropagation(scip) )
1682  {
1683  SCIP_CALL( SCIPincConsAge(scip, cons) );
1684  }
1685 
1686  /* if one of the operator variables was fixed to FALSE, the resultant can be fixed to FALSE (rule (1)) */
1687  if( !consdata->nofixedzero )
1688  {
1689  for( i = 0; i < nvars && SCIPvarGetUbLocal(vars[i]) > 0.5; ++i ) /* search for operator fixed to zero */
1690  {}
1691  if( i < nvars )
1692  {
1693  /* fix resultant to zero */
1694  SCIP_CALL( consdataFixResultantZero(scip, cons, resvar, i, cutoff, nfixedvars) );
1695  }
1696  else
1697  consdata->nofixedzero = TRUE;
1698  }
1699 
1700  /* check if resultant variables is globally fixed to zero */
1701  if( !SCIPinProbing(scip) && SCIPvarGetUbGlobal(resvar) < 0.5 )
1702  {
1703  SCIP_CALL( consdataLinearize(scip, cons, cutoff, nfixedvars, nupgdconss) );
1704 
1705  if( *cutoff && SCIPgetDepth(scip) > 0 )
1706  {
1707  /* we are done with solving since a global bound change was infeasible */
1708  SCIP_CALL( SCIPcutoffNode(scip, SCIPgetRootNode(scip)) );
1709  }
1710 
1711  return SCIP_OKAY;
1712  }
1713 
1714  /* if the resultant and at least one operand are locally fixed to zero, the constraint is locally redundant */
1715  if( SCIPvarGetUbLocal(resvar) < 0.5 && !consdata->nofixedzero )
1716  {
1717  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1718  return SCIP_OKAY;
1719  }
1720 
1721  /* if resultant is fixed to TRUE, all operator variables can be fixed to TRUE (rule (2)) */
1722  if( SCIPvarGetLbLocal(resvar) > 0.5 )
1723  {
1724  /* fix operands to one */
1725  SCIP_CALL( consdataFixOperandsOne(scip, cons, vars, nvars, cutoff, nfixedvars) );
1726 
1727  return SCIP_OKAY;
1728  }
1729 
1730  /* rules (3) and (4) can only be applied, if we know all operator variables */
1731  if( SCIPconsIsModifiable(cons) )
1732  return SCIP_OKAY;
1733 
1734  /* rules (3) and (4) cannot be applied, if we have at least two unfixed variables left;
1735  * that means, we only have to watch (i.e. capture events) of two variables, and switch to other variables
1736  * if these ones get fixed
1737  */
1738  watchedvar1 = consdata->watchedvar1;
1739  watchedvar2 = consdata->watchedvar2;
1740 
1741  /* check, if watched variables are still unfixed */
1742  if( watchedvar1 != -1 )
1743  {
1744  assert(SCIPvarGetUbLocal(vars[watchedvar1]) > 0.5); /* otherwise, rule (1) could be applied */
1745  if( SCIPvarGetLbLocal(vars[watchedvar1]) > 0.5 )
1746  watchedvar1 = -1;
1747  }
1748  if( watchedvar2 != -1 )
1749  {
1750  assert(SCIPvarGetUbLocal(vars[watchedvar2]) > 0.5); /* otherwise, rule (1) could be applied */
1751  if( SCIPvarGetLbLocal(vars[watchedvar2]) > 0.5 )
1752  watchedvar2 = -1;
1753  }
1754 
1755  /* if only one watched variable is still unfixed, make it the first one */
1756  if( watchedvar1 == -1 )
1757  {
1758  watchedvar1 = watchedvar2;
1759  watchedvar2 = -1;
1760  }
1761  assert(watchedvar1 != -1 || watchedvar2 == -1);
1762 
1763  /* if the watched variables are invalid (fixed), find new ones if existing */
1764  if( watchedvar2 == -1 )
1765  {
1766  for( i = 0; i < nvars; ++i )
1767  {
1768  assert(SCIPvarGetUbLocal(vars[i]) > 0.5); /* otherwise, rule (1) could be applied */
1769  if( SCIPvarGetLbLocal(vars[i]) < 0.5 )
1770  {
1771  if( watchedvar1 == -1 )
1772  {
1773  assert(watchedvar2 == -1);
1774  watchedvar1 = i;
1775  }
1776  else if( watchedvar1 != i )
1777  {
1778  watchedvar2 = i;
1779  break;
1780  }
1781  }
1782  }
1783  }
1784  assert(watchedvar1 != -1 || watchedvar2 == -1);
1785 
1786  /* if all variables are fixed to TRUE, the resultant can also be fixed to TRUE (rule (3)) */
1787  if( watchedvar1 == -1 )
1788  {
1789  assert(watchedvar2 == -1);
1790 
1791  SCIPdebugMessage("constraint <%s>: all operator vars fixed to 1.0 -> fix resultant <%s> to 1.0\n",
1792  SCIPconsGetName(cons), SCIPvarGetName(resvar));
1793  SCIP_CALL( SCIPinferBinvarCons(scip, resvar, TRUE, cons, (int)PROPRULE_3, &infeasible, &tightened) );
1794 
1795  if( infeasible )
1796  {
1797  /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
1798  SCIP_CALL( analyzeConflictZero(scip, cons) );
1799  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1800  *cutoff = TRUE;
1801  }
1802  else
1803  {
1804  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
1805  if( tightened )
1806  {
1807  SCIP_CALL( SCIPresetConsAge(scip, cons) );
1808  (*nfixedvars)++;
1809  }
1810  }
1811 
1812  return SCIP_OKAY;
1813  }
1814 
1815  /* if resultant is fixed to FALSE, and only one operator variable is not fixed to TRUE, this operator variable
1816  * can be fixed to FALSE (rule (4))
1817  */
1818  if( watchedvar2 == -1 && SCIPvarGetUbLocal(resvar) < 0.5 )
1819  {
1820  assert(watchedvar1 != -1);
1821 
1822  SCIP_CALL( analyzeZeroResultant(scip, cons, watchedvar1, watchedvar2, cutoff, nfixedvars) );
1823 
1824  return SCIP_OKAY;
1825  }
1826 
1827  /* switch to the new watched variables */
1828  SCIP_CALL( consdataSwitchWatchedvars(scip, consdata, eventhdlr, watchedvar1, watchedvar2) );
1829 
1830  /* mark the constraint propagated if we have an unfixed resultant or are not in probing, it is necessary that a fixed
1831  * resulting in probing mode does not lead to a propagated constraint, because the constraint upgrade needs to be performed
1832  */
1833  consdata->propagated = (!SCIPinProbing(scip) || (SCIPvarGetLbLocal(consdata->resvar) < 0.5 && SCIPvarGetUbLocal(consdata->resvar) > 0.5));
1834 
1835  return SCIP_OKAY;
1836 }
1837 
1838 /** resolves a conflict on the given variable by supplying the variables needed for applying the corresponding
1839  * propagation rule (see propagateCons()):
1840  * (1) v_i = FALSE => r = FALSE
1841  * (2) r = TRUE => v_i = TRUE for all i
1842  * (3) v_i = TRUE for all i => r = TRUE
1843  * (4) r = FALSE, v_i = TRUE for all i except j => v_j = FALSE
1844  */
1845 static
1847  SCIP* scip, /**< SCIP data structure */
1848  SCIP_CONS* cons, /**< constraint that inferred the bound change */
1849  SCIP_VAR* infervar, /**< variable that was deduced */
1850  PROPRULE proprule, /**< propagation rule that deduced the value */
1851  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1852  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
1853  )
1854 {
1855  SCIP_CONSDATA* consdata;
1856  SCIP_VAR** vars;
1857  int nvars;
1858  int i;
1859 
1860  assert(result != NULL);
1861 
1862  consdata = SCIPconsGetData(cons);
1863  assert(consdata != NULL);
1864  vars = consdata->vars;
1865  nvars = consdata->nvars;
1866 
1867  switch( proprule )
1868  {
1869  case PROPRULE_1:
1870  /* the resultant was infered to FALSE, because one operand variable was FALSE */
1871  assert(SCIPvarGetUbAtIndex(infervar, bdchgidx, TRUE) < 0.5);
1872  assert(infervar == consdata->resvar);
1873  for( i = 0; i < nvars; ++i )
1874  {
1875  if( SCIPvarGetUbAtIndex(vars[i], bdchgidx, FALSE) < 0.5 )
1876  {
1877  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
1878  break;
1879  }
1880  }
1881  assert(i < nvars);
1882  *result = SCIP_SUCCESS;
1883  break;
1884 
1885  case PROPRULE_2:
1886  /* the operand variable was infered to TRUE, because the resultant was TRUE */
1887  assert(SCIPvarGetLbAtIndex(infervar, bdchgidx, TRUE) > 0.5);
1888  assert(SCIPvarGetLbAtIndex(consdata->resvar, bdchgidx, FALSE) > 0.5);
1889  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1890  *result = SCIP_SUCCESS;
1891  break;
1892 
1893  case PROPRULE_3:
1894  /* the resultant was infered to TRUE, because all operand variables were TRUE */
1895  assert(SCIPvarGetLbAtIndex(infervar, bdchgidx, TRUE) > 0.5);
1896  assert(infervar == consdata->resvar);
1897  for( i = 0; i < nvars; ++i )
1898  {
1899  assert(SCIPvarGetLbAtIndex(vars[i], bdchgidx, FALSE) > 0.5);
1900  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
1901  }
1902  *result = SCIP_SUCCESS;
1903  break;
1904 
1905  case PROPRULE_4:
1906  /* the operand variable was infered to FALSE, because the resultant was FALSE and all other operands were TRUE */
1907  assert(SCIPvarGetUbAtIndex(infervar, bdchgidx, TRUE) < 0.5);
1908  assert(SCIPvarGetUbAtIndex(consdata->resvar, bdchgidx, FALSE) < 0.5);
1909  SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->resvar) );
1910  for( i = 0; i < nvars; ++i )
1911  {
1912  if( vars[i] != infervar )
1913  {
1914  assert(SCIPvarGetLbAtIndex(vars[i], bdchgidx, FALSE) > 0.5);
1915  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i]) );
1916  }
1917  }
1918  *result = SCIP_SUCCESS;
1919  break;
1920 
1921  case PROPRULE_INVALID:
1922  default:
1923  SCIPerrorMessage("invalid inference information %d in AND-constraint <%s>\n", proprule, SCIPconsGetName(cons));
1924  return SCIP_INVALIDDATA;
1925  }
1926 
1927  return SCIP_OKAY;
1928 }
1929 
1930 /** perform dual presolving on AND-constraints */
1931 static
1933  SCIP* scip, /**< SCIP data structure */
1934  SCIP_CONS** conss, /**< AND-constraints to perform dual presolving on */
1935  int nconss, /**< number of AND-constraints */
1936  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
1937  unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
1938  int* nentries, /**< pointer for array size, if array will be to small it's corrected */
1939  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
1940  int* nfixedvars, /**< pointer to add up the number of found domain reductions */
1941  int* naggrvars, /**< pointer to add up the number of aggregated variables */
1942  int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
1943  int* ndelconss, /**< pointer to add up the number of deleted constraints */
1944  int* nupgdconss, /**< pointer to add up the number of upgraded constraints */
1945  int* naddconss /**< pointer to add up the number of added constraints */
1946  )
1947 {
1948  SCIP_CONS* cons;
1949  SCIP_CONSDATA* consdata;
1950  SCIP_VAR** impoperands;
1951  SCIP_VAR** vars;
1952  SCIP_VAR* resvar;
1953  SCIP_VAR* var;
1954  int nimpoperands;
1955  int nvars;
1956  int size;
1957  int v;
1958  int c;
1959  SCIP_Bool infeasible;
1960  SCIP_Bool fixed;
1961 
1962  assert(scip != NULL);
1963  assert(conss != NULL || nconss == 0);
1964  assert(eventhdlr != NULL);
1965  assert(*entries != NULL);
1966  assert(nentries != NULL);
1967  assert(cutoff != NULL);
1968  assert(nfixedvars != NULL);
1969  assert(naggrvars != NULL);
1970  assert(nchgcoefs != NULL);
1971  assert(ndelconss != NULL);
1972  assert(nupgdconss != NULL);
1973  assert(naddconss != NULL);
1974 
1975  if( nconss == 0 )
1976  return SCIP_OKAY;
1977 
1978  assert(conss != NULL);
1979 
1980  size = 2 * (SCIPgetNBinVars(scip) + SCIPgetNImplVars(scip));
1981 
1982  SCIP_CALL( SCIPallocMemoryArray(scip, &impoperands, size) );
1983 
1984  for( c = nconss - 1; c >= 0 && !(*cutoff); --c )
1985  {
1986  cons = conss[c];
1987  assert(cons != NULL);
1988 
1989  if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsModifiable(cons) )
1990  continue;
1991 
1992  /* propagate constraint */
1993  SCIP_CALL( propagateCons(scip, cons, eventhdlr, cutoff, nfixedvars, nupgdconss) );
1994 
1995  if( !SCIPconsIsActive(cons) )
1996  continue;
1997 
1998  if( *cutoff )
1999  break;
2000 
2001  SCIP_CALL( applyFixings(scip, cons, eventhdlr, nchgcoefs) );
2002 
2003  /* merge multiple occurances of variables or variables with their negated variables */
2004  SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, entries, nentries, nfixedvars, nchgcoefs, ndelconss) );
2005 
2006  if( !SCIPconsIsActive(cons) )
2007  continue;
2008 
2009  consdata = SCIPconsGetData(cons);
2010  assert(consdata != NULL);
2011 
2012  vars = consdata->vars;
2013  nvars = consdata->nvars;
2014  assert(vars != NULL || nvars == 0);
2015 
2016  if( nvars == 0 )
2017  continue;
2018 
2019  assert(vars != NULL);
2020 
2021  resvar = consdata->resvar;
2022  assert(resvar != NULL);
2023  /* a fixed resultant needs to be removed, otherwise we might fix operands to a wrong value later on */
2024  assert(SCIPvarGetLbGlobal(resvar) < 0.5 && SCIPvarGetUbGlobal(resvar) > 0.5);
2025  assert(SCIPvarGetNLocksUp(resvar) >= 1 && SCIPvarGetNLocksDown(resvar) >= 1);
2026 
2027  if( SCIPvarGetNLocksUp(resvar) == 1 && SCIPvarGetNLocksDown(resvar) == 1 )
2028  {
2029  SCIP_Real resobj;
2030  SCIP_Real obj;
2031  SCIP_Real posobjsum = 0;
2032  SCIP_Real maxobj = -SCIPinfinity(scip);
2033  int maxpos = -1;
2034  int oldnfixedvars = *nfixedvars;
2035  int oldnaggrvars = *naggrvars;
2036 
2037  nimpoperands = 0;
2038 
2039  /* collect important operands */
2040  for( v = nvars - 1; v >= 0; --v )
2041  {
2042  var = vars[v];
2043  assert(var != NULL);
2044  assert(SCIPvarGetNLocksUp(var) >= 1 && SCIPvarGetNLocksDown(var) >= 1);
2045 
2046  if( SCIPvarGetNLocksUp(var) == 1 && SCIPvarGetNLocksDown(var) == 1 )
2047  {
2048  impoperands[nimpoperands] = var;
2049  ++nimpoperands;
2050 
2051  /* get aggregated objective value of active variable */
2052  SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
2053 
2054  /* add up all positive objective values of operands which have exactly one lock in both directions */
2055  if( obj > 0 )
2056  posobjsum += obj;
2057 
2058  /* memorize maximal objective value of operands and its position */
2059  if( obj > maxobj )
2060  {
2061  maxpos = nimpoperands - 1;
2062  maxobj = obj;
2063  }
2064  }
2065  }
2066  assert(nimpoperands >= 0 && nimpoperands <= nvars);
2067 
2068  /* no dual fixable variables found */
2069  if( nimpoperands == 0 )
2070  continue;
2071 
2072  /* get aggregated objective value of active variable */
2073  SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &resobj) );
2074 
2075  /* resultant contributes to the objective with a negative value */
2076  if( SCIPisLE(scip, resobj, 0.0) )
2077  {
2078  SCIP_Bool poscontissmall = SCIPisLE(scip, posobjsum, REALABS(resobj));
2079 
2080  /* if all variables are only locked by this constraint and the resultants contribution more then compensates
2081  * the positive contribution, we can fix all variables to 1
2082  */
2083  if( nimpoperands == nvars && poscontissmall )
2084  {
2085  SCIPdebugMessage("dual-fixing all variables in constraint <%s> to 1\n", SCIPconsGetName(cons));
2086 
2087  SCIP_CALL( SCIPfixVar(scip, resvar, 1.0, &infeasible, &fixed) );
2088 
2089  *cutoff = *cutoff || infeasible;
2090  if( fixed )
2091  ++(*nfixedvars);
2092 
2093 
2094  for( v = nvars - 1; v >= 0 && !(*cutoff); --v )
2095  {
2096  SCIP_CALL( SCIPfixVar(scip, vars[v], 1.0, &infeasible, &fixed) );
2097 
2098  *cutoff = *cutoff || infeasible;
2099  if( fixed )
2100  ++(*nfixedvars);
2101  }
2102 
2103  SCIPdebugMessage("deleting constraint <%s> because all variables are fixed to one\n", SCIPconsGetName(cons));
2104 
2105  SCIP_CALL( SCIPdelCons(scip, cons) );
2106  ++(*ndelconss);
2107  }
2108  else
2109  {
2110  SCIP_Bool aggregationperformed = FALSE;
2111  SCIP_Bool zerofix = FALSE;
2112 
2113  assert(nimpoperands > 0);
2114 
2115  SCIPdebugMessage("dual-fixing all variables in constraint <%s> with positive contribution (when together exceeding the negative contribution of the resultant) to 0 and with negative contribution to 1\n", SCIPconsGetName(cons));
2116 
2117  for( v = nimpoperands - 1; v >= 0 && !(*cutoff); --v )
2118  {
2119  /* get aggregated objective value of active variable */
2120  SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[v], &obj) );
2121 
2122  if( SCIPisLE(scip, obj, 0.0) )
2123  {
2124  SCIP_CALL( SCIPfixVar(scip, impoperands[v], 1.0, &infeasible, &fixed) );
2125 
2126  *cutoff = *cutoff || infeasible;
2127  if( fixed )
2128  ++(*nfixedvars);
2129  }
2130  else if( !poscontissmall )
2131  {
2132  SCIP_CALL( SCIPfixVar(scip, impoperands[v], 0.0, &infeasible, &fixed) );
2133  assert(!infeasible);
2134  assert(fixed);
2135 
2136  ++(*nfixedvars);
2137  zerofix = TRUE;
2138  }
2139  else
2140  {
2141  SCIP_Bool redundant;
2142  SCIP_Bool aggregated;
2143 
2144  /* aggregate resultant to operand */
2145  SCIP_CALL( SCIPaggregateVars(scip, resvar, impoperands[v], 1.0, -1.0, 0.0,
2146  &infeasible, &redundant, &aggregated) );
2147  assert(!infeasible);
2148 
2149  if( aggregated )
2150  {
2151  /* note that we cannot remove the aggregated operand because we do not know the position */
2152  ++(*naggrvars);
2153 
2154  aggregationperformed = TRUE;
2155 
2156  SCIPdebugMessage("dual aggregating operand <%s> with 1 up- and downlock to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(impoperands[v]), SCIPvarGetName(resvar), SCIPconsGetName(cons));
2157  }
2158  }
2159  }
2160  assert(*nfixedvars - oldnfixedvars + *naggrvars - oldnaggrvars <= nimpoperands);
2161 
2162  /* did we aggregate the resultant, then we can decide the value to fix it on the (aggregated) objective
2163  * value since it was a independant variable
2164  */
2165  if( aggregationperformed || zerofix )
2166  {
2167  SCIP_Real fixval;
2168 
2169  if( zerofix )
2170  fixval = 0.0;
2171  else
2172  {
2173  /* get aggregated objective value of active variable, that might be changed */
2174  SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &obj) );
2175  assert(!SCIPisPositive(scip, obj));
2176 
2177  fixval = (SCIPisNegative(scip, obj) ? 1.0 : 0.0);
2178  }
2179 
2180  if( fixval < 0.5 || *nfixedvars - oldnfixedvars + *naggrvars - oldnaggrvars == nvars )
2181  {
2182  SCIPdebugMessage("constraint <%s> we can fix the resultant <%s> to %g, because the AND-constraint will alwys be fulfilled\n", SCIPconsGetName(cons), SCIPvarGetName(resvar), fixval);
2183 
2184  SCIP_CALL( SCIPfixVar(scip, resvar, fixval, &infeasible, &fixed) );
2185  assert(!infeasible);
2186  assert(fixed);
2187 
2188  ++(*nfixedvars);
2189 
2190  SCIPdebugMessage("deleting constraint <%s> because \n", SCIPconsGetName(cons));
2191 
2192  SCIP_CALL( SCIPdelCons(scip, cons) );
2193  ++(*ndelconss);
2194  }
2195  }
2196  }
2197  }
2198  /* resultant contributes to the objective with a positive value */
2199  else
2200  {
2201  SCIP_Bool zerofix = FALSE;
2202 #ifndef NDEBUG
2203  SCIP_Real tmpobj;
2204 
2205  assert(nimpoperands > 0);
2206  assert(maxpos >= 0 && maxpos <= consdata->nvars);
2207  assert(!SCIPisInfinity(scip, -maxobj));
2208  SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[maxpos], &tmpobj) );
2209  assert(SCIPisEQ(scip, tmpobj, maxobj));
2210 #endif
2211 
2212  /* if the smallest possible contribution is negative, but does not compensate the positive contribution of
2213  * the resultant we need to fix this variable to 0
2214  */
2215  if( nimpoperands == nvars && SCIPisLE(scip, maxobj, 0.0) )
2216  {
2217  SCIP_Real fixval = (SCIPisLE(scip, REALABS(maxobj), resobj) ? 0.0 : 1.0);
2218 
2219  SCIPdebugMessage("dual-fixing variable <%s> in constraint <%s> to %g, because the contribution is%s enough to nullify/exceed the contribution of the resultant \n", SCIPvarGetName(impoperands[maxpos]), SCIPconsGetName(cons), fixval, (fixval < 0.5) ? " not" : "");
2220 
2221  SCIP_CALL( SCIPfixVar(scip, impoperands[maxpos], fixval, &infeasible, &fixed) );
2222  zerofix = (fixval < 0.5);
2223 
2224  *cutoff = *cutoff || infeasible;
2225  if( fixed )
2226  ++(*nfixedvars);
2227  }
2228 
2229  SCIPdebugMessage("dual-fixing all variables, except the variable with the highest contribution to the objective, in constraint <%s> with positive contribution to 0 and with negative contribution to 1\n", SCIPconsGetName(cons));
2230 
2231  for( v = nimpoperands - 1; v >= 0 && !(*cutoff); --v )
2232  {
2233  /* get aggregated objective value of active variable */
2234  SCIP_CALL( SCIPvarGetAggregatedObj(impoperands[v], &obj) );
2235 
2236  if( SCIPisLE(scip, obj, 0.0) )
2237  {
2238  if( v == maxpos )
2239  continue;
2240 
2241  SCIP_CALL( SCIPfixVar(scip, impoperands[v], 1.0, &infeasible, &fixed) );
2242  }
2243  else
2244  {
2245  SCIP_CALL( SCIPfixVar(scip, impoperands[v], 0.0, &infeasible, &fixed) );
2246  zerofix = TRUE;
2247  }
2248 
2249  *cutoff = *cutoff || infeasible;
2250  if( fixed )
2251  ++(*nfixedvars);
2252  }
2253  assert(*nfixedvars - oldnfixedvars <= nimpoperands);
2254  /* iff we have fixed all variables, all variables needed to be stored in the impoperands array */
2255  assert((*nfixedvars - oldnfixedvars == nvars) == (nimpoperands == nvars));
2256 
2257  if( *nfixedvars - oldnfixedvars == nvars )
2258  {
2259  SCIPdebugMessage("all operands are fixed in constraint <%s> => fix resultant <%s> to %g\n", SCIPconsGetName(cons), SCIPvarGetName(resvar), (zerofix ? 0.0 : 1.0));
2260 
2261  SCIP_CALL( SCIPfixVar(scip, resvar, zerofix ? 0.0 : 1.0, &infeasible, &fixed) );
2262 
2263  *cutoff = *cutoff || infeasible;
2264  if( fixed )
2265  ++(*nfixedvars);
2266 
2267  SCIPdebugMessage("deleting constraint <%s> because all variables are fixed\n", SCIPconsGetName(cons));
2268 
2269  SCIP_CALL( SCIPdelCons(scip, cons) );
2270  ++(*ndelconss);
2271  }
2272  }
2273  }
2274  /* resultant is lock by another constraint (handler), check for operands with only one down- and uplock */
2275  else
2276  {
2277  SCIP_Real maxobj = -SCIPinfinity(scip);
2278  SCIP_Real resobj;
2279  SCIP_Real obj;
2280  SCIP_Bool redundant;
2281  SCIP_Bool aggregated;
2282  SCIP_Bool resobjispos;
2283  SCIP_Bool linearize = FALSE;
2284  SCIP_Bool zerofix = FALSE;
2285 #ifndef NDEBUG
2286  int oldnchgcoefs = *nchgcoefs;
2287  int oldnfixedvars = *nfixedvars;
2288 #endif
2289 
2290  /* get aggregated objective value of active variable */
2291  SCIP_CALL( SCIPvarGetAggregatedObj(resvar, &resobj) );
2292 
2293  resobjispos = SCIPisGT(scip, resobj, 0.0);
2294 
2295  /* we can only aggregate when the objective contribution of the resultant is less or equal to 0 */
2296  if( !resobjispos )
2297  {
2298  SCIP_Bool goodvarsfound = FALSE;
2299 
2300  for( v = nvars - 1; v >= 0; --v )
2301  {
2302  var = vars[v];
2303  assert(var != NULL);
2304  assert(SCIPvarGetNLocksUp(var) >= 1 && SCIPvarGetNLocksDown(var) >= 1);
2305 
2306  /* get aggregated objective value of active variable */
2307  SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
2308 
2309  /* all operands which are only locked by this constraint, the objective contribution is greater or equal
2310  * to 0 can be aggregated to the resultant
2311  */
2312  if( SCIPvarGetNLocksUp(var) == 1 && SCIPvarGetNLocksDown(var) == 1 )
2313  {
2314  if( !SCIPisNegative(scip, obj) )
2315  {
2316  /* aggregate resultant to operand */
2317  SCIP_CALL( SCIPaggregateVars(scip, resvar, var, 1.0, -1.0, 0.0,
2318  &infeasible, &redundant, &aggregated) );
2319 
2320  if( aggregated )
2321  {
2322  ++(*naggrvars);
2323 
2324  linearize = TRUE;
2325 
2326  /* delete redundant entry from constraint */
2327  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
2328  ++(*nchgcoefs);
2329 
2330  SCIPdebugMessage("dual aggregating operand <%s> with 1 up- and downlock to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(var), SCIPvarGetName(resvar), SCIPconsGetName(cons));
2331  }
2332 
2333  *cutoff = *cutoff || infeasible;
2334  }
2335  else
2336  goodvarsfound = TRUE;
2337  }
2338  }
2339  assert(*nchgcoefs - oldnchgcoefs <= nvars);
2340 
2341  /* if we aggregated an operands with the resultant we can also fix "good" independant operands to 1, since
2342  * the correctness of "resultant = 0 => at least one operand = 0" in enforced by that aggregation
2343  * without an aggregation we cannot fix these variables since it might lead to infeasibility, e.g.
2344  *
2345  * obj(x3) = -1
2346  * r = x1 * x2 * x3
2347  * r = 0
2348  * x1 = 1
2349  * x2 = 1
2350  */
2351  if( !*cutoff && goodvarsfound && linearize )
2352  {
2353  /* fix good variables to 1 */
2354  for( v = consdata->nvars - 1; v >= 0; --v )
2355  {
2356  var = vars[v];
2357  assert(var != NULL);
2358 
2359  if( SCIPvarGetNLocksUp(var) == 1 && SCIPvarGetNLocksDown(var) == 1 )
2360  {
2361 #ifndef NDEBUG
2362  /* aggregated objective value of active variable need to be negative */
2363  SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
2364  assert(SCIPisNegative(scip, obj));
2365 #endif
2366  SCIPdebugMessage("dual-fixing variable <%s> in constraint <%s> to 1, because the contribution is negative\n", SCIPvarGetName(var), SCIPconsGetName(cons));
2367 
2368  SCIP_CALL( SCIPfixVar(scip, var, 1.0, &infeasible, &fixed) );
2369 
2370  assert(!infeasible);
2371  if( fixed )
2372  ++(*nfixedvars);
2373  }
2374  }
2375  assert(*nfixedvars - oldnfixedvars <= consdata->nvars);
2376  }
2377  assert(*nchgcoefs - oldnchgcoefs + *nfixedvars - oldnfixedvars <= nvars);
2378  }
2379  /* if the downlocks of the resultant are only from this constraint and the objective contribution is positive,
2380  * we can try to fix operands
2381  */
2382  else if( SCIPvarGetNLocksDown(resvar) == 1 )
2383  {
2384  SCIP_Bool locksareone = TRUE;
2385  int maxpos = -1;
2386 
2387  for( v = nvars - 1; v >= 0; --v )
2388  {
2389  var = vars[v];
2390  assert(var != NULL);
2391  assert(SCIPvarGetNLocksUp(var) >= 1 && SCIPvarGetNLocksDown(var) >= 1);
2392 
2393  /* check if all resultants are only locked by this constraint */
2394  locksareone = locksareone && (SCIPvarGetNLocksUp(var) == 1 && SCIPvarGetNLocksDown(var) == 1);
2395 
2396  /* get aggregated objective value of active variable */
2397  SCIP_CALL( SCIPvarGetAggregatedObj(var, &obj) );
2398 
2399  /* memorize maximal objective value of operands and its position */
2400  if( obj > maxobj )
2401  {
2402  maxpos = v;
2403  maxobj = obj;
2404  }
2405 
2406  /* all operands which are only locked by this constraint, the objective contribution is greater or equal
2407  * to 0, and the absolute value of the contribution of the resultant exceeds can be eliminated and
2408  * aggregated to the resultant
2409  */
2410  if( SCIPvarGetNLocksUp(var) == 1 && SCIPvarGetNLocksDown(var) == 1 && SCIPisGE(scip, obj, 0.0) )
2411  {
2412  SCIPdebugMessage("dualfix operand <%s> in constraint <%s> to 0\n", SCIPvarGetName(var), SCIPconsGetName(cons));
2413 
2414  SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
2415 
2416  *cutoff = *cutoff || infeasible;
2417  if( fixed )
2418  ++(*nfixedvars);
2419 
2420  zerofix = TRUE;
2421  }
2422  }
2423  assert(*nchgcoefs - oldnchgcoefs <= nvars);
2424 
2425  /* if constraint is still active and all operands are only lock by this constraint, we check if we can fix
2426  * the worst (in objective contribution) operand to zero
2427  */
2428  if( !zerofix && locksareone && SCIPisGE(scip, resobj, REALABS(maxobj)) )
2429  {
2430  assert(!zerofix);
2431  /* objective contribution needs to be negative, otherwise, the variable should already be fixed to 0 */
2432  assert(SCIPisLT(scip, maxobj, 0.0));
2433 
2434  SCIPdebugMessage("dualfix operand <%s> with worst contribution in constraint <%s> to 0\n", SCIPvarGetName(vars[maxpos]), SCIPconsGetName(cons));
2435 
2436  SCIP_CALL( SCIPfixVar(scip, vars[maxpos], 0.0, &infeasible, &fixed) );
2437 
2438  *cutoff = *cutoff || infeasible;
2439  if( fixed )
2440  ++(*nfixedvars);
2441 
2442  zerofix = TRUE;
2443  }
2444 
2445  /* fix the resultant if one operand was fixed to zero and delete the constraint */
2446  if( zerofix )
2447  {
2448  SCIPdebugMessage("fix resultant <%s> in constraint <%s> to 0\n", SCIPvarGetName(resvar), SCIPconsGetName(cons));
2449 
2450  SCIP_CALL( SCIPfixVar(scip, resvar, 0.0, &infeasible, &fixed) );
2451 
2452  *cutoff = *cutoff || infeasible;
2453  if( fixed )
2454  ++(*nfixedvars);
2455 
2456  SCIPdebugMessage("deleting constraint <%s> because at least one operand and the resultant is fixed to zero\n", SCIPconsGetName(cons));
2457 
2458  SCIP_CALL( SCIPdelCons(scip, cons) );
2459  ++(*ndelconss);
2460  }
2461  }
2462 
2463  /* we have to linearize the constraint, otherwise we might get wrong propagations, since due to aggregations a
2464  * resultant fixed to zero is already fulfilling the constraint, and we must not ensure that some remaining
2465  * operand needs to be 0
2466  */
2467  if( linearize )
2468  {
2469  SCIP_CONS* newcons;
2470  char consname[SCIP_MAXSTRLEN];
2471  SCIP_VAR* consvars[2];
2472  SCIP_Real vals[2];
2473 
2474  assert(SCIPconsIsActive(cons));
2475 
2476  consvars[0] = consdata->resvar;
2477  vals[0] = 1.0;
2478  vals[1] = -1.0;
2479 
2480  /* create operator linear constraints */
2481  for( v = consdata->nvars - 1; v >= 0; --v )
2482  {
2483  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), v);
2484  consvars[1] = consdata->vars[v];
2485 
2486  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, 2, consvars, vals, -SCIPinfinity(scip), 0.0,
2490  SCIPconsIsStickingAtNode(cons)) );
2491 
2492  /* add constraint */
2493  SCIP_CALL( SCIPaddCons(scip, newcons) );
2494  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
2495  }
2496  (*naddconss) += consdata->nvars;
2497 
2498  SCIPdebugMessage("deleting constraint <%s> because it was linearized\n", SCIPconsGetName(cons));
2499 
2500  SCIP_CALL( SCIPdelCons(scip, cons) );
2501  ++(*ndelconss);
2502  }
2503  /* if only one operand is leftover, aggregate it to the resultant */
2504  else if( consdata->nvars == 1 )
2505  {
2506  SCIPdebugMessage("aggregating last operand <%s> to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(consdata->vars[0]), SCIPvarGetName(resvar), SCIPconsGetName(cons));
2507 
2508  /* aggregate resultant to operand */
2509  SCIP_CALL( SCIPaggregateVars(scip, resvar, consdata->vars[0], 1.0, -1.0, 0.0,
2510  &infeasible, &redundant, &aggregated) );
2511 
2512  if( aggregated )
2513  ++(*naggrvars);
2514 
2515  *cutoff = *cutoff || infeasible;
2516 
2517  SCIPdebugMessage("deleting constraint <%s> because all variables are removed\n", SCIPconsGetName(cons));
2518 
2519  SCIP_CALL( SCIPdelCons(scip, cons) );
2520  ++(*ndelconss);
2521  }
2522 
2523  /* if no operand is leftover delete the constraint */
2524  if( SCIPconsIsActive(cons) && consdata->nvars == 0 )
2525  {
2526  SCIPdebugMessage("deleting constraint <%s> because all variables are removed\n", SCIPconsGetName(cons));
2527 
2528  SCIP_CALL( SCIPdelCons(scip, cons) );
2529  ++(*ndelconss);
2530  }
2531  }
2532  }
2533 
2534  SCIPfreeMemoryArray(scip, &impoperands);
2535 
2536  return SCIP_OKAY;
2537 }
2538 
2539 /** 1. check if at least two operands or one operand and the resultant are in one clique, if so, we can fix the
2540  * resultant to zero and in the former case we can also delete this constraint but we need to extract the clique
2541  * information as constraint
2542  *
2543  * x == AND(y, z) and clique(y,z) => x = 0, delete constraint and create y + z <= 1
2544  * x == AND(y, z) and clique(x,y) => x = 0
2545  *
2546  * special handled cases are:
2547  * - if the resultant is a negation of an operand, in that case we fix the resultant to 0
2548  * - if the resultant is equal to an operand, we will linearize this constraint by adding all necessary
2549  * set-packing constraints like resultant + ~operand <= 1 and delete the old constraint
2550  *
2551  * x == AND(~x, y) => x = 0
2552  * x == AND(x, y) => add x + ~y <= 1 and delete the constraint
2553  *
2554  * 2. check if one operand is in a clique with the negation of all other operands, this means we can aggregate this
2555  * operand to the resultant
2556  *
2557  * r == AND(x,y,z) and clique(x,~y) and clique(x,~z) => r == x
2558  *
2559  * 3. check if the resultant and the negations of all operands are in a clique
2560  *
2561  * r == AND(x,y) and clique(r, ~x,~y) => upgrade the constraint to a set-partitioning constraint r + ~x + ~y = 1
2562  *
2563  * @note We removed also fixed variables and propagate them, and if only one operand is remaining due to removal, we
2564  * will aggregate the resultant with this operand
2565  */
2566 static
2568  SCIP* scip, /**< SCIP data structure */
2569  SCIP_CONS* cons, /**< constraint to process */
2570  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
2571  SCIP_Bool* cutoff, /**< pointer to store TRUE, if the node can be cut off */
2572  int* nfixedvars, /**< pointer to add up the number of found domain reductions */
2573  int* naggrvars, /**< pointer to add up the number of aggregated variables */
2574  int* nchgcoefs, /**< pointer to add up the number of changed coefficients */
2575  int* ndelconss, /**< pointer to add up the number of deleted constraints */
2576  int* naddconss /**< pointer to add up the number of added constraints */
2577  )
2578 {
2579  SCIP_CONSDATA* consdata;
2580  SCIP_VAR** vars;
2581  SCIP_VAR* var1;
2582  SCIP_VAR* var2;
2583  int nvars;
2584  int vstart;
2585  int vend;
2586  int v;
2587  int v2;
2588  SCIP_Bool negated;
2589  SCIP_Bool value1;
2590  SCIP_Bool value2;
2591  SCIP_Bool infeasible;
2592  SCIP_Bool fixed;
2593  SCIP_Bool allnegoperandsexist;
2594 
2595  assert(scip != NULL);
2596  assert(cons != NULL);
2597  assert(eventhdlr != NULL);
2598  assert(cutoff != NULL);
2599  assert(nfixedvars != NULL);
2600  assert(naggrvars != NULL);
2601  assert(nchgcoefs != NULL);
2602  assert(ndelconss != NULL);
2603  assert(naddconss != NULL);
2604 
2605  consdata = SCIPconsGetData(cons);
2606  assert(consdata != NULL);
2607 
2608  if( !SCIPconsIsActive(cons) || SCIPconsIsModifiable(cons) )
2609  return SCIP_OKAY;
2610 
2611  vars = consdata->vars;
2612  nvars = consdata->nvars;
2613  assert(vars != NULL || nvars == 0);
2614 
2615  /* remove fixed variables to be able to ask for cliques
2616  *
2617  * if an operand is fixed to 0 fix the resultant to 0 and delete the constraint
2618  * if an operand is fixed to 1 remove it from the constraint
2619  */
2620  for( v = nvars - 1; v >= 0; --v )
2621  {
2622  assert(vars != NULL);
2623 
2624  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
2625  {
2626  SCIPdebugMessage("In constraint <%s> the operand <%s> is fixed to 1 so remove it from the constraint\n",
2627  SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
2628 
2629  /* because we loop from back to front we can delete the entry in the consdata structure */
2630  SCIP_CALL( delCoefPos(scip, cons, eventhdlr, v) );
2631  ++(*nchgcoefs);
2632 
2633  assert(consdata->vars == vars);
2634 
2635  continue;
2636  }
2637  else if( SCIPvarGetUbGlobal(vars[v]) < 0.5 )
2638  {
2639  SCIPdebugMessage("constraint <%s> redundant: because operand <%s> is fixed to zero so we can fix the resultant <%s> to 0\n",
2640  SCIPconsGetName(cons), SCIPvarGetName(vars[v]), SCIPvarGetName(consdata->resvar));
2641 
2642  SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
2643  *cutoff = *cutoff || infeasible;
2644  if( fixed )
2645  ++(*nfixedvars);
2646 
2647  SCIP_CALL( SCIPdelCons(scip, cons) );
2648  ++(*ndelconss);
2649 
2650  return SCIP_OKAY;
2651  }
2652  }
2653 
2654  /* if we deleted some operands constraint might be redundant */
2655  if( consdata->nvars < nvars )
2656  {
2657  assert(vars == consdata->vars);
2658 
2659  /* all operands fixed to one were removed, so if no operand is left this means we can fix the resultant to 1
2660  * too
2661  */
2662  if( consdata->nvars == 0 )
2663  {
2664  SCIPdebugMessage("All operand in constraint <%s> were deleted, so the resultant needs to be fixed to 1\n",
2665  SCIPconsGetName(cons));
2666 
2667  SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 1.0, &infeasible, &fixed) );
2668  *cutoff = *cutoff || infeasible;
2669  if( fixed )
2670  ++(*nfixedvars);
2671 
2672  SCIP_CALL( SCIPdelCons(scip, cons) );
2673  ++(*ndelconss);
2674 
2675  return SCIP_OKAY;
2676  }
2677  /* if only one not fixed operand is left, we can aggregate it to the resultant */
2678  else if( consdata->nvars == 1 )
2679  {
2680  SCIP_Bool redundant;
2681  SCIP_Bool aggregated;
2682 
2683  /* aggregate resultant to last operand */
2684  SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, consdata->vars[0], 1.0, -1.0, 0.0,
2685  &infeasible, &redundant, &aggregated) );
2686 
2687  if( aggregated )
2688  ++(*naggrvars);
2689 
2690  SCIP_CALL( SCIPdelCons(scip, cons) );
2691  ++(*ndelconss);
2692 
2693  *cutoff = *cutoff || infeasible;
2694 
2695  return SCIP_OKAY;
2696  }
2697 
2698  nvars = consdata->nvars;
2699  }
2700 
2701  /* @todo when cliques are improved, we only need to collect all clique-ids for all variables and check for doubled
2702  * entries
2703  */
2704  /* case 1 first part */
2705  /* check if two operands are in a clique */
2706  for( v = nvars - 1; v > 0; --v )
2707  {
2708  assert(vars != NULL);
2709 
2710  var1 = vars[v];
2711  assert(var1 != NULL);
2712  negated = FALSE;
2713 
2714  SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
2715  assert(var1 != NULL);
2716 
2717  if( negated )
2718  value1 = FALSE;
2719  else
2720  value1 = TRUE;
2721 
2722  assert(SCIPvarGetStatus(var1) != SCIP_VARSTATUS_FIXED);
2723 
2724  for( v2 = v - 1; v2 >= 0; --v2 )
2725  {
2726  var2 = vars[v2];
2727  assert(var2 != NULL);
2728 
2729  negated = FALSE;
2730  SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
2731  assert(var2 != NULL);
2732 
2733  if( negated )
2734  value2 = FALSE;
2735  else
2736  value2 = TRUE;
2737 
2738  assert(SCIPvarGetStatus(var2) != SCIP_VARSTATUS_FIXED);
2739 
2740  /* if both variables are negated of each other or the same, this will be handled in applyFixings();
2741  * @note if both variables are the same, then SCIPvarsHaveCommonClique() will return TRUE, so we better
2742  * continue
2743  */
2744  if( var1 == var2 )
2745  continue;
2746 
2747  if( SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
2748  {
2749  SCIP_CONS* cliquecons;
2750  SCIP_VAR* consvars[2];
2751  char name[SCIP_MAXSTRLEN];
2752 
2753  SCIPdebugMessage("constraint <%s> redundant: because variable <%s> and variable <%s> are in a clique, the resultant <%s> can be fixed to 0\n",
2754  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2), SCIPvarGetName(consdata->resvar));
2755 
2756  SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
2757  *cutoff = *cutoff || infeasible;
2758  if( fixed )
2759  ++(*nfixedvars);
2760 
2761 
2762  /* create clique constraint which lead to the last fixing */
2763  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq", SCIPconsGetName(cons), v2);
2764 
2765  if( value1 )
2766  consvars[0] = var1;
2767  else
2768  {
2769  SCIP_CALL( SCIPgetNegatedVar(scip, var1, &(consvars[0])) );
2770  }
2771 
2772  if( value2 )
2773  consvars[1] = var2;
2774  else
2775  {
2776  SCIP_CALL( SCIPgetNegatedVar(scip, var2, &(consvars[1])) );
2777  }
2778 
2779  SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, 2, consvars,
2781  consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
2783  !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
2784  SCIPdebugMessage(" -> adding clique constraint: ");
2785  SCIPdebugPrintCons(scip, cliquecons, NULL);
2786  SCIP_CALL( SCIPaddCons(scip, cliquecons) );
2787  SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
2788  ++(*naddconss);
2789 
2790  SCIP_CALL( SCIPdelCons(scip, cons) );
2791  ++(*ndelconss);
2792 
2793  return SCIP_OKAY;
2794  }
2795  }
2796  }
2797 
2798  var1 = consdata->resvar;
2799  assert(var1 != NULL);
2800 
2801  negated = FALSE;
2802  SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
2803  assert(var1 != NULL);
2804 
2805  /* it may appear that we have a fixed resultant */
2806  if( SCIPvarGetStatus(var1) == SCIP_VARSTATUS_FIXED )
2807  {
2808  /* resultant is fixed to 1, so fix all operands to 1 */
2809  if( SCIPvarGetLbGlobal(consdata->resvar) > 0.5 )
2810  {
2811  SCIPdebugMessage("In constraint <%s> the resultant <%s> is fixed to 1 so fix all operands to 1\n",
2812  SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
2813 
2814  /* fix all operands to 1 */
2815  for( v = nvars - 1; v >= 0 && !(*cutoff); --v )
2816  {
2817  assert(vars != NULL);
2818 
2819  SCIPdebugMessage("Fixing operand <%s> to 1.\n", SCIPvarGetName(vars[v]));
2820 
2821  SCIP_CALL( SCIPfixVar(scip, vars[v], 1.0, &infeasible, &fixed) );
2822  *cutoff = *cutoff || infeasible;
2823 
2824  if( fixed )
2825  ++(*nfixedvars);
2826  }
2827 
2828  SCIP_CALL( SCIPdelCons(scip, cons) );
2829  ++(*ndelconss);
2830  }
2831  /* the upgrade to a linear constraint because of the to 0 fixed resultant we do in propagateCons() */
2832  else
2833  assert(SCIPvarGetUbGlobal(consdata->resvar) < 0.5);
2834 
2835  return SCIP_OKAY;
2836  }
2837 
2838  if( negated )
2839  value1 = FALSE;
2840  else
2841  value1 = TRUE;
2842 
2843  /* case 1 second part */
2844  /* check if one operands is in a clique with the resultant */
2845  for( v = nvars - 1; v >= 0; --v )
2846  {
2847  assert(vars != NULL);
2848 
2849  var2 = vars[v];
2850  assert(var2 != NULL);
2851 
2852  negated = FALSE;
2853  SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
2854  assert(var2 != NULL);
2855 
2856  if( negated )
2857  value2 = FALSE;
2858  else
2859  value2 = TRUE;
2860 
2861  /* if both variables are negated of each other or the same, this will be handled in applyFixings();
2862  * @note if both variables are the same, then SCIPvarsHaveCommonClique() will return TRUE, so we better continue
2863  */
2864  if( var1 == var2 )
2865  {
2866  /* x1 == AND(~x1, x2 ...) => x1 = 0 */
2867  if( value1 != value2 )
2868  {
2869  SCIPdebugMessage("In constraint <%s> the resultant <%s> can be fixed to 0 because the negation of it is an operand.\n",
2870  SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
2871 
2872  SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
2873  *cutoff = *cutoff || infeasible;
2874 
2875  if( fixed )
2876  ++(*nfixedvars);
2877 
2878  return SCIP_OKAY;
2879  }
2880  /* x1 == AND(x1, x2 ...) => delete constraint and create all set-packing constraints x1 + ~x2 <= 1, x1 + ~... <= 1 */
2881  else
2882  {
2883  SCIP_CONS* cliquecons;
2884  SCIP_VAR* consvars[2];
2885  char name[SCIP_MAXSTRLEN];
2886 
2887  assert(value1 == value2);
2888 
2889  consvars[0] = consdata->resvar;
2890 
2891  for( v2 = nvars - 1; v2 >= 0; --v2 )
2892  {
2893  var2 = vars[v2];
2894  negated = FALSE;
2895  SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
2896 
2897  /* if the active representations of the resultant and an operand are different then we need to extract
2898  * this as a clique constraint
2899  *
2900  * if the active representations of the resultant and an operand are equal then the clique constraint
2901  * would look like x1 + ~x1 <= 1, which is redundant
2902  *
2903  * if the active representations of the resultant and an operand are negated of each other then the
2904  * clique constraint would look like x1 + x1 <= 1, which will lead to a fixation of the resultant later
2905  * on
2906  */
2907  if( var1 == var2 )
2908  {
2909  if( value1 == negated )
2910  {
2911  SCIPdebugMessage("In constraint <%s> the resultant <%s> can be fixed to 0 because the negation of it is an operand.\n",
2912  SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
2913 
2914  SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
2915  *cutoff = *cutoff || infeasible;
2916 
2917  if( fixed )
2918  ++(*nfixedvars);
2919 
2920  break;
2921  }
2922  }
2923  else
2924  {
2925  SCIP_CALL( SCIPgetNegatedVar(scip, vars[v2], &consvars[1]) );
2926  assert(consvars[1] != NULL);
2927 
2928  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%d", SCIPconsGetName(cons), v2);
2929 
2930  SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, 2, consvars,
2932  consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),
2934  !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
2935  SCIPdebugMessage(" -> adding clique constraint: ");
2936  SCIPdebugPrintCons(scip, cliquecons, NULL);
2937  SCIP_CALL( SCIPaddCons(scip, cliquecons) );
2938  SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
2939  ++(*naddconss);
2940  }
2941  }
2942 
2943  /* delete old constraint */
2944  SCIP_CALL( SCIPdelCons(scip, cons) );
2945  ++(*ndelconss);
2946 
2947  return SCIP_OKAY;
2948  }
2949  }
2950 
2951  /* due to SCIPvarsHaveCommonClique() returns on two same variables that they are in a clique, we need to handle
2952  * it explicitly
2953  */
2954  if( var1 == var2 && value1 == value2 )
2955  continue;
2956 
2957  /* due to SCIPvarsHaveCommonClique() returns on two negated variables that they are not in a clique, we need to
2958  * handle it explicitly
2959  */
2960  if( (var1 == var2 && value1 != value2) || SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
2961  {
2962  SCIPdebugMessage("in constraint <%s> the resultant <%s> can be fixed to 0 because it is in a clique with operand <%s>\n",
2963  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
2964 
2965  SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
2966  *cutoff = *cutoff || infeasible;
2967  if( fixed )
2968  ++(*nfixedvars);
2969 
2970  return SCIP_OKAY;
2971  }
2972  }
2973 
2974  if( !SCIPconsIsActive(cons) )
2975  return SCIP_OKAY;
2976 
2977  v2 = -1;
2978  /* check which operands have a negated variable */
2979  for( v = nvars - 1; v >= 0; --v )
2980  {
2981  assert(vars != NULL);
2982 
2983  var1 = vars[v];
2984  assert(var1 != NULL);
2985 
2986  negated = FALSE;
2987  SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
2988  assert(var1 != NULL);
2989 
2990  if( SCIPvarGetNegatedVar(var1) == NULL )
2991  {
2992  if( v2 >= 0 )
2993  break;
2994  v2 = v;
2995  }
2996  }
2997 
2998  allnegoperandsexist = FALSE;
2999 
3000  /* all operands have a negated variable, so we will check for all possible negated ciques */
3001  if( v2 == -1 )
3002  {
3003  allnegoperandsexist = TRUE;
3004  vstart = nvars - 1;
3005  vend = 0;
3006  }
3007  /* exactly one operands has no negated variable, so only this variable can be in a clique with all other negations */
3008  else if( v2 >= 0 && v == -1 )
3009  {
3010  vstart = v2;
3011  vend = v2;
3012  }
3013  /* at least two operands have no negated variable, so there is no possible clique with negated variables */
3014  else
3015  {
3016  vstart = -1;
3017  vend = 0;
3018  }
3019 
3020  /* case 2 */
3021  /* check for negated cliques in the operands */
3022  for( v = vstart; v >= vend; --v )
3023  {
3024  assert(vars != NULL);
3025 
3026  var1 = vars[v];
3027  assert(var1 != NULL);
3028 
3029  negated = FALSE;
3030  SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negated) );
3031  assert(var1 != NULL);
3032 
3033  if( negated )
3034  value1 = FALSE;
3035  else
3036  value1 = TRUE;
3037 
3038  for( v2 = nvars - 1; v2 >= 0; --v2 )
3039  {
3040  if( v2 == v )
3041  continue;
3042 
3043  var2 = vars[v2];
3044  assert(var2 != NULL);
3045 
3046  negated = FALSE;
3047  SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &negated) );
3048  assert(var2 != NULL);
3049 
3050  if( negated )
3051  value2 = FALSE;
3052  else
3053  value2 = TRUE;
3054 
3055  assert(SCIPvarGetNegatedVar(var2) != NULL);
3056 
3057  /* invert flag, because we want to check var 1 against all negations of the other variables */
3058  value2 = !value2;
3059 
3060  /* due to SCIPvarsHaveCommonClique() returns on two same variables that they are in a clique, we need to handle
3061  * it explicitly
3062  */
3063  if( var1 == var2 && value1 == value2 )
3064  {
3065  SCIPdebugMessage("in constraint <%s> the resultant <%s> can be fixed to 0 because two operands are negated of each other\n",
3066  SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar));
3067 
3068  SCIP_CALL( SCIPfixVar(scip, consdata->resvar, 0.0, &infeasible, &fixed) );
3069  *cutoff = *cutoff || infeasible;
3070  if( fixed )
3071  ++(*nfixedvars);
3072 
3073  return SCIP_OKAY;
3074  }
3075 
3076  /* due to SCIPvarsHaveCommonClique() returns on two negated variables that they are not in a clique, we need to
3077  * handle it explicitly
3078  */
3079  if( var1 == var2 && value1 != value2 )
3080  continue;
3081 
3082  if( !SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
3083  break;
3084  }
3085 
3086  if( v2 == -1 )
3087  {
3088  SCIP_Bool redundant;
3089  SCIP_Bool aggregated;
3090 
3091  SCIPdebugMessage("In constraint <%s> the operand <%s> is in a negated clique with all other operands, so we can aggregated this operand to the resultant <%s>.\n",
3092  SCIPconsGetName(cons), SCIPvarGetName(vars[v]), SCIPvarGetName(consdata->resvar));
3093 
3094  SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, vars[v], 1.0, -1.0, 0.0,
3095  &infeasible, &redundant, &aggregated) );
3096  *cutoff = *cutoff || infeasible;
3097 
3098  if( aggregated )
3099  ++(*naggrvars);
3100 
3101  return SCIP_OKAY;
3102  }
3103  }
3104 
3105  /* case 3 */
3106  /* check if the resultant and the negations of the operands are in a clique, then we can upgrade this constraint to a
3107  * set-partitioning constraint
3108  */
3109  if( allnegoperandsexist && SCIPconsIsActive(cons) )
3110  {
3111  SCIP_VAR** newvars;
3112  SCIP_Bool* negations;
3113  SCIP_Bool upgrade;
3114 
3115  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nvars + 1) );
3116  SCIP_CALL( SCIPallocBufferArray(scip, &negations, nvars + 1) );
3117  BMSclearMemoryArray(negations, nvars + 1);
3118 
3119  var1 = consdata->resvar;
3120  SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negations[nvars]) );
3121  assert(var1 != NULL);
3122  assert(SCIPvarGetStatus(var1) != SCIP_VARSTATUS_FIXED);
3123 
3124  newvars[nvars] = var1;
3125 
3126  /* get active variables */
3127  for( v = nvars - 1; v >= 0; --v )
3128  {
3129  assert(vars != NULL);
3130 
3131  var1 = vars[v];
3132  SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &negations[v]) );
3133  assert(var1 != NULL);
3134  assert(SCIPvarGetStatus(var1) != SCIP_VARSTATUS_FIXED);
3135 
3136  newvars[v] = var1;
3137 
3138  /* there should be no variable left that is equal or negated to the resultant */
3139  assert(newvars[v] != newvars[nvars]);
3140  }
3141 
3142  upgrade = TRUE;
3143 
3144  /* the resultant is in a clique with the negations of all operands, due to this AND-constraint */
3145  /* only check if the negations of all operands are in a clique */
3146  for( v = nvars - 1; v >= 0 && upgrade; --v )
3147  {
3148  for( v2 = v - 1; v2 >= 0; --v2 )
3149  {
3150  /* the resultant need to be in a clique with the negations of all operands */
3151  if( !SCIPvarsHaveCommonClique(newvars[v], negations[v], newvars[v2], negations[v2], TRUE) )
3152  {
3153  upgrade = FALSE;
3154  break;
3155  }
3156  }
3157  }
3158 
3159  /* all variables are in a clique, so upgrade thi AND-constraint */
3160  if( upgrade )
3161  {
3162  SCIP_CONS* cliquecons;
3163  char name[SCIP_MAXSTRLEN];
3164 
3165  /* get new constraint variables */
3166  if( negations[nvars] )
3167  {
3168  /* negation does not need to be existing, so SCIPvarGetNegatedVar() cannot be called
3169  * (e.g. resultant = ~x = 1 - x and x = y = newvars[nvars] and negations[nvars] = TRUE,
3170  * then y does not need to have a negated variable, yet)
3171  */
3172  SCIP_CALL( SCIPgetNegatedVar(scip, newvars[nvars], &(newvars[nvars])) );
3173  }
3174  assert(newvars[nvars] != NULL);
3175 
3176  for( v = nvars - 1; v >= 0; --v )
3177  {
3178  if( !negations[v] )
3179  {
3180  /* negation does not need to be existing, so SCIPvarGetNegatedVar() cannot be called
3181  * (e.g. vars[v] = ~x = 1 - x and x = y = newvars[v] and negations[v] = TRUE,
3182  * then y does not need to have a negated variable, yet)
3183  */
3184  SCIP_CALL( SCIPgetNegatedVar(scip, newvars[v], &(newvars[v])) );
3185  }
3186  assert(newvars[v] != NULL);
3187  }
3188 
3189  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clqeq", SCIPconsGetName(cons));
3190 
3191  SCIP_CALL( SCIPcreateConsSetpart(scip, &cliquecons, name, nvars + 1, newvars,
3193  consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
3195  !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
3196  SCIPdebugMessage(" -> upgrading AND-constraint <%s> with use of clique information to a set-partitioning constraint: \n", SCIPconsGetName(cons));
3197  SCIPdebugPrintCons(scip, cliquecons, NULL);
3198  SCIP_CALL( SCIPaddCons(scip, cliquecons) );
3199  SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
3200  ++(*naddconss);
3201 
3202  /* delete old constraint */
3203  SCIP_CALL( SCIPdelCons(scip, cons) );
3204  ++(*ndelconss);
3205  }
3206 
3207  SCIPfreeBufferArray(scip, &negations);
3208  SCIPfreeBufferArray(scip, &newvars);
3209  }
3210 
3211  return SCIP_OKAY;
3212 }
3213 
3214 /** gets the key of the given element */
3215 static
3216 SCIP_DECL_HASHGETKEY(hashGetKeyAndcons)
3217 { /*lint --e{715}*/
3218  /* the key is the element itself */
3219  return elem;
3220 }
3221 
3222 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
3223 static
3224 SCIP_DECL_HASHKEYEQ(hashKeyEqAndcons)
3226  SCIP_CONSDATA* consdata1;
3227  SCIP_CONSDATA* consdata2;
3228  SCIP_Bool coefsequal;
3229  int i;
3230 #ifndef NDEBUG
3231  SCIP* scip;
3232 
3233  scip = (SCIP*)userptr;
3234  assert(scip != NULL);
3235 #endif
3236 
3237  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
3238  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
3239 
3240  /* checks trivial case */
3241  if( consdata1->nvars != consdata2->nvars )
3242  return FALSE;
3243 
3244  /* sorts the constraints */
3245  consdataSort(consdata1);
3246  consdataSort(consdata2);
3247  assert(consdata1->sorted);
3248  assert(consdata2->sorted);
3249 
3250  coefsequal = TRUE;
3251 
3252  for( i = 0; i < consdata1->nvars ; ++i )
3253  {
3254  /* tests if variables are equal */
3255  if( consdata1->vars[i] != consdata2->vars[i] )
3256  {
3257  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
3258  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
3259  coefsequal = FALSE;
3260  break;
3261  }
3262  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
3263  }
3264 
3265  return coefsequal;
3266 }
3267 
3268 /** returns the hash value of the key */
3269 static
3270 SCIP_DECL_HASHKEYVAL(hashKeyValAndcons)
3271 { /*lint --e{715}*/
3272  SCIP_CONSDATA* consdata;
3273  unsigned int hashval;
3274  int minidx;
3275  int mididx;
3276  int maxidx;
3277 
3278  consdata = SCIPconsGetData((SCIP_CONS*)key);
3279  assert(consdata != NULL);
3280  assert(consdata->sorted);
3281  assert(consdata->nvars > 0);
3282 
3283  minidx = SCIPvarGetIndex(consdata->vars[0]);
3284  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
3285  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
3286  assert(minidx >= 0 && minidx <= maxidx);
3287 
3288  hashval = (consdata->nvars << 29) + (minidx << 22) + (mididx << 11) + maxidx; /*lint !e701*/
3289 
3290  return hashval;
3291 }
3292 
3293 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
3294  * accordingly; in contrast to removeRedundantConstraints(), it uses a hash table
3295  */
3296 static
3298  SCIP* scip, /**< SCIP data structure */
3299  BMS_BLKMEM* blkmem, /**< block memory */
3300  SCIP_CONS** conss, /**< constraint set */
3301  int nconss, /**< number of constraints in constraint set */
3302  int* firstchange, /**< pointer to store first changed constraint */
3303  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
3304  int* naggrvars, /**< pointer to count number of aggregated variables */
3305  int* ndelconss /**< pointer to count number of deleted constraints */
3306  )
3307 {
3308  SCIP_HASHTABLE* hashtable;
3309  int hashtablesize;
3310  int c;
3311 
3312  assert(conss != NULL);
3313  assert(ndelconss != NULL);
3314 
3315  /* create a hash table for the constraint set */
3316  hashtablesize = SCIPcalcHashtableSize(10*nconss);
3317  hashtablesize = MAX(hashtablesize, HASHSIZE_ANDCONS);
3318  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
3319  hashGetKeyAndcons, hashKeyEqAndcons, hashKeyValAndcons, (void*) scip) );
3320 
3321  *cutoff = FALSE;
3322 
3323  /* check all constraints in the given set for redundancy */
3324  for( c = 0; c < nconss; ++c )
3325  {
3326  SCIP_CONS* cons0;
3327  SCIP_CONS* cons1;
3328  SCIP_CONSDATA* consdata0;
3329 
3330  cons0 = conss[c];
3331 
3332  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
3333  continue;
3334 
3335  consdata0 = SCIPconsGetData(cons0);
3336  /* sort the constraint */
3337  consdataSort(consdata0);
3338  assert(consdata0->sorted);
3339 
3340  /* get constraint from current hash table with same variables as cons0 */
3341  cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
3342 
3343  if( cons1 != NULL )
3344  {
3345  SCIP_CONSDATA* consdata1;
3346  SCIP_Bool redundant;
3347 
3348 
3349  assert(SCIPconsIsActive(cons1));
3350  assert(!SCIPconsIsModifiable(cons1));
3351 
3352  consdata1 = SCIPconsGetData(cons1);
3353 
3354  assert(consdata0 != NULL && consdata1 != NULL);
3355  assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
3356 
3357  assert(consdata0->sorted && consdata1->sorted);
3358  assert(consdata0->vars[0] == consdata1->vars[0]);
3359 
3360  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3361  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
3362  redundant = FALSE;
3363 
3364  if( consdata0->resvar != consdata1->resvar )
3365  {
3366  SCIP_Bool aggregated;
3367 
3368  assert(SCIPvarCompare(consdata0->resvar, consdata1->resvar) != 0);
3369 
3370  /* aggregate resultants */
3371  SCIP_CALL( SCIPaggregateVars(scip, consdata0->resvar, consdata1->resvar, 1.0, -1.0, 0.0,
3372  cutoff, &redundant, &aggregated) );
3373  assert(redundant || SCIPdoNotAggr(scip));
3374 
3375  if( aggregated )
3376  ++(*naggrvars);
3377  if( *cutoff )
3378  goto TERMINATE;
3379  }
3380  else
3381  redundant = TRUE;
3382 
3383  /* delete consdel */
3384  if( redundant )
3385  {
3386  /* also take the check when upgrade flag over if necessary */
3387  consdata1->checkwhenupgr = consdata1->checkwhenupgr || consdata0->checkwhenupgr;
3388  consdata1->notremovablewhenupgr = consdata1->notremovablewhenupgr || consdata0->notremovablewhenupgr;
3389 
3390  SCIP_CALL( SCIPdelCons(scip, cons0) );
3391  (*ndelconss)++;
3392  }
3393 
3394  /* update the first changed constraint to begin the next aggregation round with */
3395  if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
3396  *firstchange = SCIPconsGetPos(cons1);
3397 
3398  assert(SCIPconsIsActive(cons1));
3399  }
3400  else
3401  {
3402  /* no such constraint in current hash table: insert cons0 into hash table */
3403  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
3404  }
3405  }
3406  TERMINATE:
3407  /* free hash table */
3408  SCIPhashtableFree(&hashtable);
3409 
3410  return SCIP_OKAY;
3411 }
3412 
3413 
3414 /** compares constraint with all prior constraints for possible redundancy or aggregation,
3415  * and removes or changes constraint accordingly
3416  */
3417 static
3419  SCIP* scip, /**< SCIP data structure */
3420  SCIP_CONS** conss, /**< constraint set */
3421  int firstchange, /**< first constraint that changed since last pair preprocessing round */
3422  int chkind, /**< index of constraint to check against all prior indices upto startind */
3423  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
3424  int* naggrvars, /**< pointer to count number of aggregated variables */
3425  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
3426  int* ndelconss /**< pointer to count number of deleted constraints */
3427  )
3428 {
3429  SCIP_CONS* cons0;
3430  SCIP_CONSDATA* consdata0;
3431  SCIP_Bool cons0changed;
3432  int c;
3433 
3434  assert(conss != NULL);
3435  assert(firstchange <= chkind);
3436  assert(cutoff != NULL);
3437  assert(naggrvars != NULL);
3438  assert(nbdchgs != NULL);
3439  assert(ndelconss != NULL);
3440 
3441  /* get the constraint to be checked against all prior constraints */
3442  cons0 = conss[chkind];
3443  assert(SCIPconsIsActive(cons0));
3444  assert(!SCIPconsIsModifiable(cons0));
3445 
3446  consdata0 = SCIPconsGetData(cons0);
3447  assert(consdata0 != NULL);
3448  assert(consdata0->nvars >= 1);
3449 
3450  /* sort the constraint */
3451  consdataSort(consdata0);
3452  assert(consdata0->sorted);
3453 
3454  /* check constraint against all prior constraints */
3455  cons0changed = consdata0->changed;
3456 
3457  if( SCIPconsIsActive(cons0) )
3458  {
3459  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff); ++c )
3460  {
3461  SCIP_CONS* cons1;
3462  SCIP_CONSDATA* consdata1;
3463  SCIP_Bool cons0superset;
3464  SCIP_Bool cons1superset;
3465  int v0;
3466  int v1;
3467 
3468  if( c % 1000 == 0 && SCIPisStopped(scip) )
3469  break;
3470 
3471  cons1 = conss[c];
3472 
3473  /* ignore inactive and modifiable constraints */
3474  if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
3475  continue;
3476 
3477  consdata1 = SCIPconsGetData(cons1);
3478  assert(consdata1 != NULL);
3479 
3480 #if 0
3481  SCIPdebugMessage("preprocess AND-constraint pair <%s>[chg:%d] and <%s>[chg:%d]\n",
3482  SCIPconsGetName(cons0), cons0changed, SCIPconsGetName(cons1), consdata1->changed);
3483 #endif
3484 
3485  /* if both constraints were not changed since last round, we can ignore the pair */
3486  if( !cons0changed && !consdata1->changed )
3487  continue;
3488 
3489  assert(consdata1->nvars >= 1);
3490 
3491  /* sort the constraint */
3492  consdataSort(consdata1);
3493  assert(consdata1->sorted);
3494 
3495  /* check consdata0 against consdata1:
3496  * - if they consist of the same operands, the resultants can be aggregated
3497  * - if one operand list is a subset of the other, add implication r0 = 1 -> r1 = 1, or r1 = 1 -> r0 = 1
3498  */
3499  v0 = 0;
3500  v1 = 0;
3501  cons0superset = TRUE;
3502  cons1superset = TRUE;
3503  while( (v0 < consdata0->nvars || v1 < consdata1->nvars) && (cons0superset || cons1superset) )
3504  {
3505  int varcmp;
3506 
3507  /* test, if variable appears in only one or in both constraints */
3508  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
3509  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
3510  else if( v0 < consdata0->nvars )
3511  varcmp = -1;
3512  else
3513  varcmp = +1;
3514 
3515  switch( varcmp )
3516  {
3517  case -1:
3518  /* variable doesn't appear in consdata1 */
3519  cons1superset = FALSE;
3520  v0++;
3521  break;
3522 
3523  case +1:
3524  /* variable doesn't appear in consdata0 */
3525  cons0superset = FALSE;
3526  v1++;
3527  break;
3528 
3529  case 0:
3530  /* variable appears in both constraints */
3531  v0++;
3532  v1++;
3533  break;
3534 
3535  default:
3536  SCIPerrorMessage("invalid comparison result\n");
3537  SCIPABORT();
3538  return SCIP_INVALIDDATA; /*lint !e527*/
3539  }
3540  }
3541 
3542  /* check for equivalence and domination */
3543  if( cons0superset && cons1superset )
3544  {
3545  SCIP_Bool infeasible;
3546  SCIP_Bool redundant;
3547  SCIP_Bool aggregated;
3548 
3549  /* constraints are equivalent */
3550  SCIPdebugMessage("equivalent AND-constraints <%s> and <%s>: aggregate resultants <%s> == <%s>\n",
3551  SCIPconsGetName(cons0), SCIPconsGetName(cons1), SCIPvarGetName(consdata0->resvar),
3552  SCIPvarGetName(consdata1->resvar));
3553 
3554  /* aggregate resultants */
3555  SCIP_CALL( SCIPaggregateVars(scip, consdata0->resvar, consdata1->resvar, 1.0, -1.0, 0.0,
3556  &infeasible, &redundant, &aggregated) );
3557  assert(redundant || SCIPdoNotAggr(scip));
3558 
3559  if( aggregated )
3560  {
3561  assert(redundant);
3562  (*naggrvars)++;
3563  }
3564 
3565  if( redundant )
3566  {
3567  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3568  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
3569 
3570  /* also take the check when upgrade flag over if necessary */
3571  consdata0->checkwhenupgr = consdata1->checkwhenupgr || consdata0->checkwhenupgr;
3572  consdata0->notremovablewhenupgr = consdata1->notremovablewhenupgr || consdata0->notremovablewhenupgr;
3573 
3574  /* delete constraint */
3575  SCIP_CALL( SCIPdelCons(scip, cons1) );
3576  (*ndelconss)++;
3577  }
3578 
3579  *cutoff = *cutoff || infeasible;
3580  }
3581  else if( cons0superset )
3582  {
3583  SCIP_Bool infeasible;
3584  int nboundchgs;
3585 
3586  /* the conjunction of cons0 is a superset of the conjunction of cons1 */
3587  SCIPdebugMessage("AND-constraint <%s> is superset of <%s>: add implication <%s> = 1 -> <%s> = 1\n",
3588  SCIPconsGetName(cons0), SCIPconsGetName(cons1), SCIPvarGetName(consdata0->resvar),
3589  SCIPvarGetName(consdata1->resvar));
3590 
3591  /* add implication */
3592  SCIP_CALL( SCIPaddVarImplication(scip, consdata0->resvar, TRUE, consdata1->resvar, SCIP_BOUNDTYPE_LOWER, 1.0,
3593  &infeasible, &nboundchgs) );
3594  *cutoff = *cutoff || infeasible;
3595  (*nbdchgs) += nboundchgs;
3596  }
3597  else if( cons1superset )
3598  {
3599  SCIP_Bool infeasible;
3600  int nboundchgs;
3601 
3602  /* the conjunction of cons1 is a superset of the conjunction of cons0 */
3603  SCIPdebugMessage("AND-constraint <%s> is superset of <%s>: add implication <%s> = 1 -> <%s> = 1\n",
3604  SCIPconsGetName(cons1), SCIPconsGetName(cons0), SCIPvarGetName(consdata1->resvar),
3605  SCIPvarGetName(consdata0->resvar));
3606 
3607  /* add implication */
3608  SCIP_CALL( SCIPaddVarImplication(scip, consdata1->resvar, TRUE, consdata0->resvar, SCIP_BOUNDTYPE_LOWER, 1.0,
3609  &infeasible, &nboundchgs) );
3610  *cutoff = *cutoff || infeasible;
3611  (*nbdchgs) += nboundchgs;
3612  }
3613  }
3614  }
3615  consdata0->changed = FALSE;
3616 
3617  return SCIP_OKAY;
3618 }
3619 
3620 /** tries to reformulate an expression graph node that is a product of binary variables via introducing an AND-constraint */
3621 static
3622 SCIP_DECL_EXPRGRAPHNODEREFORM(exprgraphnodeReformAnd)
3624  SCIP_EXPRGRAPHNODE* child;
3625  char name[SCIP_MAXSTRLEN];
3626  int nchildren;
3627  SCIP_CONS* cons;
3628  SCIP_VAR** vars;
3629  SCIP_VAR* var;
3630  int c;
3631 
3632  assert(scip != NULL);
3633  assert(exprgraph != NULL);
3634  assert(node != NULL);
3635  assert(naddcons != NULL);
3636  assert(reformnode != NULL);
3637 
3638  *reformnode = NULL;
3639 
3640  /* allow only products given as EXPR_PRODUCT or EXPR_POLYNOMIAL with only 1 monomial */
3643  )
3644  return SCIP_OKAY;
3645 
3646  nchildren = SCIPexprgraphGetNodeNChildren(node);
3647 
3648  /* for a polynomial with only one monomial, all children should appear as factors in the monomial
3649  * since we assume that the factors have been merged, this means that the number of factors in the monomial should equal the number of children of the node
3650  */
3652 
3653  /* check only products with at least 3 variables (2 variables are taken of by cons_quadratic) */
3654  if( nchildren <= 2 )
3655  return SCIP_OKAY;
3656 
3657  /* check if all factors correspond to binary variables, and if so, setup vars array */
3658  for( c = 0; c < nchildren; ++c )
3659  {
3660  child = SCIPexprgraphGetNodeChildren(node)[c];
3661 
3663  return SCIP_OKAY;
3664 
3665  var = (SCIP_VAR*)SCIPexprgraphGetNodeVar(exprgraph, child);
3666  if( !SCIPvarIsBinary(var) )
3667  return SCIP_OKAY;
3668  }
3669 
3670  /* node corresponds to product of binary variables (maybe with coefficient and constant, if polynomial) */
3671  SCIPdebugMessage("reformulate node %p via AND-constraint\n", (void*)node);
3672 
3673  /* collect variables in product */
3674  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nchildren) );
3675  for( c = 0; c < nchildren; ++c )
3676  {
3677  child = SCIPexprgraphGetNodeChildren(node)[c];
3678  vars[c] = (SCIP_VAR*)SCIPexprgraphGetNodeVar(exprgraph, child);
3679  }
3680 
3681  /* create variable for resultant
3682  * cons_and wants to add implications for resultant, which is only possible for binary variables currently
3683  * so choose binary as vartype, even though implicit integer had been sufficient
3684  */
3685  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "nlreform%dand", *naddcons);
3686  SCIP_CALL( SCIPcreateVar(scip, &var, name, 0.0, 1.0, 0.0, SCIP_VARTYPE_BINARY,
3687  TRUE, TRUE, NULL, NULL, NULL, NULL, NULL) );
3688  SCIP_CALL( SCIPaddVar(scip, var) );
3689 
3690 #ifdef SCIP_DEBUG_SOLUTION
3691  if( SCIPdebugIsMainscip(scip) )
3692  {
3693  SCIP_Bool debugval;
3694  SCIP_Real varval;
3695 
3696  debugval = TRUE;
3697  for( c = 0; c < nchildren; ++c )
3698  {
3699  SCIP_CALL( SCIPdebugGetSolVal(scip, vars[c], &varval) );
3700  debugval = debugval && (varval > 0.5);
3701  }
3702  SCIP_CALL( SCIPdebugAddSolVal(scip, var, debugval ? 1.0 : 0.0) );
3703  }
3704 #endif
3705 
3706  /* create AND-constraint */
3707  SCIP_CALL( SCIPcreateConsAnd(scip, &cons, name, var, nchildren, vars,
3708  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
3709  SCIP_CALL( SCIPaddCons(scip, cons) );
3710  SCIPdebugPrintCons(scip, cons, NULL);
3711  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3712  ++*naddcons;
3713 
3714  SCIPfreeBufferArray(scip, &vars);
3715 
3716  /* add var to exprgraph */
3717  SCIP_CALL( SCIPexprgraphAddVars(exprgraph, 1, (void**)&var, reformnode) );
3718  SCIP_CALL( SCIPreleaseVar(scip, &var) );
3719 
3720  /* if we have coefficient and constant, then replace reformnode by linear expression in reformnode */
3722  {
3723  SCIP_Real coef;
3724  SCIP_Real constant;
3725 
3727  constant = SCIPexprgraphGetNodePolynomialConstant(node);
3728 
3729  if( coef != 1.0 || constant != 0.0 )
3730  {
3731  SCIP_EXPRGRAPHNODE* linnode;
3732  SCIP_CALL( SCIPexprgraphCreateNodeLinear(SCIPblkmem(scip), &linnode, 1, &coef, constant) );
3733  SCIP_CALL( SCIPexprgraphAddNode(exprgraph, linnode, -1, 1, reformnode) );
3734  *reformnode = linnode;
3735  }
3736  }
3737 
3738  return SCIP_OKAY;
3739 }
3740 
3741 /*
3742  * Callback methods of constraint handler
3743  */
3744 
3745 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
3746 static
3747 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyAnd)
3748 { /*lint --e{715}*/
3749  assert(scip != NULL);
3750  assert(conshdlr != NULL);
3751  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3752 
3753  /* call inclusion method of constraint handler */
3755 
3756  *valid = TRUE;
3757 
3758  return SCIP_OKAY;
3759 }
3760 
3761 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
3762 static
3763 SCIP_DECL_CONSFREE(consFreeAnd)
3764 { /*lint --e{715}*/
3765  SCIP_CONSHDLRDATA* conshdlrdata;
3766 
3767  /* free constraint handler data */
3768  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3769  assert(conshdlrdata != NULL);
3770 
3771  SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
3772 
3773  SCIPconshdlrSetData(conshdlr, NULL);
3774 
3775  return SCIP_OKAY;
3776 }
3777 
3778 
3779 /** presolving initialization method of constraint handler (called when presolving is about to begin) */
3780 static
3781 SCIP_DECL_CONSINITPRE(consInitpreAnd)
3782 { /*lint --e{715}*/
3783  SCIP_CONSHDLRDATA* conshdlrdata;
3784 
3785  assert( scip != NULL );
3786  assert( conshdlr != NULL );
3787  assert( nconss == 0 || conss != NULL );
3788 
3789  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3790  assert(conshdlrdata != NULL);
3791 
3792  if( conshdlrdata->linearize )
3793  {
3794  /* linearize all AND-constraints and remove the AND-constraints */
3795  SCIP_CONS* newcons;
3796  SCIP_CONS* cons;
3797  SCIP_CONSDATA* consdata;
3798  char consname[SCIP_MAXSTRLEN];
3799 
3800  SCIP_VAR** vars;
3801  SCIP_Real* vals;
3802 
3803  int nvars;
3804  int c, v;
3805 
3806  /* allocate buffer array */
3807  SCIP_CALL( SCIPallocBufferArray(scip, &vars, 2) );
3808  SCIP_CALL( SCIPallocBufferArray(scip, &vals, 2) );
3809 
3810  for( c = 0; c < nconss; ++c )
3811  {
3812  cons = conss[c];
3813  assert( cons != NULL );
3814 
3815  /* only added constraints can be upgraded */
3816  if( !SCIPconsIsAdded(cons) )
3817  continue;
3818 
3819  consdata = SCIPconsGetData(cons);
3820  assert( consdata != NULL );
3821  assert( consdata->resvar != NULL );
3822 
3823  nvars = consdata->nvars;
3824 
3825  if( !conshdlrdata->aggrlinearization )
3826  {
3827  vars[0] = consdata->resvar;
3828  vals[0] = 1.0;
3829  vals[1] = -1.0;
3830 
3831  /* create operator linear constraints */
3832  for( v = 0; v < nvars; ++v )
3833  {
3834  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_%d", SCIPconsGetName(cons), v);
3835  vars[1] = consdata->vars[v];
3836 
3837  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, 2, vars, vals, -SCIPinfinity(scip), 0.0,
3839  consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
3841  !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
3842 
3843 
3844  /* add constraint */
3845  SCIP_CALL( SCIPaddCons(scip, newcons) );
3846  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3847  }
3848  }
3849 
3850  /* reallocate buffer array */
3851  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, nvars + 1) );
3852  SCIP_CALL( SCIPreallocBufferArray(scip, &vals, nvars + 1) );
3853 
3854  for( v = 0; v < nvars; ++v )
3855  {
3856  vars[v] = consdata->vars[v];
3857  vals[v] = -1.0;
3858  }
3859 
3860  vars[nvars] = consdata->resvar;
3861 
3862  if( conshdlrdata->aggrlinearization )
3863  {
3864  /* create additional linear constraint */
3865  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_operators", SCIPconsGetName(cons));
3866 
3867  vals[nvars] = (SCIP_Real) nvars;
3868 
3869  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, nvars + 1, vars, vals, -SCIPinfinity(scip), 0.0,
3871  consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
3873  !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
3874 
3875  /* add constraint */
3876  SCIP_CALL( SCIPaddCons(scip, newcons) );
3877  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3878  }
3879 
3880  /* create additional linear constraint */
3881  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "%s_add", SCIPconsGetName(cons));
3882 
3883  vals[nvars] = 1.0;
3884 
3885  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, nvars + 1, vars, vals, -nvars + 1.0, SCIPinfinity(scip),
3887  consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
3889  !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
3890 
3891  /* add constraint */
3892  SCIP_CALL( SCIPaddCons(scip, newcons) );
3893  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
3894 
3895  /* delete constraint */
3896  SCIP_CALL( SCIPdelCons(scip, cons) );
3897  }
3898 
3899  /* free buffer array */
3900  SCIPfreeBufferArray(scip, &vars);
3901  SCIPfreeBufferArray(scip, &vals);
3902  }
3903 
3904  return SCIP_OKAY;
3905 }
3906 
3907 
3908 #ifdef GMLGATEPRINTING
3909 
3910 #define HASHTABLESIZE_FACTOR 5
3911 
3912 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
3913 static
3914 SCIP_DECL_CONSEXITPRE(consExitpreAnd)
3915 { /*lint --e{715}*/
3916  SCIP_HASHMAP* hashmap;
3917  FILE* gmlfile;
3918  char fname[SCIP_MAXSTRLEN];
3919  SCIP_CONS* cons;
3920  SCIP_CONSDATA* consdata;
3921  SCIP_VAR** activeconsvars;
3922  SCIP_VAR* activevar;
3923  int* varnodeids;
3924  SCIP_VAR** vars;
3925  int nvars;
3926  int nbinvars;
3927  int nintvars;
3928  int nimplvars;
3929  int ncontvars;
3930  int v;
3931  int c;
3932  unsigned int resid;
3933  unsigned int varid;
3934  unsigned int id = 1;
3935 
3936  /* no AND-constraints available */
3937  if( nconss == 0 )
3938  return SCIP_OKAY;
3939 
3940  nvars = SCIPgetNVars(scip);
3941 
3942  /* no variables left anymore */
3943  if( nvars == 0 )
3944  return SCIP_OKAY;
3945 
3946  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
3947  SCIP_CALL( SCIPallocBufferArray(scip, &varnodeids, nvars) );
3948  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, &nimplvars, &ncontvars) );
3949 
3950  /* open gml file */
3951  (void) SCIPsnprintf(fname, SCIP_MAXSTRLEN, "and-gates%p.gml", scip);
3952  gmlfile = fopen(fname, "w");
3953 
3954  if( gmlfile == NULL )
3955  {
3956  SCIPerrorMessage("cannot open graph file <%s>\n", fname);
3957  SCIPABORT();
3958  return SCIP_WRITEERROR; /*lint !e527*/
3959  }
3960 
3961  /* create the variable mapping hash map */
3963 
3964  /* write starting of gml file */
3965  SCIPgmlWriteOpening(gmlfile, TRUE);
3966 
3967  /* walk over all AND-constraints */
3968  for( c = nconss - 1; c >= 0; --c )
3969  {
3970  cons = conss[c];
3971 
3972  /* only handle active constraints */
3973  if( !SCIPconsIsActive(cons) )
3974  continue;
3975 
3976  consdata = SCIPconsGetData(cons);
3977  assert(consdata != NULL);
3978 
3979  /* only handle constraints which have operands */
3980  if( consdata->nvars == 0 )
3981  continue;
3982 
3983  assert(consdata->vars != NULL);
3984  assert(consdata->resvar != NULL);
3985 
3986  /* get active variable of resultant */
3987  activevar = SCIPvarGetProbvar(consdata->resvar);
3988 
3989  /* check if we already found this variables */
3990  resid = (unsigned int)(size_t) SCIPhashmapGetImage(hashmap, activevar);
3991  if( resid == 0 )
3992  {
3993  resid = id;
3994  ++id;
3995  SCIP_CALL( SCIPhashmapInsert(hashmap, (void*)activevar, (void*)(size_t)resid) );
3996 
3997  /* write new gml node for new resultant */
3998  SCIPgmlWriteNode(gmlfile, resid, SCIPvarGetName(activevar), NULL, NULL, NULL);
3999  }
4000 
4001  /* copy operands to get problem variables for */
4002  SCIP_CALL( SCIPduplicateBufferArray(scip, &activeconsvars, consdata->vars, consdata->nvars) );
4003 
4004  /* get problem variables of operands */
4005  SCIPvarsGetProbvar(activeconsvars, consdata->nvars);
4006 
4007  for( v = consdata->nvars - 1; v >= 0; --v )
4008  {
4009  /* check if we already found this variables */
4010  varid = (unsigned int)(size_t) SCIPhashmapGetImage(hashmap, activeconsvars[v]);
4011  if( varid == 0 )
4012  {
4013  varid = id;
4014  ++id;
4015  SCIP_CALL( SCIPhashmapInsert(hashmap, (void*)activeconsvars[v], (void*)(size_t)varid) );
4016 
4017  /* write new gml node for new operand */
4018  SCIPgmlWriteNode(gmlfile, varid, SCIPvarGetName(activeconsvars[v]), NULL, NULL, NULL);
4019  }
4020  /* write gml arc between resultant and operand */
4021  SCIPgmlWriteArc(gmlfile, resid, varid, NULL, NULL);
4022  }
4023 
4024  /* free temporary memory for active constraint variables */
4025  SCIPfreeBufferArray(scip, &activeconsvars);
4026  }
4027 
4028  /* write all remaining variables as nodes */
4029 #if 0
4030  for( v = nvars - 1; v >= 0; --v )
4031  {
4032  activevar = SCIPvarGetProbvar(vars[v]);
4033 
4034  varid = (unsigned int)(size_t) SCIPhashmapGetImage(hashmap, activevar);
4035  if( varid == 0 )
4036  {
4037  varid = id;
4038  ++id;
4039  SCIP_CALL( SCIPhashmapInsert(hashmap, (void*)activeconsvars[v], (void*)(size_t)varid) );
4040 
4041  /* write new gml node for new operand */
4042  SCIPgmlWriteNode(gmlfile, varid, SCIPvarGetName(activevar), NULL, NULL, NULL);
4043  }
4044  }
4045 #endif
4046 
4047  /* free the variable mapping hash map */
4048  SCIPhashmapFree(&hashmap);
4049 
4050  SCIPgmlWriteClosing(gmlfile);
4051 
4052  fclose(gmlfile);
4053 
4054  SCIPfreeBufferArray(scip, &varnodeids);
4055  SCIPfreeBufferArray(scip, &vars);
4056 
4057  return SCIP_OKAY;
4058 }
4059 #endif
4060 
4061 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
4062 static
4063 SCIP_DECL_CONSEXITSOL(consExitsolAnd)
4064 { /*lint --e{715}*/
4065  SCIP_CONSDATA* consdata;
4066  int c;
4067 
4068  /* release and free the rows of all constraints */
4069  for( c = 0; c < nconss; ++c )
4070  {
4071  consdata = SCIPconsGetData(conss[c]);
4072  assert(consdata != NULL);
4073 
4074  SCIP_CALL( consdataFreeRows(scip, consdata) );
4075  }
4076 
4077  return SCIP_OKAY;
4078 }
4079 
4080 
4081 /** frees specific constraint data */
4082 static
4083 SCIP_DECL_CONSDELETE(consDeleteAnd)
4084 { /*lint --e{715}*/
4085  SCIP_CONSHDLRDATA* conshdlrdata;
4086 
4087  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4088  assert(conshdlrdata != NULL);
4089 
4090  SCIP_CALL( consdataFree(scip, consdata, conshdlrdata->eventhdlr) );
4091 
4092  return SCIP_OKAY;
4093 }
4094 
4095 
4096 /** transforms constraint data into data belonging to the transformed problem */
4097 static
4098 SCIP_DECL_CONSTRANS(consTransAnd)
4099 { /*lint --e{715}*/
4100  SCIP_CONSHDLRDATA* conshdlrdata;
4101  SCIP_CONSDATA* sourcedata;
4102  SCIP_CONSDATA* targetdata;
4103 
4104  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4105  assert(conshdlrdata != NULL);
4106 
4107  sourcedata = SCIPconsGetData(sourcecons);
4108  assert(sourcedata != NULL);
4109 
4110  /* create target constraint data */
4111  SCIP_CALL( consdataCreate(scip, &targetdata, conshdlrdata->eventhdlr,
4112  sourcedata->nvars, sourcedata->vars, sourcedata->resvar, sourcedata->checkwhenupgr,
4113  sourcedata->notremovablewhenupgr) );
4114 
4115  /* create target constraint */
4116  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
4117  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
4118  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
4119  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
4120  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
4121 
4122  return SCIP_OKAY;
4123 }
4124 
4125 
4126 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
4127 static
4128 SCIP_DECL_CONSINITLP(consInitlpAnd)
4129 { /*lint --e{715}*/
4130  int i;
4131 
4132  for( i = 0; i < nconss; i++ )
4133  {
4134  assert(SCIPconsIsInitial(conss[i]));
4135  SCIP_CALL( addRelaxation(scip, conss[i]) );
4136  }
4137 
4138  return SCIP_OKAY;
4139 }
4140 
4141 
4142 /** separation method of constraint handler for LP solutions */
4143 static
4144 SCIP_DECL_CONSSEPALP(consSepalpAnd)
4145 { /*lint --e{715}*/
4146  SCIP_Bool separated;
4147  SCIP_Bool cutoff;
4148  int c;
4149 
4150  *result = SCIP_DIDNOTFIND;
4151 
4152  /* separate all useful constraints */
4153  for( c = 0; c < nusefulconss; ++c )
4154  {
4155  SCIP_CALL( separateCons(scip, conss[c], NULL, &separated, &cutoff) );
4156  if ( cutoff )
4157  *result = SCIP_CUTOFF;
4158  else if ( separated )
4159  *result = SCIP_SEPARATED;
4160  }
4161 
4162  /* combine constraints to get more cuts */
4163  /**@todo combine constraints to get further cuts */
4164 
4165  return SCIP_OKAY;
4166 }
4167 
4168 
4169 /** separation method of constraint handler for arbitrary primal solutions */
4170 static
4171 SCIP_DECL_CONSSEPASOL(consSepasolAnd)
4172 { /*lint --e{715}*/
4173  SCIP_Bool separated;
4174  SCIP_Bool cutoff;
4175  int c;
4176 
4177  *result = SCIP_DIDNOTFIND;
4178 
4179  /* separate all useful constraints */
4180  for( c = 0; c < nusefulconss; ++c )
4181  {
4182  SCIP_CALL( separateCons(scip, conss[c], sol, &separated, &cutoff) );
4183  if ( cutoff )
4184  *result = SCIP_CUTOFF;
4185  else if ( separated )
4186  *result = SCIP_SEPARATED;
4187  }
4188 
4189  /* combine constraints to get more cuts */
4190  /**@todo combine constraints to get further cuts */
4191 
4192  return SCIP_OKAY;
4193 }
4194 
4195 
4196 /** constraint enforcing method of constraint handler for LP solutions */
4197 static
4198 SCIP_DECL_CONSENFOLP(consEnfolpAnd)
4199 { /*lint --e{715}*/
4200  SCIP_CONSHDLRDATA* conshdlrdata;
4201  SCIP_Bool separated;
4202  SCIP_Bool violated;
4203  SCIP_Bool cutoff;
4204  int i;
4205 
4206  separated = FALSE;
4207 
4208  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4209  assert(conshdlrdata != NULL);
4210 
4211  /* method is called only for integral solutions, because the enforcing priority is negative */
4212  for( i = 0; i < nconss; i++ )
4213  {
4214  SCIP_CALL( checkCons(scip, conss[i], NULL, FALSE, FALSE, &violated) );
4215  if( violated )
4216  {
4217  if( conshdlrdata->enforcecuts )
4218  {
4219  SCIP_Bool consseparated;
4220 
4221  SCIP_CALL( separateCons(scip, conss[i], NULL, &consseparated, &cutoff) );
4222  if ( cutoff )
4223  {
4224  *result = SCIP_CUTOFF;
4225  return SCIP_OKAY;
4226  }
4227  separated = separated || consseparated;
4228 
4229  /* following assert is wrong in the case some variables were not in LP (dynamic columns),
4230  *
4231  * e.g. the resultant, which has a negative objective value, is in the lp solution on its upper bound
4232  * (variables with status loose are in an lp solution on it's best bound), but already creating a row, and
4233  * thereby creating the column, changes the solution value (variable than has status column, and the
4234  * initialization sets the lp solution value) to 0.0, and this already could lead to no violation of the
4235  * rows, which then are not seperated into the lp
4236  */
4237 #if 0
4238  assert(consseparated); /* because the solution is integral, the separation always finds a cut */
4239 #endif
4240  }
4241  else
4242  {
4243  *result = SCIP_INFEASIBLE;
4244  return SCIP_OKAY;
4245  }
4246  }
4247  }
4248 
4249  if( separated )
4250  *result = SCIP_SEPARATED;
4251  else
4252  *result = SCIP_FEASIBLE;
4253 
4254  return SCIP_OKAY;
4255 }
4256 
4257 
4258 /** constraint enforcing method of constraint handler for pseudo solutions */
4259 static
4260 SCIP_DECL_CONSENFOPS(consEnfopsAnd)
4261 { /*lint --e{715}*/
4262  SCIP_Bool violated;
4263  int i;
4264 
4265  /* method is called only for integral solutions, because the enforcing priority is negative */
4266  for( i = 0; i < nconss; i++ )
4267  {
4268  SCIP_CALL( checkCons(scip, conss[i], NULL, TRUE, FALSE, &violated) );
4269  if( violated )
4270  {
4271  *result = SCIP_INFEASIBLE;
4272  return SCIP_OKAY;
4273  }
4274  }
4275  *result = SCIP_FEASIBLE;
4276 
4277  return SCIP_OKAY;
4278 }
4279 
4280 
4281 /** feasibility check method of constraint handler for integral solutions */
4282 static
4283 SCIP_DECL_CONSCHECK(consCheckAnd)
4284 { /*lint --e{715}*/
4285  SCIP_Bool violated;
4286  int i;
4287 
4288  /* method is called only for integral solutions, because the enforcing priority is negative */
4289  for( i = 0; i < nconss; i++ )
4290  {
4291  SCIP_CALL( checkCons(scip, conss[i], sol, checklprows, printreason, &violated) );
4292  if( violated )
4293  {
4294  *result = SCIP_INFEASIBLE;
4295  return SCIP_OKAY;
4296  }
4297  }
4298  *result = SCIP_FEASIBLE;
4299 
4300  return SCIP_OKAY;
4301 }
4302 
4303 
4304 /** domain propagation method of constraint handler */
4305 static
4306 SCIP_DECL_CONSPROP(consPropAnd)
4307 { /*lint --e{715}*/
4308  SCIP_CONSHDLRDATA* conshdlrdata;
4309  SCIP_Bool cutoff;
4310  int nfixedvars;
4311  int nupgdconss;
4312  int c;
4313 
4314  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4315  assert(conshdlrdata != NULL);
4316 
4317  cutoff = FALSE;
4318  nfixedvars = 0;
4319  nupgdconss = 0;
4320 
4321  /* propagate all useful constraints */
4322  for( c = 0; c < nusefulconss && !cutoff; ++c )
4323  {
4324  SCIP_CALL( propagateCons(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &nfixedvars, &nupgdconss) );
4325  }
4326 
4327  /* return the correct result */
4328  if( cutoff )
4329  *result = SCIP_CUTOFF;
4330  else if( nfixedvars > 0 || nupgdconss > 0 )
4331  *result = SCIP_REDUCEDDOM;
4332  else
4333  *result = SCIP_DIDNOTFIND;
4334 
4335  return SCIP_OKAY;
4336 }
4337 
4338 
4339 /** presolving method of constraint handler */
4340 static
4341 SCIP_DECL_CONSPRESOL(consPresolAnd)
4342 { /*lint --e{715}*/
4343  SCIP_CONSHDLRDATA* conshdlrdata;
4344  SCIP_CONS* cons;
4345  SCIP_CONSDATA* consdata;
4346  unsigned char* entries;
4347  SCIP_Bool cutoff;
4348  int oldnfixedvars;
4349  int oldnaggrvars;
4350  int oldnchgbds;
4351  int oldndelconss;
4352  int oldnupgdconss;
4353  int firstchange;
4354  int nentries;
4355  int c;
4356 
4357  assert(result != NULL);
4358 
4359  oldnfixedvars = *nfixedvars;
4360  oldnaggrvars = *naggrvars;
4361  oldnchgbds = *nchgbds;
4362  oldndelconss = *ndelconss;
4363  oldnupgdconss = *nupgdconss;
4364 
4365  nentries = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
4366  SCIP_CALL( SCIPallocBufferArray(scip, &entries, nentries) );
4367 
4368  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4369  assert(conshdlrdata != NULL);
4370 
4371  /* process constraints */
4372  cutoff = FALSE;
4373  firstchange = INT_MAX;
4374  for( c = 0; c < nconss && !cutoff && (c % 1000 != 0 || !SCIPisStopped(scip)); ++c )
4375  {
4376  cons = conss[c];
4377  assert(cons != NULL);
4378  consdata = SCIPconsGetData(cons);
4379  assert(consdata != NULL);
4380 
4381  /* force presolving the constraint in the initial round */
4382  if( nrounds == 0 )
4383  consdata->propagated = FALSE;
4384 
4385  /* remember the first changed constraint to begin the next aggregation round with */
4386  if( firstchange == INT_MAX && consdata->changed )
4387  firstchange = c;
4388 
4389  /* propagate constraint */
4390  SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars, nupgdconss) );
4391 
4392  /* remove all variables that are fixed to one; merge multiple entries of the same variable;
4393  * fix resultant to zero if a pair of negated variables is contained in the operand variables
4394  */
4395  if( !cutoff && !SCIPconsIsDeleted(cons) )
4396  {
4397  SCIP_CALL( applyFixings(scip, cons, conshdlrdata->eventhdlr, nchgcoefs) );
4398 
4399  /* merge multiple occurances of variables or variables with their negated variables */
4400  SCIP_CALL( mergeMultiples(scip, cons, conshdlrdata->eventhdlr, &entries, &nentries, nfixedvars, nchgcoefs, ndelconss) );
4401  }
4402 
4403  if( !cutoff && !SCIPconsIsDeleted(cons) && !SCIPconsIsModifiable(cons) )
4404  {
4405  assert(consdata->nvars >= 1); /* otherwise, propagateCons() has deleted the constraint */
4406 
4407  /* if only one variable is left, the resultant has to be equal to this single variable */
4408  if( consdata->nvars == 1 )
4409  {
4410  SCIP_Bool redundant;
4411  SCIP_Bool aggregated;
4412 
4413  SCIPdebugMessage("AND-constraint <%s> has only one variable not fixed to 1.0\n", SCIPconsGetName(cons));
4414 
4415  assert(consdata->vars != NULL);
4416  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(consdata->vars[0]), 0.0));
4417  assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(consdata->vars[0]), 1.0));
4418 
4419  /* aggregate variables: resultant - operand == 0 */
4420  SCIP_CALL( SCIPaggregateVars(scip, consdata->resvar, consdata->vars[0], 1.0, -1.0, 0.0,
4421  &cutoff, &redundant, &aggregated) );
4422  assert(redundant || SCIPdoNotAggr(scip));
4423 
4424  if( aggregated )
4425  {
4426  assert(redundant);
4427  (*naggrvars)++;
4428  }
4429 
4430  if( redundant )
4431  {
4432  /* delete constraint */
4433  SCIP_CALL( SCIPdelCons(scip, cons) );
4434  (*ndelconss)++;
4435  }
4436  }
4437  else if( !consdata->impladded )
4438  {
4439  int i;
4440 
4441  /* add implications: resultant == 1 -> all operands == 1 */
4442  for( i = 0; i < consdata->nvars && !cutoff; ++i )
4443  {
4444  int nimplbdchgs;
4445 
4446  SCIP_CALL( SCIPaddVarImplication(scip, consdata->resvar, TRUE, consdata->vars[i],
4447  SCIP_BOUNDTYPE_LOWER, 1.0, &cutoff, &nimplbdchgs) );
4448  (*nchgbds) += nimplbdchgs;
4449  }
4450  consdata->impladded = TRUE;
4451  }
4452 
4453  /* if in r = x and y, the resultant is fixed to zero, add implication x = 1 -> y = 0 */
4454  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 2 && !consdata->opimpladded
4455  && SCIPvarGetUbGlobal(consdata->resvar) < 0.5 )
4456  {
4457  int nimplbdchgs;
4458 
4459  SCIP_CALL( SCIPaddVarImplication(scip, consdata->vars[0], TRUE, consdata->vars[1],
4460  SCIP_BOUNDTYPE_UPPER, 0.0, &cutoff, &nimplbdchgs) );
4461  (*nchgbds) += nimplbdchgs;
4462  consdata->opimpladded = TRUE;
4463  }
4464  }
4465  }
4466 
4467  /* perform dual presolving on AND-constraints */
4468  if( conshdlrdata->dualpresolving && !cutoff && !SCIPisStopped(scip) && SCIPallowDualReds(scip))
4469  {
4470  SCIP_CALL( dualPresolve(scip, conss, nconss, conshdlrdata->eventhdlr, &entries, &nentries, &cutoff, nfixedvars, naggrvars, nchgcoefs, ndelconss, nupgdconss, naddconss) );
4471  }
4472 
4473  /* check for cliques inside the AND constraint */
4474  if( (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4475  {
4476  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
4477  {
4478  if( SCIPconsIsActive(conss[c]) )
4479  {
4480  /* check if at least two operands are in one clique */
4481  SCIP_CALL( cliquePresolve(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, nfixedvars, naggrvars, nchgcoefs, ndelconss, naddconss) );
4482  }
4483  }
4484  }
4485 
4486  /* process pairs of constraints: check them for equal operands in order to aggregate resultants;
4487  * only apply this expensive procedure, if the single constraint preprocessing did not find any reductions
4488  * (otherwise, we delay the presolving to be called again next time)
4489  */
4490  if( !cutoff && conshdlrdata->presolusehashing && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4491  {
4492  if( *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars )
4493  {
4494  if( firstchange < nconss )
4495  {
4496  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
4497  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff, naggrvars, ndelconss) );
4498  oldnaggrvars = *naggrvars;
4499  }
4500  }
4501  }
4502 
4503  if( !cutoff && conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
4504  {
4505  if( *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars )
4506  {
4507  SCIP_Longint npaircomparisons;
4508  npaircomparisons = 0;
4509  oldndelconss = *ndelconss;
4510 
4511  for( c = firstchange; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
4512  {
4513  if( SCIPconsIsActive(conss[c]) && !SCIPconsIsModifiable(conss[c]) )
4514  {
4515  npaircomparisons += ((SCIPconsGetData(conss[c])->changed) ? (SCIP_Longint) c : ((SCIP_Longint) c - (SCIP_Longint) firstchange));
4516 
4517  SCIP_CALL( preprocessConstraintPairs(scip, conss, firstchange, c, &cutoff, naggrvars, nchgbds,
4518  ndelconss) );
4519 
4520  if( npaircomparisons > NMINCOMPARISONS )
4521  {
4522  if( ((*ndelconss - oldndelconss) + (*naggrvars - oldnaggrvars) + (*nchgbds - oldnchgbds)/2.0) / ((SCIP_Real) npaircomparisons) < MINGAINPERNMINCOMPARISONS )
4523  break;
4524  oldndelconss = *ndelconss;
4525  oldnaggrvars = *naggrvars;
4526  oldnchgbds = *nchgbds;
4527 
4528  npaircomparisons = 0;
4529  }
4530  }
4531  }
4532  }
4533  }
4534 
4535  SCIPfreeBufferArray(scip, &entries);
4536 
4537  /* return the correct result code */
4538  if( cutoff )
4539  *result = SCIP_CUTOFF;
4540  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds
4541  || *ndelconss > oldndelconss || *nupgdconss > oldnupgdconss )
4542  *result = SCIP_SUCCESS;
4543  else
4544  *result = SCIP_DIDNOTFIND;
4545 
4546  return SCIP_OKAY;
4547 }
4548 
4549 
4550 /** propagation conflict resolving method of constraint handler */
4551 static
4552 SCIP_DECL_CONSRESPROP(consRespropAnd)
4553 { /*lint --e{715}*/
4554  SCIP_CALL( resolvePropagation(scip, cons, infervar, (PROPRULE)inferinfo, bdchgidx, result) );
4555 
4556  return SCIP_OKAY;
4557 }
4558 
4559 
4560 /** variable rounding lock method of constraint handler */
4561 static
4562 SCIP_DECL_CONSLOCK(consLockAnd)
4563 { /*lint --e{715}*/
4564  SCIP_CONSDATA* consdata;
4565  int i;
4566 
4567  consdata = SCIPconsGetData(cons);
4568  assert(consdata != NULL);
4569 
4570  /* resultant variable */
4571  SCIP_CALL( SCIPaddVarLocks(scip, consdata->resvar, nlockspos + nlocksneg, nlockspos + nlocksneg) );
4572 
4573  /* operand variables */
4574  for( i = 0; i < consdata->nvars; ++i )
4575  {
4576  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos + nlocksneg, nlockspos + nlocksneg) );
4577  }
4578 
4579  return SCIP_OKAY;
4580 }
4581 
4582 
4583 /** constraint display method of constraint handler */
4584 static
4585 SCIP_DECL_CONSPRINT(consPrintAnd)
4586 { /*lint --e{715}*/
4587 
4588  assert( scip != NULL );
4589  assert( conshdlr != NULL );
4590  assert( cons != NULL );
4591 
4592  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
4593 
4594  return SCIP_OKAY;
4595 }
4596 
4597 /** constraint copying method of constraint handler */
4598 static
4599 SCIP_DECL_CONSCOPY(consCopyAnd)
4600 { /*lint --e{715}*/
4601  SCIP_VAR** sourcevars;
4602  SCIP_VAR** vars;
4603  SCIP_VAR* sourceresvar;
4604  SCIP_VAR* resvar;
4605  const char* consname;
4606  int nvars;
4607  int v;
4608 
4609  assert(valid != NULL);
4610  (*valid) = TRUE;
4611 
4612  sourceresvar = SCIPgetResultantAnd(sourcescip, sourcecons);
4613 
4614  /* map resultant to active variable of the target SCIP */
4615  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourceresvar, &resvar, varmap, consmap, global, valid) );
4616  assert(!(*valid) || resvar != NULL);
4617 
4618  /* we do not copy, if a variable is missing */
4619  if( !(*valid) )
4620  return SCIP_OKAY;
4621 
4622  /* map operand variables to active variables of the target SCIP */
4623  sourcevars = SCIPgetVarsAnd(sourcescip, sourcecons);
4624  nvars = SCIPgetNVarsAnd(sourcescip, sourcecons);
4625 
4626  /* allocate buffer array */
4627  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
4628 
4629  for( v = 0; v < nvars; ++v )
4630  {
4631  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &vars[v], varmap, consmap, global, valid) );
4632  assert(!(*valid) || vars[v] != NULL);
4633 
4634  /* we do not copy, if a variable is missing */
4635  if( !(*valid) )
4636  goto TERMINATE;
4637  }
4638 
4639  if( name != NULL )
4640  consname = name;
4641  else
4642  consname = SCIPconsGetName(sourcecons);
4643 
4644  /* creates and captures a AND-constraint */
4645  SCIP_CALL( SCIPcreateConsAnd(scip, cons, consname, resvar, nvars, vars,
4646  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4647 
4648  TERMINATE:
4649  /* free buffer array */
4650  SCIPfreeBufferArray(scip, &vars);
4651 
4652  return SCIP_OKAY;
4653 }
4654 
4655 /** constraint parsing method of constraint handler */
4656 static
4657 SCIP_DECL_CONSPARSE(consParseAnd)
4658 { /*lint --e{715}*/
4659  SCIP_VAR** vars;
4660  SCIP_VAR* resvar;
4661  char* endptr;
4662  int requiredsize;
4663  int varssize;
4664  int nvars;
4665 
4666  SCIPdebugMessage("parse <%s> as AND-constraint\n", str);
4667 
4668  *success = FALSE;
4669 
4670  /* parse variable name of resultant */
4671  SCIP_CALL( SCIPparseVarName(scip, str, &resvar, &endptr) );
4672  str = endptr;
4673 
4674  if( resvar == NULL )
4675  {
4676  SCIPdebugMessage("resultant variable does not exist \n");
4677  }
4678  else
4679  {
4680  char* strcopy = NULL;
4681  char* startptr;
4682 
4683  /* cutoff "== and(" form the constraint string */
4684  startptr = strchr((char*)str, '(');
4685 
4686  if( startptr == NULL )
4687  {
4688  SCIPerrorMessage("missing starting character '(' parsing AND-constraint\n");
4689  return SCIP_OKAY;
4690  }
4691 
4692  /* skip '(' */
4693  ++startptr;
4694 
4695  /* find end character ')' */
4696  endptr = strrchr(startptr, ')');
4697 
4698  if( endptr == NULL )
4699  {
4700  SCIPerrorMessage("missing ending character ')' parsing AND-constraint\n");
4701  return SCIP_OKAY;
4702  }
4703  assert(endptr >= startptr);
4704 
4705  if( endptr > startptr )
4706  {
4707  /* copy string for parsing */
4708  SCIP_CALL( SCIPduplicateBufferArray(scip, &strcopy, startptr, (int)(endptr-startptr)) );
4709 
4710  varssize = 100;
4711  nvars = 0;
4712 
4713  /* allocate buffer array for variables */
4714  SCIP_CALL( SCIPallocBufferArray(scip, &vars, varssize) );
4715 
4716  /* parse string */
4717  SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
4718 
4719  if( *success )
4720  {
4721  /* check if the size of the variable array was great enough */
4722  if( varssize < requiredsize )
4723  {
4724  /* reallocate memory */
4725  varssize = requiredsize;
4726  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, varssize) );
4727 
4728  /* parse string again with the correct size of the variable array */
4729  SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
4730  }
4731 
4732  assert(*success);
4733  assert(varssize >= requiredsize);
4734 
4735  /* create AND-constraint */
4736  SCIP_CALL( SCIPcreateConsAnd(scip, cons, name, resvar, nvars, vars,
4737  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4738  }
4739 
4740  /* free variable buffer */
4741  SCIPfreeBufferArray(scip, &vars);
4742  SCIPfreeBufferArray(scip, &strcopy);
4743  }
4744  else
4745  {
4746  if( !modifiable )
4747  {
4748  SCIPerrorMessage("cannot create empty AND-constraint\n");
4749  return SCIP_OKAY;
4750  }
4751 
4752  /* create empty AND-constraint */
4753  SCIP_CALL( SCIPcreateConsAnd(scip, cons, name, resvar, 0, NULL,
4754  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4755 
4756  *success = TRUE;
4757  }
4758  }
4759 
4760  return SCIP_OKAY;
4761 }
4762 
4763 /** constraint method of constraint handler which returns the variables (if possible) */
4764 static
4765 SCIP_DECL_CONSGETVARS(consGetVarsAnd)
4766 { /*lint --e{715}*/
4767  SCIP_CONSDATA* consdata;
4768 
4769  consdata = SCIPconsGetData(cons);
4770  assert(consdata != NULL);
4771 
4772  if( varssize < consdata->nvars + 1 )
4773  (*success) = FALSE;
4774  else
4775  {
4776  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
4777  vars[consdata->nvars] = consdata->resvar;
4778  (*success) = TRUE;
4779  }
4780 
4781  return SCIP_OKAY;
4782 }
4783 
4784 /** constraint method of constraint handler which returns the number of variable (if possible) */
4785 static
4786 SCIP_DECL_CONSGETNVARS(consGetNVarsAnd)
4787 { /*lint --e{715}*/
4788  SCIP_CONSDATA* consdata;
4789 
4790  assert(cons != NULL);
4791 
4792  consdata = SCIPconsGetData(cons);
4793  assert(consdata != NULL);
4794 
4795  (*nvars) = consdata->nvars + 1;
4796  (*success) = TRUE;
4797 
4798  return SCIP_OKAY;
4799 }
4800 
4801 
4802 /*
4803  * Callback methods of event handler
4804  */
4805 
4806 static
4807 SCIP_DECL_EVENTEXEC(eventExecAnd)
4808 { /*lint --e{715}*/
4809  SCIP_CONSDATA* consdata;
4810 
4811  assert(eventhdlr != NULL);
4812  assert(eventdata != NULL);
4813  assert(event != NULL);
4814 
4815  consdata = (SCIP_CONSDATA*)eventdata;
4816  assert(consdata != NULL);
4817 
4818  /* check, if the variable was fixed to zero */
4820  consdata->nofixedzero = FALSE;
4821 
4822  consdata->propagated = FALSE;
4823 
4824  return SCIP_OKAY;
4825 }
4826 
4827 
4828 /*
4829  * constraint specific interface methods
4830  */
4831 
4832 /** creates the handler for AND-constraints and includes it in SCIP */
4834  SCIP* scip /**< SCIP data structure */
4835  )
4836 {
4837  SCIP_CONSHDLRDATA* conshdlrdata;
4838  SCIP_CONSHDLR* conshdlr;
4839  SCIP_EVENTHDLR* eventhdlr;
4840 
4841  /* create event handler for events on variables */
4843  eventExecAnd, NULL) );
4844 
4845  /* create constraint handler data */
4846  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
4847 
4848  /* include constraint handler */
4851  consEnfolpAnd, consEnfopsAnd, consCheckAnd, consLockAnd,
4852  conshdlrdata) );
4853 
4854  assert(conshdlr != NULL);
4855 
4856  /* set non-fundamental callbacks via specific setter functions */
4857  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyAnd, consCopyAnd) );
4858  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteAnd) );
4859 #ifdef GMLGATEPRINTING
4860  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreAnd) );
4861 #endif
4862  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolAnd) );
4863  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeAnd) );
4864  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsAnd) );
4865  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsAnd) );
4866  SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreAnd) );
4867  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpAnd) );
4868  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseAnd) );
4869  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolAnd, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
4870  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintAnd) );
4871  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropAnd, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
4873  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropAnd) );
4874  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpAnd, consSepasolAnd, CONSHDLR_SEPAFREQ,
4876  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransAnd) );
4877 
4878  /* add AND-constraint handler parameters */
4880  "constraints/" CONSHDLR_NAME "/presolpairwise",
4881  "should pairwise constraint comparison be performed in presolving?",
4882  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
4884  "constraints/and/presolusehashing",
4885  "should hash table be used for detecting redundant constraints in advance",
4886  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
4888  "constraints/" CONSHDLR_NAME "/linearize",
4889  "should the AND-constraint get linearized and removed (in presolving)?",
4890  &conshdlrdata->linearize, TRUE, DEFAULT_LINEARIZE, NULL, NULL) );
4892  "constraints/" CONSHDLR_NAME "/enforcecuts",
4893  "should cuts be separated during LP enforcing?",
4894  &conshdlrdata->enforcecuts, TRUE, DEFAULT_ENFORCECUTS, NULL, NULL) );
4896  "constraints/" CONSHDLR_NAME "/aggrlinearization",
4897  "should an aggregated linearization be used?",
4898  &conshdlrdata->aggrlinearization, TRUE, DEFAULT_AGGRLINEARIZATION, NULL, NULL) );
4900  "constraints/" CONSHDLR_NAME "/upgraderesultant",
4901  "should all binary resultant variables be upgraded to implicit binary variables?",
4902  &conshdlrdata->upgrresultant, TRUE, DEFAULT_UPGRRESULTANT, NULL, NULL) );
4904  "constraints/" CONSHDLR_NAME "/dualpresolving",
4905  "should dual presolving be performed?",
4906  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
4907 
4908  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
4909  {
4910  /* include the AND-constraint upgrade in the nonlinear constraint handler */
4912  }
4913 
4914  return SCIP_OKAY;
4915 }
4916 
4917 /** creates and captures a AND-constraint
4918  *
4919  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
4920  */
4922  SCIP* scip, /**< SCIP data structure */
4923  SCIP_CONS** cons, /**< pointer to hold the created constraint */
4924  const char* name, /**< name of constraint */
4925  SCIP_VAR* resvar, /**< resultant variable of the operation */
4926  int nvars, /**< number of operator variables in the constraint */
4927  SCIP_VAR** vars, /**< array with operator variables of constraint */
4928  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
4929  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
4930  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
4931  * Usually set to TRUE. */
4932  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
4933  * TRUE for model constraints, FALSE for additional, redundant constraints. */
4934  SCIP_Bool check, /**< should the constraint be checked for feasibility?
4935  * TRUE for model constraints, FALSE for additional, redundant constraints. */
4936  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
4937  * Usually set to TRUE. */
4938  SCIP_Bool local, /**< is constraint only valid locally?
4939  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
4940  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
4941  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
4942  * adds coefficients to this constraint. */
4943  SCIP_Bool dynamic, /**< is constraint subject to aging?
4944  * Usually set to FALSE. Set to TRUE for own cuts which
4945  * are separated as constraints. */
4946  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
4947  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
4948  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
4949  * if it may be moved to a more global node?
4950  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
4951  )
4952 {
4953  SCIP_CONSHDLR* conshdlr;
4954  SCIP_CONSHDLRDATA* conshdlrdata;
4955  SCIP_CONSDATA* consdata;
4956  SCIP_Bool infeasible;
4957 
4958  /* find the AND-constraint handler */
4959  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
4960  if( conshdlr == NULL )
4961  {
4962  SCIPerrorMessage("AND-constraint handler not found\n");
4963  return SCIP_PLUGINNOTFOUND;
4964  }
4965 
4966  conshdlrdata = SCIPconshdlrGetData(conshdlr);
4967  assert(conshdlrdata != NULL);
4968 
4969  /* upgrade binary resultant variable to an implicit binary variable */
4970  /* @todo add implicit upgrade in presolving, improve decision making for upgrade by creating an implication graph */
4971  if( conshdlrdata->upgrresultant && SCIPvarGetType(resvar) == SCIP_VARTYPE_BINARY
4972 #if 1 /* todo delete following hack,
4973  * the following avoids upgrading not artificial variables, for example and-resultants which are generated
4974  * from the gate presolver, it seems better to not upgrade these variables
4975  */
4976  && strlen(SCIPvarGetName(resvar)) > strlen(ARTIFICIALVARNAMEPREFIX) && strncmp(SCIPvarGetName(resvar), ARTIFICIALVARNAMEPREFIX, strlen(ARTIFICIALVARNAMEPREFIX)) == 0 )
4977 #else
4978  )
4979 #endif
4980  {
4981  SCIP_VAR* activeresvar;
4982  SCIP_VAR* activevar;
4983  int v;
4984 
4985  if( SCIPisTransformed(scip) )
4986  activeresvar = SCIPvarGetProbvar(resvar);
4987  else
4988  activeresvar = resvar;
4989 
4990  if( SCIPvarGetType(activeresvar) == SCIP_VARTYPE_BINARY )
4991  {
4992  /* check if we can upgrade the variable type of the resultant */
4993  for( v = nvars - 1; v >= 0; --v )
4994  {
4995  if( SCIPisTransformed(scip) )
4996  activevar = SCIPvarGetProbvar(vars[v]);
4997  else
4998  activevar = vars[v];
4999 
5000  if( activevar == activeresvar || SCIPvarGetType(activevar) == SCIP_VARTYPE_IMPLINT )
5001  break;
5002  }
5003 
5004  /* upgrade the type of the resultant */
5005  if( v < 0 )
5006  {
5007  SCIP_CALL( SCIPchgVarType(scip, resvar, SCIP_VARTYPE_IMPLINT, &infeasible) );
5008  assert(!infeasible);
5009  }
5010  }
5011  }
5012 
5013  /* create constraint data */
5014  SCIP_CALL( consdataCreate(scip, &consdata, conshdlrdata->eventhdlr, nvars, vars, resvar, FALSE, FALSE) );
5015 
5016  /* create constraint */
5017  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
5018  local, modifiable, dynamic, removable, stickingatnode) );
5019 
5020  return SCIP_OKAY;
5021 }
5022 
5023 /** creates and captures an AND-constraint
5024  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
5025  * method SCIPcreateConsAnd(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
5026  *
5027  * @see SCIPcreateConsAnd() for information about the basic constraint flag configuration
5028  *
5029  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5030  */
5032  SCIP* scip, /**< SCIP data structure */
5033  SCIP_CONS** cons, /**< pointer to hold the created constraint */
5034  const char* name, /**< name of constraint */
5035  SCIP_VAR* resvar, /**< resultant variable of the operation */
5036  int nvars, /**< number of operator variables in the constraint */
5037  SCIP_VAR** vars /**< array with operator variables of constraint */
5038  )
5039 {
5040  assert(scip != NULL);
5041 
5042  SCIP_CALL( SCIPcreateConsAnd(scip, cons, name, resvar, nvars, vars,
5043  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
5044 
5045  return SCIP_OKAY;
5046 }
5047 
5048 
5049 /** gets number of variables in AND-constraint */
5050 int SCIPgetNVarsAnd(
5051  SCIP* scip, /**< SCIP data structure */
5052  SCIP_CONS* cons /**< constraint data */
5053  )
5054 {
5055  SCIP_CONSDATA* consdata;
5056 
5057  assert(scip != NULL);
5058  assert(cons != NULL);
5059 
5060  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5061  {
5062  SCIPerrorMessage("constraint is not an AND-constraint\n");
5063  SCIPABORT();
5064  return -1; /*lint !e527*/
5065  }
5066 
5067  consdata = SCIPconsGetData(cons);
5068  assert(consdata != NULL);
5069 
5070  return consdata->nvars;
5071 }
5072 
5073 /** gets array of variables in AND-constraint */
5075  SCIP* scip, /**< SCIP data structure */
5076  SCIP_CONS* cons /**< constraint data */
5077  )
5078 {
5079  SCIP_CONSDATA* consdata;
5080 
5081  assert(scip != NULL);
5082  assert(cons != NULL);
5083 
5084  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5085  {
5086  SCIPerrorMessage("constraint is not an AND-constraint\n");
5087  SCIPABORT();
5088  return NULL; /*lint !e527*/
5089  }
5090 
5091  consdata = SCIPconsGetData(cons);
5092  assert(consdata != NULL);
5093 
5094  return consdata->vars;
5095 }
5096 
5097 
5098 /** gets the resultant variable in AND-constraint */
5100  SCIP* scip, /**< SCIP data structure */
5101  SCIP_CONS* cons /**< constraint data */
5102  )
5103 {
5104  SCIP_CONSDATA* consdata;
5105 
5106  assert(cons != NULL);
5107 
5108  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5109  {
5110  SCIPerrorMessage("constraint is not an AND-constraint\n");
5111  SCIPABORT();
5112  return NULL; /*lint !e527*/
5113  }
5114 
5115  consdata = SCIPconsGetData(cons);
5116  assert(consdata != NULL);
5117 
5118  return consdata->resvar;
5119 }
5120 
5121 /** return if the variables of the AND-constraint are sorted due to their indices */
5123  SCIP* scip, /**< SCIP data structure */
5124  SCIP_CONS* cons /**< constraint data */
5125  )
5126 {
5127  SCIP_CONSDATA* consdata;
5128 
5129  assert(scip != NULL);
5130  assert(cons != NULL);
5131 
5132  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5133  {
5134  SCIPerrorMessage("constraint is not an AND-constraint\n");
5135  SCIPABORT();
5136  return FALSE; /*lint !e527*/
5137  }
5138 
5139  consdata = SCIPconsGetData(cons);
5140  assert(consdata != NULL);
5141 
5142  return consdata->sorted;
5143 }
5144 
5145 /** sort the variables of the AND-constraint due to their indices */
5147  SCIP* scip, /**< SCIP data structure */
5148  SCIP_CONS* cons /**< constraint data */
5149  )
5150 {
5151  SCIP_CONSDATA* consdata;
5152 
5153  assert(scip != NULL);
5154  assert(cons != NULL);
5155 
5156  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5157  {
5158  SCIPerrorMessage("constraint is not an AND-constraint\n");
5159  SCIPABORT();
5160  return SCIP_INVALIDDATA; /*lint !e527*/
5161  }
5162 
5163  consdata = SCIPconsGetData(cons);
5164  assert(consdata != NULL);
5165 
5166  consdataSort(consdata);
5167  assert(consdata->sorted);
5168 
5169  return SCIP_OKAY;
5170 }
5171 
5172 /** when 'upgrading' the given AND-constraint, should the check flag for the upgraded constraint be set to TRUE, even if
5173  * the check flag of this AND-constraint is set to FALSE?
5174  */
5176  SCIP* scip, /**< SCIP data structure */
5177  SCIP_CONS* cons, /**< constraint data */
5178  SCIP_Bool flag /**< should an arising constraint from the given AND-constraint be checked,
5179  * even if the check flag of the AND-constraint is set to FALSE
5180  */
5181  )
5182 {
5183  SCIP_CONSDATA* consdata;
5184 
5185  assert(scip != NULL);
5186  assert(cons != NULL);
5187 
5188  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5189  {
5190  SCIPerrorMessage("constraint is not an AND-constraint\n");
5191  SCIPABORT();
5192  return SCIP_INVALIDDATA; /*lint !e527*/
5193  }
5194 
5195  consdata = SCIPconsGetData(cons);
5196  assert(consdata != NULL);
5197 
5198  consdata->checkwhenupgr = flag;
5199 
5200  return SCIP_OKAY;
5201 }
5202 
5203 /** when 'upgrading' the given AND-constraint, should the removable flag for the upgraded constraint be set to FALSE,
5204  * even if the removable flag of this AND-constraint is set to TRUE?
5205  */
5207  SCIP* scip, /**< SCIP data structure */
5208  SCIP_CONS* cons, /**< constraint data */
5209  SCIP_Bool flag /**< should an arising constraint from the given AND-constraint be not
5210  * removable, even if the removable flag of the AND-constraint is set to
5211  * TRUE
5212  */
5213  )
5214 {
5215  SCIP_CONSDATA* consdata;
5216 
5217  assert(scip != NULL);
5218  assert(cons != NULL);
5219 
5220  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
5221  {
5222  SCIPerrorMessage("constraint is not an AND-constraint\n");
5223  SCIPABORT();
5224  return SCIP_INVALIDDATA; /*lint !e527*/
5225  }
5226 
5227  consdata = SCIPconsGetData(cons);
5228  assert(consdata != NULL);
5229 
5230  consdata->notremovablewhenupgr = flag;
5231 
5232  return SCIP_OKAY;
5233 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:22777
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41572
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_and.c:181
static SCIP_RETCODE consdataFixResultantZero(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *resvar, int pos, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_and.c:1220
SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
Definition: scip.c:27932
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip.c:15853
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, PROPRULE proprule, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
Definition: cons_and.c:1847
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:28308
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5878
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:5588
#define ARTIFICIALVARNAMEPREFIX
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:25588
static SCIP_DECL_CONSSEPASOL(consSepasolAnd)
Definition: cons_and.c:4172
SCIP_RETCODE SCIPexprgraphAddNode(SCIP_EXPRGRAPH *exprgraph, SCIP_EXPRGRAPHNODE *node, int mindepth, int nchildren, SCIP_EXPRGRAPHNODE **children)
Definition: expr.c:14923
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
static SCIP_RETCODE cliquePresolve(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *nchgcoefs, int *ndelconss, int *naddconss)
Definition: cons_and.c:2568
SCIP_RETCODE SCIPexprgraphAddVars(SCIP_EXPRGRAPH *exprgraph, int nvars, void **vars, SCIP_EXPRGRAPHNODE **varnodes)
Definition: expr.c:15007
#define CONSHDLR_SEPAPRIORITY
Definition: cons_and.c:51
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip.c:22886
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11461
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:20589
static SCIP_DECL_EVENTEXEC(eventExecAnd)
Definition: cons_and.c:4808
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1567
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:20573
SCIP_RETCODE SCIPcreateConsSetpart(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_setppc.c:8890
int SCIPexprgraphGetNodeNChildren(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12733
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:10378
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11540
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16623
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:15737
#define SCIP_MAXSTRLEN
Definition: def.h:201
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:5634
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, int *nfixedvars, int *nchgcoefs, int *ndelconss)
Definition: cons_and.c:1485
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:5246
void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:437
static SCIP_RETCODE analyzeConflictZero(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:1185
#define NULL
Definition: lpi_spx.cpp:130
static SCIP_RETCODE consdataSwitchWatchedvars(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int watchedvar1, int watchedvar2)
Definition: cons_and.c:315
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:7849
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:7681
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:5334
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
static SCIP_DECL_HASHKEYEQ(hashKeyEqAndcons)
Definition: cons_and.c:3225
void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:295
static SCIP_DECL_CONSPARSE(consParseAnd)
Definition: cons_and.c:4658
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:16927
#define SCIPfreeMemoryArray(scip, ptr)
Definition: scip.h:20544
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:24320
void SCIPgmlWriteClosing(FILE *file)
Definition: misc.c:497
static SCIP_RETCODE consdataFixOperandsOne(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_and.c:1259
static SCIP_RETCODE consdataFreeRows(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_and.c:482
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:5818
SCIP_RETCODE SCIPwriteVarsList(SCIP *scip, FILE *file, SCIP_VAR **vars, int nvars, SCIP_Bool type, char delimiter)
Definition: scip.c:15915
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_and.c:78
SCIP_RETCODE SCIPcreateConsSetpack(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_setppc.c:8948
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:7909
#define FALSE
Definition: def.h:56
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2057
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:10743
#define CONSHDLR_CHECKPRIORITY
Definition: cons_and.c:53
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:7778
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define TRUE
Definition: def.h:55
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7640
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
enum Proprule PROPRULE
static SCIP_DECL_CONSPROP(consPropAnd)
Definition: cons_and.c:4307
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:45
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:5795
#define SCIP_CALL(x)
Definition: def.h:266
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_and.c:558
SCIP_RETCODE SCIPgetBinvarRepresentatives(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **repvars, SCIP_Bool *negated)
Definition: scip.c:17280
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip.c:23083
#define CONSHDLR_NAME
Definition: cons_and.c:49
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:42008
static SCIP_RETCODE consdataLinearize(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nupgdconss)
Definition: cons_and.c:1313
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:20556
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15737
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34983
#define HASHTABLESIZE_FACTOR
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
Constraint handler for "and" constraints, .
static SCIP_DECL_CONSINITPRE(consInitpreAnd)
Definition: cons_and.c:3782
#define DEFAULT_ENFORCECUTS
Definition: cons_and.c:72
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_and.c:167
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2116
SCIP_RETCODE SCIPsortAndCons(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5147
SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
Definition: scip.c:37116
static SCIP_DECL_CONSPRINT(consPrintAnd)
Definition: cons_and.c:4586
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:10878
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:7839
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:7779
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:26237
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:30967
Constraint handler for the set partitioning / packing / covering constraints .
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24949
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_and.c:375
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:99
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:20554
static SCIP_RETCODE consdataDropWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int filterpos)
Definition: cons_and.c:240
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11206
static SCIP_DECL_CONSEXITSOL(consExitsolAnd)
Definition: cons_and.c:4064
#define EVENTHDLR_DESC
Definition: cons_and.c:68
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_and.c:70
int SCIPexprgraphGetNodePolynomialNMonomials(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12956
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:5359
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:7769
SCIP_RETCODE SCIPincludeConshdlrAnd(SCIP *scip)
Definition: cons_and.c:4834
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:1480
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:24720
#define SCIP_REAL_FORMAT
Definition: def.h:130
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_EVENTHDLR *eventhdlr, unsigned char **entries, int *nentries, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *nchgcoefs, int *ndelconss, int *nupgdconss, int *naddconss)
Definition: cons_and.c:1933
static SCIP_DECL_CONSENFOPS(consEnfopsAnd)
Definition: cons_and.c:4261
int SCIPexprGetMonomialNFactors(SCIP_EXPRDATA_MONOMIAL *monomial)
Definition: expr.c:5790
SCIP_RETCODE SCIPparseVarsList(SCIP *scip, const char *str, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize, char **endptr, char delimiter, SCIP_Bool *success)
Definition: scip.c:16233
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3547
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip.c:16156
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:56
SCIP_EXPROP SCIPexprgraphGetNodeOperator(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12793
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3917
SCIP_EXPRDATA_MONOMIAL ** SCIPexprgraphGetNodePolynomialMonomials(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12944
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:36622
static SCIP_DECL_CONSFREE(consFreeAnd)
Definition: cons_and.c:3764
#define EVENTHDLR_NAME
Definition: cons_and.c:67
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition: scip.c:17233
static SCIP_DECL_CONSPRESOL(consPresolAnd)
Definition: cons_and.c:4342
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip)
Definition: scip.c:24342
SCIP_RETCODE SCIPincludeNonlinconsUpgrade(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nonlinconsupgd)), SCIP_DECL_EXPRGRAPHNODEREFORM((*nodereform)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41585
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16585
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:25560
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1781
SCIP_RETCODE SCIPchgAndConsCheckFlagWhenUpgr(SCIP *scip, SCIP_CONS *cons, SCIP_Bool flag)
Definition: cons_and.c:5176
SCIP_VAR ** SCIPgetVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5075
SCIP_Real SCIPexprgraphGetNodePolynomialConstant(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12968
#define CONSHDLR_PRESOLTIMING
Definition: cons_and.c:64
SCIP_NODE * SCIPgetRootNode(SCIP *scip)
Definition: scip.c:36798
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41709
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:17075
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:7879
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_and.c:3298
#define SCIPerrorMessage
Definition: pub_message.h:45
#define SCIPdebugPrintf
Definition: pub_message.h:80
#define CONSHDLR_PROP_TIMING
Definition: cons_and.c:65
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:19526
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip.c:25300
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Bool *cutoff, int *naggrvars, int *nbdchgs, int *ndelconss)
Definition: cons_and.c:3419
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_and.c:643
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41996
Constraint handler for logicor constraints (equivalent to set covering, but algorithms are suited fo...
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3897
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:1157
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15859
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip.c:23050
static SCIP_DECL_CONSDELETE(consDeleteAnd)
Definition: cons_and.c:4084
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41598
SCIP_RETCODE SCIPgetNegatedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **negvar)
Definition: scip.c:17163
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:5527
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:41353
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7620
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool printreason, SCIP_Bool *violated)
Definition: cons_and.c:992
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41907
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16598
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:19126
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
SCIP_RETCODE SCIPinferBinvarCons(SCIP *scip, SCIP_VAR *var, SCIP_Bool fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20669
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2075
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip.c:5503
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:20562
static SCIP_DECL_CONSTRANS(consTransAnd)
Definition: cons_and.c:4099
SCIP_VAR * SCIPgetResultantAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5100
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11573
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:58
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3204
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
SCIP_RETCODE SCIPexprgraphCreateNodeLinear(BMS_BLKMEM *blkmem, SCIP_EXPRGRAPHNODE **node, int ncoefs, SCIP_Real *coefs, SCIP_Real constant)
Definition: expr.c:13198
#define DEFAULT_LINEARIZE
Definition: cons_and.c:71
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5292
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:55
enum Proprule PROPRULE
Definition: cons_and.c:144
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:5192
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10742
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, int *nfixedvars, int *nupgdconss)
Definition: cons_and.c:1642
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:32131
#define EXPRGRAPHREFORM_PRIORITY
Definition: cons_and.c:81
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:264
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7650
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:16884
SCIP_RETCODE SCIPaddVarImplication(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:21682
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12080
static SCIP_DECL_CONSINITLP(consInitlpAnd)
Definition: cons_and.c:4129
static SCIP_RETCODE conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_and.c:201
static SCIP_DECL_CONSGETVARS(consGetVarsAnd)
Definition: cons_and.c:4766
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:17116
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_and.c:513
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41611
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:16873
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:23119
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip.c:22681
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:16850
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:997
public data structures and miscellaneous methods
SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
Definition: scip.c:5479
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:24772
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16740
#define SCIP_Bool
Definition: def.h:53
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, SCIP_VAR *var)
Definition: cons_and.c:583
#define CONSHDLR_NEEDSCONS
Definition: cons_and.c:62
static SCIP_DECL_CONSCOPY(consCopyAnd)
Definition: cons_and.c:4600
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:801
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_EVENTHDLR *eventhdlr, int nvars, SCIP_VAR **vars, SCIP_VAR *resvar, SCIP_Bool checkwhenupgr, SCIP_Bool notremovablewhenupgr)
Definition: cons_and.c:399
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:7859
constraint handler for nonlinear constraints
#define SCIP_DECL_CONSEXITPRE(x)
Definition: type_cons.h:138
#define MAX(x, y)
Definition: tclique_def.h:75
#define NMINCOMPARISONS
Definition: cons_and.c:79
static SCIP_DECL_HASHGETKEY(hashGetKeyAndcons)
Definition: cons_and.c:3217
methods for debugging
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:7869
SCIP_Bool SCIPconsIsAdded(SCIP_CONS *cons)
Definition: cons.c:7969
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:7739
#define HASHSIZE_ANDCONS
Definition: cons_and.c:77
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_and.c:153
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyAnd)
Definition: cons_and.c:3748
#define CONSHDLR_MAXPREROUNDS
Definition: cons_and.c:59
#define DEFAULT_UPGRRESULTANT
Definition: cons_and.c:74
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:7630
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:5611
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
#define DEFAULT_DUALPRESOLVING
Definition: cons_and.c:75
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:57
Constraint handler for linear constraints in their most general form, .
SCIP_Bool SCIPisAndConsSorted(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5123
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:1627
SCIP_Real SCIPexprGetMonomialCoef(SCIP_EXPRDATA_MONOMIAL *monomial)
Definition: expr.c:5780
#define CONSHDLR_DELAYPROP
Definition: cons_and.c:61
Proprule
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
void * SCIPexprgraphGetNodeVar(SCIP_EXPRGRAPH *exprgraph, SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12825
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41624
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:1510
static SCIP_DECL_CONSENFOLP(consEnfolpAnd)
Definition: cons_and.c:4199
#define CONSHDLR_EAGERFREQ
Definition: cons_and.c:56
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:36668
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:5565
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11477
#define CONSHDLR_PROPFREQ
Definition: cons_and.c:55
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
static SCIP_RETCODE analyzeZeroResultant(SCIP *scip, SCIP_CONS *cons, int watchedvar1, int watchedvar2, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_and.c:1424
static SCIP_DECL_EXPRGRAPHNODEREFORM(exprgraphnodeReformAnd)
Definition: cons_and.c:3623
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:5772
static SCIP_RETCODE consdataCatchEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_and.c:263
static SCIP_DECL_CONSSEPALP(consSepalpAnd)
Definition: cons_and.c:4145
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1281
#define REALABS(x)
Definition: def.h:151
#define DEFAULT_AGGRLINEARIZATION
Definition: cons_and.c:73
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:10788
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:4922
static SCIP_RETCODE createRelaxation(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:887
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
#define MINGAINPERNMINCOMPARISONS
Definition: cons_and.c:80
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:20593
#define CONSHDLR_DELAYSEPA
Definition: cons_and.c:60
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:5455
static SCIP_RETCODE consdataCatchWatchedEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos, int *filterpos)
Definition: cons_and.c:216
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:934
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:19453
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
static SCIP_RETCODE consdataDropEvents(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_and.c:289
#define CONSHDLR_SEPAFREQ
Definition: cons_and.c:54
#define SCIP_Real
Definition: def.h:127
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:7799
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:27600
static SCIP_DECL_HASHKEYVAL(hashKeyValAndcons)
Definition: cons_and.c:3271
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:20568
SCIP_EXPRGRAPHNODE ** SCIPexprgraphGetNodeChildren(SCIP_EXPRGRAPHNODE *node)
Definition: expr.c:12743
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:27738
static void consdataSort(SCIP_CONSDATA *consdata)
Definition: cons_and.c:706
#define SCIP_Longint
Definition: def.h:112
static SCIP_DECL_CONSGETNVARS(consGetNVarsAnd)
Definition: cons_and.c:4787
SCIP_RETCODE SCIPcreateConsBasicAnd(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *resvar, int nvars, SCIP_VAR **vars)
Definition: cons_and.c:5032
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:917
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:20571
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:263
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:19399
static SCIP_DECL_CONSRESPROP(consRespropAnd)
Definition: cons_and.c:4553
constraint handler for pseudoboolean constraints
static SCIP_DECL_CONSCHECK(consCheckAnd)
Definition: cons_and.c:4284
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:10572
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16730
#define SCIPdebug(x)
Definition: pub_message.h:74
void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
Definition: misc.c:481
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:24573
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:41422
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2094
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:392
int SCIPgetNImplVars(SCIP *scip)
Definition: scip.c:10833
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41697
#define CONSHDLR_DESC
Definition: cons_and.c:50
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:5841
SCIP_RETCODE SCIPcreateConsLogicor(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11481
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:27864
#define SCIPABORT()
Definition: def.h:238
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:7789
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *separated, SCIP_Bool *cutoff)
Definition: cons_and.c:1105
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:7819
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:3927
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3149
#define CONSHDLR_ENFOPRIORITY
Definition: cons_and.c:52
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int *nchgcoefs)
Definition: cons_and.c:787
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip.c:36834
static SCIP_RETCODE analyzeConflictOne(SCIP *scip, SCIP_CONS *cons, int falsepos)
Definition: cons_and.c:1154
static SCIP_DECL_CONSLOCK(consLockAnd)
Definition: cons_and.c:4563
SCIP_RETCODE SCIPchgAndConsRemovableFlagWhenUpgr(SCIP *scip, SCIP_CONS *cons, SCIP_Bool flag)
Definition: cons_and.c:5207
int SCIPgetNVarsAnd(SCIP *scip, SCIP_CONS *cons)
Definition: cons_and.c:5051