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