1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SCIP; see the file LICENSE. If not visit scipopt.org.         */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file   cons_setppc.c
26   	 * @ingroup DEFPLUGINS_CONS
27   	 * @brief  Constraint handler for the set partitioning / packing / covering constraints \f$1^T x\ \{=, \le, \ge\}\ 1\f$.
28   	 * @author Tobias Achterberg
29   	 * @author Michael Winkler
30   	 */
31   	
32   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33   	
34   	#include "blockmemshell/memory.h"
35   	#include "scip/cons_nonlinear.h"
36   	#include "scip/cons_linear.h"
37   	#include "scip/cons_setppc.h"
38   	#include "scip/pub_conflict.h"
39   	#include "scip/pub_cons.h"
40   	#include "scip/pub_event.h"
41   	#include "scip/pub_lp.h"
42   	#include "scip/pub_message.h"
43   	#include "scip/pub_misc.h"
44   	#include "scip/pub_misc_sort.h"
45   	#include "scip/pub_var.h"
46   	#include "scip/scip_conflict.h"
47   	#include "scip/scip_cons.h"
48   	#include "scip/scip_cut.h"
49   	#include "scip/scip_event.h"
50   	#include "scip/scip_general.h"
51   	#include "scip/scip_lp.h"
52   	#include "scip/scip_mem.h"
53   	#include "scip/scip_message.h"
54   	#include "scip/scip_nlp.h"
55   	#include "scip/scip_numerics.h"
56   	#include "scip/scip_param.h"
57   	#include "scip/scip_prob.h"
58   	#include "scip/scip_probing.h"
59   	#include "scip/scip_randnumgen.h"
60   	#include "scip/scip_sol.h"
61   	#include "scip/scip_solvingstats.h"
62   	#include "scip/scip_var.h"
63   	#include "scip/symmetry_graph.h"
64   	#include "symmetry/struct_symmetry.h"
65   	#include <string.h>
66   	
67   	
68   	#define CONSHDLR_NAME          "setppc"
69   	#define CONSHDLR_DESC          "set partitioning / packing / covering constraints"
70   	#define CONSHDLR_SEPAPRIORITY   +700000 /**< priority of the constraint handler for separation */
71   	#define CONSHDLR_ENFOPRIORITY   -700000 /**< priority of the constraint handler for constraint enforcing */
72   	#define CONSHDLR_CHECKPRIORITY  -700000 /**< priority of the constraint handler for checking feasibility */
73   	#define CONSHDLR_SEPAFREQ             0 /**< frequency for separating cuts; zero means to separate only in the root node */
74   	#define CONSHDLR_PROPFREQ             1 /**< frequency for propagating domains; zero means only preprocessing propagation */
75   	#define CONSHDLR_EAGERFREQ          100 /**< frequency for using all instead of only the useful constraints in separation,
76   	                                              *   propagation and enforcement, -1 for no eager evaluations, 0 for first only */
77   	#define CONSHDLR_MAXPREROUNDS        -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
78   	#define CONSHDLR_DELAYSEPA        FALSE /**< should separation method be delayed, if other separators found cuts? */
79   	#define CONSHDLR_DELAYPROP        FALSE /**< should propagation method be delayed, if other propagators found reductions? */
80   	#define CONSHDLR_NEEDSCONS         TRUE /**< should the constraint handler be skipped, if no constraints are available? */
81   	
82   	#define CONSHDLR_PRESOLTIMING            SCIP_PRESOLTIMING_ALWAYS
83   	#define CONSHDLR_PROP_TIMING             SCIP_PROPTIMING_BEFORELP
84   	
85   	#define LINCONSUPGD_PRIORITY    +700000 /**< priority of the constraint handler for upgrading of linear constraints */
86   	#define NONLINCONSUPGD_PRIORITY +700000 /**< priority of the constraint handler for upgrading of nonlinear constraints */
87   	
88   	#define EVENTHDLR_NAME         "setppc"
89   	#define EVENTHDLR_DESC         "bound change event handler for set partitioning / packing / covering constraints"
90   	
91   	#define CONFLICTHDLR_NAME      "setppc"
92   	#define CONFLICTHDLR_DESC      "conflict handler creating set covering constraints"
93   	#define CONFLICTHDLR_PRIORITY  LINCONSUPGD_PRIORITY
94   	
95   	#define DEFAULT_PRESOLPAIRWISE     TRUE /**< should pairwise constraint comparison be performed in presolving? */
96   	
97   	#define HASHSIZE_SETPPCCONS         500 /**< minimal size of hash table in setppc constraint tables */
98   	#define DEFAULT_PRESOLUSEHASHING   TRUE /**< should hash table be used for detecting redundant constraints in advance */
99   	#define NMINCOMPARISONS          200000 /**< number for minimal pairwise presolving comparisons */
100  	#define MINGAINPERNMINCOMPARISONS 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
101  	
102  	#define DEFAULT_RANDSEED              3
103  	
104  	/*#define VARUSES*/  /* activate variable usage counting, that is necessary for LP and pseudo branching */
105  	/*#define BRANCHLP*/ /* BRANCHLP is only useful if the ENFOPRIORITY is set to a positive value */
106  	#ifdef BRANCHLP
107  	#define MINBRANCHWEIGHT             0.3 /**< minimum weight of both sets in binary set branching */
108  	#define MAXBRANCHWEIGHT             0.7 /**< maximum weight of both sets in binary set branching */
109  	#endif
110  	#define DEFAULT_NPSEUDOBRANCHES       2 /**< number of children created in pseudo branching (0: disable branching) */
111  	#define DEFAULT_DUALPRESOLVING     TRUE /**< should dual presolving steps be performed? */
112  	
113  	#define DEFAULT_CLIQUELIFTING     FALSE /**< should we try to lift variables into other clique constraints, fix
114  						 *   variables, aggregate them, and also shrink the amount of variables in
115  						 *   clique constraints
116  						 */
117  	#define DEFAULT_ADDVARIABLESASCLIQUES FALSE/**< should we try to generate extra clique constraint out of all binary
118  	                                            *   variables to hopefully fasten the detection of redundant clique
119  	                                            *   constraints */
120  	#define DEFAULT_CLIQUESHRINKING    TRUE /**< should we try to shrink the number of variables in a clique constraints, by
121  						 *   replacing more than one variable by only one
122  						 */
123  	
124  	/* @todo maybe use event SCIP_EVENTTYPE_VARUNLOCKED to decide for another dual-presolving run on a constraint */
125  	
126  	/*
127  	 * Data structures
128  	 */
129  	
130  	/** constraint handler data */
131  	struct SCIP_ConshdlrData
132  	{
133  	   SCIP_EVENTHDLR*       eventhdlr;          /**< event handler for bound change events */
134  	   SCIP_CONSHDLR*        conshdlrlinear;     /**< pointer to linear constraint handler or NULL if not included */
135  	#ifdef VARUSES
136  	   SCIP_INTARRAY*        varuses;            /**< number of times a var is used in the active setppc constraints */
137  	#endif
138  	   SCIP_Longint          nsetpart;           /**< number of set partitioning constraints in transformed problem */
139  	   int                   npseudobranches;    /**< number of children created in pseudo branching (0 to disable branching) */
140  	   int                   noldfixedvars;      /**< number of fixed variables after last clique lifting run */
141  	   int                   noldimpls;          /**< number of implication before last clique lifting run */
142  	   int                   noldcliques;        /**< number of cliques before last clique lifting run */
143  	   int                   noldupgrs;          /**< number of setppc constraints since the last clique lifting run */
144  	   int                   nclqpresolve;       /**< number of setppc clique lifting runs */
145  	   SCIP_Bool             updatedsetppctype;  /**< remember whether we upgraded a constraint type */
146  	   SCIP_Bool             cliquelifting;      /**< should we perform the clique lifting procedure */
147  	   SCIP_Bool             enablecliquelifting;/**< check whether we have enough changes to run the lifting procedure again */
148  	   SCIP_Bool             cliqueshrinking;    /**< should we try to shrink the number of variables in a clique
149  						      *   constraints, by replacing more than one variable by only one
150  						      */
151  	   SCIP_Bool             addvariablesascliques;/**< should we try to generate extra clique constraint out of all binary
152  	                                                *   variables to hopefully fasten the detection of redundant clique
153  	                                                *   constraints */
154  	   SCIP_RANDNUMGEN*      randnumgen;         /**< random number generator */
155  	   SCIP_Bool             presolpairwise;     /**< should pairwise constraint comparison be performed in presolving? */
156  	   SCIP_Bool             presolusehashing;   /**< should hash table be used for detecting redundant constraints in advance */
157  	   SCIP_Bool             dualpresolving;     /**< should dual presolving steps be performed? */
158  	};
159  	
160  	/** constraint data for set partitioning / packing / covering constraints */
161  	struct SCIP_ConsData
162  	{
163  	   uint64_t              signature;          /**< bit signature of vars array */
164  	   SCIP_ROW*             row;                /**< LP row, if constraint is already stored in LP row format */
165  	   SCIP_NLROW*           nlrow;              /**< NLP row, if constraint has been added to NLP relaxation */
166  	   SCIP_VAR**            vars;               /**< variables of the constraint */
167  	   int                   varssize;           /**< size of vars array */
168  	   int                   nvars;              /**< number of variables in the constraint */
169  	   int                   nfixedzeros;        /**< current number of variables fixed to zero in the constraint */
170  	   int                   nfixedones;         /**< current number of variables fixed to one in the constraint */
171  	   unsigned int          setppctype:2;       /**< type of constraint: set partitioning, packing or covering */
172  	   unsigned int          sorted:1;           /**< are the constraint's variables sorted? */
173  	   unsigned int          cliqueadded:1;      /**< was the set partitioning / packing constraint already added as clique? */
174  	   unsigned int          validsignature:1;   /**< is the bit signature valid? */
175  	   unsigned int          changed:1;          /**< was constraint changed since last redundancy round in preprocessing? */
176  	   unsigned int          varsdeleted:1;      /**< were variables deleted after last cleanup? */
177  	   unsigned int          merged:1;           /**< are the constraint's equal/negated variables already merged? */
178  	   unsigned int          presolpropagated:1; /**< was the constraint already propagated in presolving w.r.t. the current domains? */
179  	   unsigned int          existmultaggr:1;    /**< does this constraint contain aggregations */
180  	   unsigned int          catchevents:1;      /**< are events installed for this constraint? */
181  	};
182  	
183  	
184  	
185  	
186  	/*
187  	 * Local methods
188  	 */
189  	
190  	/** compares two active constraints of type set partitioning or set packing such that a "-1" is return if
191  	 *    1. the first constraint is a set partitioning constraint and the second is a set packing or
192  	 *    2. both constraints are set partitioning constraints and the second has more! variables than the first or
193  	 *    3. both constraints are set packing constraints and the second has less! variables than the first
194  	 *  a "0" is return if
195  	 *    1. both constraint are of the same type and have the amount of variables or
196  	 *  and a "1" is returned otherwise
197  	 */
198  	static
199  	int setppcCompare(
200  	   SCIP_CONS*const       cons1,              /**< first problem variable */
201  	   SCIP_CONS*const       cons2               /**< second problem variable */
202  	   )
203  	{
204  	   SCIP_CONSDATA* consdata1;
205  	   SCIP_CONSDATA* consdata2;
206  	
207  	   assert(cons1 != NULL);
208  	   assert(cons2 != NULL);
209  	   assert(SCIPconsIsActive(cons1));
210  	   assert(SCIPconsIsActive(cons2));
211  	
212  	   /* the partitioning type should be the smallest value and the packing the second smallest */
213  	   assert(SCIP_SETPPCTYPE_PARTITIONING < SCIP_SETPPCTYPE_PACKING); /*lint !e506*/
214  	
215  	   consdata1 = SCIPconsGetData(cons1);
216  	   assert(consdata1 != NULL);
217  	   assert(consdata1->setppctype != SCIP_SETPPCTYPE_COVERING); /*lint !e641*/
218  	   consdata2 = SCIPconsGetData(cons2);
219  	   assert(consdata2 != NULL);
220  	   assert(consdata2->setppctype != SCIP_SETPPCTYPE_COVERING); /*lint !e641*/
221  	
222  	   if( consdata1->setppctype < consdata2->setppctype ||
223  	      (consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->nvars < consdata2->nvars) || /*lint !e641*/
224  	      (consdata2->setppctype == SCIP_SETPPCTYPE_PACKING && consdata1->nvars > consdata2->nvars) ) /*lint !e641*/
225  	      return -1;
226  	   else if( (consdata1->setppctype == consdata2->setppctype && consdata1->nvars == consdata2->nvars) ) /*lint !e641*/
227  	      return 0;
228  	   else
229  	   {
230  	      assert(consdata1->setppctype > consdata2->setppctype || (consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->setppctype == consdata2->setppctype && consdata1->nvars > consdata2->nvars) || (consdata1->setppctype == SCIP_SETPPCTYPE_PACKING && consdata1->setppctype == consdata2->setppctype && consdata1->nvars < consdata2->nvars)); /*lint !e641*/
231  	      return +1;
232  	   }
233  	}
234  	
235  	/** sort constraints first after type (partitioning before packing before covering) and second after number of
236  	 *  variables such that the partitioning constraints have increasing number of variables and the packing constraints
237  	 *  have decreasing number of variables */
238  	static
239  	SCIP_DECL_SORTPTRCOMP(setppcConssSort)
240  	{
241  	   return setppcCompare((SCIP_CONS*)elem1, (SCIP_CONS*)elem2);
242  	}
243  	
244  	/** compares two setppc constraints such that a "-1" is return if the first constraint is active and
245  	 *    1. the second constraint is deleted
246  	 *    2. the first constraint is a set partitioning constraint and the second is a set packing or
247  	 *    3. both constraints are set partitioning constraints and the second has more! variables than the first or
248  	 *    4. both constraints are set packing constraints and the second has less! variables than the first
249  	 *  a "0" is return if
250  	 *    1. both constraint are set-covering constraints
251  	 *    2. both constraint are of the same type and have the amount of variables or
252  	 *  and a "1" is returned otherwise
253  	 */
254  	static
255  	int setppcCompare2(
256  	   SCIP_CONS*const       cons1,              /**< first problem variable */
257  	   SCIP_CONS*const       cons2               /**< second problem variable */
258  	   )
259  	{
260  	   SCIP_CONSDATA* consdata1;
261  	   SCIP_CONSDATA* consdata2;
262  	
263  	   assert(cons1 != NULL);
264  	   assert(cons2 != NULL);
265  	
266  	   if( SCIPconsIsDeleted(cons1) )
267  	   {
268  	      if( SCIPconsIsDeleted(cons2) )
269  	         return 0;
270  	      else
271  	         return +1;
272  	   }
273  	   else if( SCIPconsIsDeleted(cons2) )
274  	      return -1;
275  	
276  	   consdata1 = SCIPconsGetData(cons1);
277  	   assert(consdata1 != NULL);
278  	   consdata2 = SCIPconsGetData(cons2);
279  	   assert(consdata2 != NULL);
280  	
281  	   /* the partitioning type should be the smallest value and the packing the second smallest */
282  	   assert(SCIP_SETPPCTYPE_PARTITIONING < SCIP_SETPPCTYPE_PACKING && SCIP_SETPPCTYPE_PACKING < SCIP_SETPPCTYPE_COVERING); /*lint !e506*//*lint !e1564*/
283  	
284  	   if( consdata1->setppctype < consdata2->setppctype ||
285  	      ((SCIP_SETPPCTYPE)consdata1->setppctype != SCIP_SETPPCTYPE_COVERING &&
286  	         (((SCIP_SETPPCTYPE)consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->nvars < consdata2->nvars) ||
287  	            ((SCIP_SETPPCTYPE)consdata2->setppctype == SCIP_SETPPCTYPE_PACKING && consdata1->nvars > consdata2->nvars))) )
288  	      return -1;
289  	   else if( ((SCIP_SETPPCTYPE)consdata2->setppctype == SCIP_SETPPCTYPE_COVERING || (consdata1->setppctype == consdata2->setppctype && consdata1->nvars == consdata2->nvars)) )
290  	      return 0;
291  	   else
292  	   {
293  	      assert(consdata1->setppctype > consdata2->setppctype || ((consdata1->setppctype == consdata2->setppctype) &&
294  	            ((consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->nvars > consdata2->nvars)
295  	               || (consdata1->setppctype == SCIP_SETPPCTYPE_PACKING && consdata1->nvars < consdata2->nvars)))); /*lint !e641*/
296  	      return +1;
297  	   }
298  	}
299  	
300  	/** sort constraints first after type (partitioning before packing before covering) and second after number of
301  	 *  variables such that the partitioning constraints have increasing number of variables and the packing constraints
302  	 *  have decreasing number of variables */
303  	static
304  	SCIP_DECL_SORTPTRCOMP(setppcConssSort2)
305  	{
306  	   return setppcCompare2((SCIP_CONS*)elem1, (SCIP_CONS*)elem2);
307  	}
308  	
309  	
310  	/** installs rounding locks for the given variable in the given setppc constraint */
311  	static
312  	SCIP_RETCODE lockRounding(
313  	   SCIP*                 scip,               /**< SCIP data structure */
314  	   SCIP_CONS*            cons,               /**< setppc constraint */
315  	   SCIP_VAR*             var                 /**< variable of constraint entry */
316  	   )
317  	{
318  	   SCIP_CONSDATA* consdata;
319  	
320  	   consdata = SCIPconsGetData(cons);
321  	   assert(consdata != NULL);
322  	
323  	   switch( consdata->setppctype )
324  	   {
325  	   case SCIP_SETPPCTYPE_PARTITIONING:
326  	      SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, TRUE) );
327  	      break;
328  	   case SCIP_SETPPCTYPE_PACKING:
329  	      SCIP_CALL( SCIPlockVarCons(scip, var, cons, FALSE, TRUE) );
330  	      break;
331  	   case SCIP_SETPPCTYPE_COVERING:
332  	      SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, FALSE) );
333  	      break;
334  	   default:
335  	      SCIPerrorMessage("unknown setppc type\n");
336  	      return SCIP_INVALIDDATA;
337  	   }
338  	
339  	   return SCIP_OKAY;
340  	}
341  	
342  	/** removes rounding locks for the given variable in the given setppc constraint */
343  	static
344  	SCIP_RETCODE unlockRounding(
345  	   SCIP*                 scip,               /**< SCIP data structure */
346  	   SCIP_CONS*            cons,               /**< setppc constraint */
347  	   SCIP_VAR*             var                 /**< variable of constraint entry */
348  	   )
349  	{
350  	   SCIP_CONSDATA* consdata;
351  	
352  	   consdata = SCIPconsGetData(cons);
353  	   assert(consdata != NULL);
354  	
355  	   switch( consdata->setppctype )
356  	   {
357  	   case SCIP_SETPPCTYPE_PARTITIONING:
358  	      SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, TRUE) );
359  	      break;
360  	   case SCIP_SETPPCTYPE_PACKING:
361  	      SCIP_CALL( SCIPunlockVarCons(scip, var, cons, FALSE, TRUE) );
362  	      break;
363  	   case SCIP_SETPPCTYPE_COVERING:
364  	      SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, FALSE) );
365  	      break;
366  	   default:
367  	      SCIPerrorMessage("unknown setppc type\n");
368  	      return SCIP_INVALIDDATA;
369  	   }
370  	
371  	   return SCIP_OKAY;
372  	}
373  	
374  	/** creates constraint handler data for set partitioning / packing / covering constraint handler */
375  	static
376  	SCIP_RETCODE conshdlrdataCreate(
377  	   SCIP*                 scip,               /**< SCIP data structure */
378  	   SCIP_CONSHDLRDATA**   conshdlrdata,       /**< pointer to store the constraint handler data */
379  	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler */
380  	   )
381  	{
382  	   assert(scip != NULL);
383  	   assert(conshdlrdata != NULL);
384  	   assert(eventhdlr != NULL);
385  	
386  	   SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
387  	#ifdef VARUSES
388  	   SCIP_CALL( SCIPcreateIntarray(scip, &(*conshdlrdata)->varuses) );
389  	#endif
390  	   (*conshdlrdata)->npseudobranches = DEFAULT_NPSEUDOBRANCHES;
391  	
392  	   /* set event handler for bound change events */
393  	   (*conshdlrdata)->eventhdlr = eventhdlr;
394  	   (*conshdlrdata)->nsetpart = 0;
395  	
396  	   /* create a random number generator */
397  	   SCIP_CALL( SCIPcreateRandom(scip, &(*conshdlrdata)->randnumgen,
398  	         DEFAULT_RANDSEED, TRUE) );
399  	
400  	   return SCIP_OKAY;
401  	}
402  	
403  	/** frees constraint handler data for set partitioning / packing / covering constraint handler */
404  	static
405  	SCIP_RETCODE conshdlrdataFree(
406  	   SCIP*                 scip,               /**< SCIP data structure */
407  	   SCIP_CONSHDLRDATA**   conshdlrdata        /**< pointer to the constraint handler data */
408  	   )
409  	{
410  	   assert(conshdlrdata != NULL);
411  	   assert(*conshdlrdata != NULL);
412  	
413  	#ifdef VARUSES
414  	   SCIP_CALL( SCIPfreeIntarray(scip, &(*conshdlrdata)->varuses) );
415  	#endif
416  	
417  	   /* free random number generator */
418  	   SCIPfreeRandom(scip, &(*conshdlrdata)->randnumgen);
419  	
420  	   SCIPfreeBlockMemory(scip, conshdlrdata);
421  	
422  	   return SCIP_OKAY;
423  	}
424  	
425  	#ifdef VARUSES
426  	/** adds the given value to the usage counter of the given variable */
427  	static
428  	SCIP_RETCODE conshdlrdataAddVaruses(
429  	   SCIP*                 scip,               /**< SCIP data structure */
430  	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
431  	   SCIP_VAR*             var,                /**< variable to increase usage counter for */
432  	   int                   addval              /**< value to add to the usage counter */
433  	   )
434  	{
435  	   SCIP_INTARRAY* varuses;
436  	
437  	   assert(conshdlrdata != NULL);
438  	   assert(var != NULL);
439  	
440  	   varuses = conshdlrdata->varuses;
441  	   assert(varuses != NULL);
442  	
443  	   /* if the variable is the negation of a problem variable, count the varuses in the problem variable */
444  	   if( SCIPvarIsNegated(var) )
445  	   {
446  	      SCIP_VAR* negvar;
447  	      int varindex;
448  	
449  	      /* move the varuses value of the negated variable to the active problem variable */
450  	      varindex = SCIPvarGetIndex(var);
451  	      addval += SCIPgetIntarrayVal(scip, varuses, varindex);
452  	      SCIP_CALL( SCIPsetIntarrayVal(scip, varuses, varindex, 0) );
453  	      SCIP_CALL( SCIPgetNegatedVar(scip, var, &negvar) );
454  	      var = negvar;
455  	   }
456  	
457  	   /* increase varuses counter */
458  	   SCIP_CALL( SCIPincIntarrayVal(scip, varuses, SCIPvarGetIndex(var), addval) );
459  	
460  	   SCIPdebugMsg(scip, "added %d to varuses of <%s>: %d\n",
461  	      addval, SCIPvarGetName(var), SCIPgetIntarrayVal(scip, varuses, SCIPvarGetIndex(var)));
462  	
463  	   return SCIP_OKAY;
464  	}
465  	
466  	/** increases the usage counter of the given variable */
467  	static
468  	SCIP_RETCODE conshdlrdataIncVaruses(
469  	   SCIP*                 scip,               /**< SCIP data structure */
470  	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
471  	   SCIP_VAR*             var                 /**< variable to increase usage counter for */
472  	   )
473  	{
474  	   assert(conshdlrdata != NULL);
475  	
476  	   SCIPdebugMsg(scip, "increasing varuses of <%s>: %d\n",
477  	      SCIPvarGetName(var), SCIPgetIntarrayVal(scip, conshdlrdata->varuses, SCIPvarGetIndex(var)));
478  	
479  	   SCIP_CALL( conshdlrdataAddVaruses(scip, conshdlrdata, var, +1) );
480  	
481  	   return SCIP_OKAY;
482  	}
483  	
484  	/** decreases the usage counter of the given variable */
485  	static
486  	SCIP_RETCODE conshdlrdataDecVaruses(
487  	   SCIP*                 scip,               /**< SCIP data structure */
488  	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
489  	   SCIP_VAR*             var                 /**< variable to increase usage counter for */
490  	   )
491  	{
492  	   assert(conshdlrdata != NULL);
493  	
494  	   SCIPdebugMsg(scip, "decreasing varuses of <%s>: %d\n",
495  	      SCIPvarGetName(var), SCIPgetIntarrayVal(scip, conshdlrdata->varuses, SCIPvarGetIndex(var)));
496  	
497  	   SCIP_CALL( conshdlrdataAddVaruses(scip, conshdlrdata, var, -1) );
498  	
499  	   return SCIP_OKAY;
500  	}
501  	
502  	/** increases the usage counter of all variable in the constraint */
503  	static
504  	SCIP_RETCODE consdataIncVaruses(
505  	   SCIP*                 scip,               /**< SCIP data structure */
506  	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
507  	   SCIP_CONSDATA*        consdata            /**< setppc constraint data */
508  	   )
509  	{
510  	   int v;
511  	
512  	   assert(consdata != NULL);
513  	
514  	   for( v = 0; v < consdata->nvars; ++v )
515  	   {
516  	      SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, consdata->vars[v]) );
517  	   }
518  	
519  	   return SCIP_OKAY;
520  	}
521  	
522  	/** decreases the usage counter of all variable in the constraint */
523  	static
524  	SCIP_RETCODE consdataDecVaruses(
525  	   SCIP*                 scip,               /**< SCIP data structure */
526  	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
527  	   SCIP_CONSDATA*        consdata            /**< setppc constraint data */
528  	   )
529  	{
530  	   int v;
531  	
532  	   assert(consdata != NULL);
533  	
534  	   for( v = 0; v < consdata->nvars; ++v )
535  	   {
536  	      SCIP_CALL( conshdlrdataDecVaruses(scip, conshdlrdata, consdata->vars[v]) );
537  	   }
538  	
539  	   return SCIP_OKAY;
540  	}
541  	#endif
542  	
543  	/** ensures, that the vars array can store at least num entries */
544  	static
545  	SCIP_RETCODE consdataEnsureVarsSize(
546  	   SCIP*                 scip,               /**< SCIP data structure */
547  	   SCIP_CONSDATA*        consdata,           /**< setppc constraint data */
548  	   int                   num                 /**< minimum number of entries to store */
549  	   )
550  	{
551  	   assert(consdata != NULL);
552  	   assert(consdata->nvars <= consdata->varssize);
553  	
554  	   if( num > consdata->varssize )
555  	   {
556  	      int newsize;
557  	
558  	      newsize = SCIPcalcMemGrowSize(scip, num);
559  	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
560  	      consdata->varssize = newsize;
561  	   }
562  	   assert(num <= consdata->varssize);
563  	
564  	   return SCIP_OKAY;
565  	}
566  	
567  	/** creates a set partitioning / packing / covering constraint data object */
568  	static
569  	SCIP_RETCODE consdataCreate(
570  	   SCIP*                 scip,               /**< SCIP data structure */
571  	   SCIP_CONSDATA**       consdata,           /**< pointer to store the set partitioning / packing / covering constraint */
572  	   int                   nvars,              /**< number of variables in the constraint */
573  	   SCIP_VAR**            vars,               /**< variables of the constraint */
574  	   SCIP_SETPPCTYPE       setppctype          /**< type of constraint: set partitioning, packing, or covering constraint */
575  	   )
576  	{
577  	   assert(consdata != NULL);
578  	   assert(nvars == 0 || vars != NULL);
579  	
580  	   SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
581  	
582  	   (*consdata)->signature = 0;
583  	   (*consdata)->row = NULL;
584  	   (*consdata)->nlrow = NULL;
585  	   (*consdata)->existmultaggr = FALSE;
586  	   (*consdata)->catchevents = FALSE;
587  	   (*consdata)->nfixedzeros = 0;
588  	   (*consdata)->nfixedones = 0;
589  	
590  	   if( nvars > 0 )
591  	   {
592  	      int v;
593  	
594  	      /* @todo the setppc constraint handler does not remove fixed variables from its var array; removing those
595  	       * variables is only possible if we consider the values of nfixedones and nfixedzeros in all propagation methods
596  	       */
597  	#ifdef SCIP_DISABLED_CODE
598  	
599  	      if( SCIPisConsCompressionEnabled(scip) )
600  	      {
601  	         SCIP_VAR** varsbuffer;
602  	         int k;
603  	
604  	         /* allocate temporary buffer storage for active variables */
605  	         SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
606  	
607  	         k = 0;
608  	         /* collect fixed variables to compress the required memory */
609  	         for( v = 0; v < nvars; ++v )
610  	         {
611  	            assert(SCIPvarIsBinary(vars[v]));
612  	
613  	            /* already fixed variables account as fixed ones or zero, only unfixed are appended */
614  	            if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
615  	               (*consdata)->nfixedones++;
616  	            else if( SCIPvarGetUbGlobal(vars[v]) < 0.5 )
617  	               (*consdata)->nfixedzeros++;
618  	            else
619  	               varsbuffer[k++] = vars[v];
620  	         }
621  	
622  	         (*consdata)->varssize = k;
623  	         (*consdata)->nvars = k;
624  	         /* copy unfixed variables into constraint data */
625  	         if( k > 0 )
626  	         {
627  	            SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
628  	         }
629  	
630  	         /* free temporary storage */
631  	         SCIPfreeBufferArray(scip, &varsbuffer);
632  	      }
633  	      else
634  	#endif
635  	      {
636  	         /* for uncompressed copies, simply duplicate the whole array */
637  	         SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
638  	         (*consdata)->varssize = nvars;
639  	         (*consdata)->nvars = nvars;
640  	      }
641  	
642  	      if( SCIPisTransformed(scip) )
643  	      {
644  	         /* get transformed variables */
645  	         SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
646  	
647  	         /* check for multi-aggregations and capture variables */
648  	         for( v = 0; v < (*consdata)->nvars; v++ )
649  	         {
650  	            SCIP_VAR* var = SCIPvarGetProbvar((*consdata)->vars[v]);
651  	            assert(var != NULL);
652  	            (*consdata)->existmultaggr = (*consdata)->existmultaggr || (SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
653  	            SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
654  	         }
655  	      }
656  	      else
657  	      {
658  	         /* capture variables */
659  	         for( v = 0; v < (*consdata)->nvars; v++ )
660  	         {
661  	            assert((*consdata)->vars[v] != NULL);
662  	            SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
663  	         }
664  	      }
665  	   }
666  	   else
667  	   {
668  	      (*consdata)->vars = NULL;
669  	      (*consdata)->varssize = 0;
670  	      (*consdata)->nvars = 0;
671  	   }
672  	   (*consdata)->setppctype = setppctype; /*lint !e641*/
673  	   (*consdata)->sorted = (nvars <= 1);
674  	   (*consdata)->cliqueadded = FALSE;
675  	   (*consdata)->validsignature = FALSE;
676  	   (*consdata)->changed = TRUE;
677  	   (*consdata)->varsdeleted = FALSE;
678  	   (*consdata)->merged = FALSE;
679  	   (*consdata)->presolpropagated = FALSE;
680  	
681  	   return SCIP_OKAY;
682  	}
683  	
684  	/** creates a transformed set partitioning / packing / covering constraint data object */
685  	static
686  	SCIP_RETCODE consdataCreateTransformed(
687  	   SCIP*                 scip,               /**< SCIP data structure */
688  	   SCIP_CONSDATA**       consdata,           /**< pointer to store the set partitioning / packing / covering constraint */
689  	   int                   nvars,              /**< number of variables in the constraint */
690  	   SCIP_VAR**            vars,               /**< variables of the constraint */
691  	   SCIP_SETPPCTYPE       setppctype          /**< type of constraint: set partitioning, packing, or covering constraint */
692  	   )
693  	{
694  	   assert(consdata != NULL);
695  	   assert(nvars == 0 || vars != NULL);
696  	
697  	   /* create constraint data */
698  	   SCIP_CALL( consdataCreate(scip, consdata, nvars, vars, setppctype) );
699  	
700  	   /* transform the variables */
701  	   SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
702  	
703  	   return SCIP_OKAY;
704  	}
705  	
706  	/** frees a set partitioning / packing / covering constraint data */
707  	static
708  	SCIP_RETCODE consdataFree(
709  	   SCIP*                 scip,               /**< SCIP data structure */
710  	   SCIP_CONSDATA**       consdata            /**< pointer to store the set partitioning / packing / covering constraint */
711  	   )
712  	{
713  	   int v;
714  	
715  	   assert(consdata != NULL);
716  	   assert(*consdata != NULL);
717  	
718  	   /* release the row */
719  	   if( (*consdata)->row != NULL )
720  	   {
721  	      SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
722  	   }
723  	
724  	   /* release the nlrow */
725  	   if( (*consdata)->nlrow != NULL )
726  	   {
727  	      SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
728  	   }
729  	
730  	   /* release variables */
731  	   for( v = 0; v < (*consdata)->nvars; v++ )
732  	   {
733  	      assert((*consdata)->vars[v] != NULL);
734  	      SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
735  	   }
736  	
737  	   SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
738  	   SCIPfreeBlockMemory(scip, consdata);
739  	
740  	   return SCIP_OKAY;
741  	}
742  	
743  	/** prints set partitioning / packing / covering constraint to file stream */
744  	static
745  	SCIP_RETCODE consdataPrint(
746  	   SCIP*                 scip,               /**< SCIP data structure */
747  	   SCIP_CONSDATA*        consdata,           /**< set partitioning / packing / covering constraint data */
748  	   FILE*                 file                /**< output file (or NULL for standard output) */
749  	   )
750  	{
751  	   assert(consdata != NULL);
752  	
753  	   /* print coefficients */
754  	   if( consdata->nvars == 0 )
755  	      SCIPinfoMessage(scip, file, "0 ");
756  	
757  	   /* write linear sum */
758  	   SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, NULL, consdata->nvars, TRUE) );
759  	
760  	   /* print right hand side */
761  	   switch( consdata->setppctype )
762  	   {
763  	   case SCIP_SETPPCTYPE_PARTITIONING:
764  	      SCIPinfoMessage(scip, file, " == 1");
765  	      break;
766  	   case SCIP_SETPPCTYPE_PACKING:
767  	      SCIPinfoMessage(scip, file, " <= 1");
768  	      break;
769  	   case SCIP_SETPPCTYPE_COVERING:
770  	      SCIPinfoMessage(scip, file, " >= 1");
771  	      break;
772  	   default:
773  	      SCIPerrorMessage("unknown setppc type\n");
774  	      return SCIP_ERROR;
775  	   }
776  	
777  	   return SCIP_OKAY;
778  	}
779  	
780  	/** returns the bit signature of the given constraint data */
781  	static
782  	uint64_t consdataGetSignature(
783  	   SCIP_CONSDATA*        consdata            /**< set partitioning / packing / covering constraint data */
784  	   )
785  	{
786  	   assert(consdata != NULL);
787  	
788  	   if( !consdata->validsignature )
789  	   {
790  	      int i;
791  	
792  	      consdata->signature = 0;
793  	      for( i = 0; i < consdata->nvars; ++i )
794  	         consdata->signature |= SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[i]));
795  	      consdata->validsignature = TRUE;
796  	   }
797  	
798  	   return consdata->signature;
799  	}
800  	
801  	/** sorts setppc constraint's variables by non-decreasing variable index */
802  	static
803  	void consdataSort(
804  	   SCIP_CONSDATA*        consdata            /**< linear constraint data */
805  	   )
806  	{
807  	   assert(consdata != NULL);
808  	
809  	   if( !consdata->sorted )
810  	   {
811  	      if( consdata->nvars <= 1 )
812  		 consdata->sorted = TRUE;
813  	      else
814  	      {
815  		 SCIPsortPtr((void**)consdata->vars, SCIPvarComp, consdata->nvars);
816  		 consdata->sorted = TRUE;
817  	      }
818  	   }
819  	   assert(consdata->sorted);
820  	#ifdef SCIP_DEBUG
821  	   /* check sorting */
822  	   {
823  	      int v;
824  	
825  	      for( v = 0; v < consdata->nvars; ++v )
826  	      {
827  	         assert(v == consdata->nvars-1 || SCIPvarCompare(consdata->vars[v], consdata->vars[v+1]) <= 0);
828  	      }
829  	   }
830  	#endif
831  	}
832  	
833  	/** changes the type of a setppc constraint */
834  	static
835  	SCIP_RETCODE setSetppcType(
836  	   SCIP*                 scip,               /**< SCIP data structure */
837  	   SCIP_CONS*            cons,               /**< setppc constraint */
838  	   SCIP_SETPPCTYPE       setppctype          /**< new type of constraint */
839  	   )
840  	{
841  	   SCIP_CONSHDLR* conshdlr;
842  	   SCIP_CONSHDLRDATA* conshdlrdata;
843  	   SCIP_CONSDATA* consdata;
844  	   SCIP_Bool locked;
845  	   int i;
846  	
847  	   consdata = SCIPconsGetData(cons);
848  	   assert(consdata != NULL);
849  	
850  	   if( (SCIP_SETPPCTYPE)consdata->setppctype == setppctype )
851  	      return SCIP_OKAY;
852  	
853  	   SCIPdebugMsg(scip, " -> converting <%s> into setppc type %d\n", SCIPconsGetName(cons), setppctype);
854  	
855  	   /* remove rounding locks */
856  	   locked = FALSE;
857  	   for( i = 0; i < NLOCKTYPES && !locked; i++ )
858  	      locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
859  	
860  	   if( locked )
861  	   {
862  	      for( i = 0; i < consdata->nvars; ++i )
863  	      {
864  	         SCIP_CALL( unlockRounding(scip, cons, consdata->vars[i]) );
865  	      }
866  	   }
867  	
868  	   conshdlr = SCIPconsGetHdlr(cons);
869  	   assert(conshdlr != NULL);
870  	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
871  	   assert(conshdlrdata != NULL);
872  	
873  	   if( SCIPisTransformed(scip) )
874  	   {
875  	      if( setppctype == SCIP_SETPPCTYPE_PARTITIONING )
876  	      {
877  	         ++(conshdlrdata->nsetpart);
878  	         assert(conshdlrdata->nsetpart >= 0);
879  	      }
880  	      else if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
881  	      {
882  	         --(conshdlrdata->nsetpart);
883  	         assert(conshdlrdata->nsetpart >= 0);
884  	      }
885  	   }
886  	
887  	   /* change the constraint type */
888  	   consdata->setppctype = setppctype; /*lint !e641*/
889  	
890  	   /* reinstall rounding locks again */
891  	   if( locked )
892  	   {
893  	      for( i = 0; i < consdata->nvars; ++i )
894  	      {
895  	         SCIP_CALL( lockRounding(scip, cons, consdata->vars[i]) );
896  	      }
897  	   }
898  	
899  	   /* remember that we changed a constraint type for clique lifting procedure */
900  	   if( setppctype != SCIP_SETPPCTYPE_COVERING )
901  	      conshdlrdata->updatedsetppctype = TRUE;
902  	
903  	   return SCIP_OKAY;
904  	}
905  	
906  	/** catches events for variable at given position */
907  	static
908  	SCIP_RETCODE catchEvent(
909  	   SCIP*                 scip,               /**< SCIP data structure */
910  	   SCIP_CONS*            cons,               /**< set partitioning / packing / covering constraint */
911  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
912  	   int                   pos                 /**< array position of variable to catch bound change events for */
913  	   )
914  	{
915  	   SCIP_CONSDATA* consdata;
916  	   SCIP_EVENTTYPE eventtype;
917  	   SCIP_VAR* var;
918  	
919  	   consdata = SCIPconsGetData(cons);
920  	   assert(consdata != NULL);
921  	   assert(eventhdlr != NULL);
922  	   assert(0 <= pos && pos < consdata->nvars);
923  	   assert(consdata->vars != NULL);
924  	
925  	   var = consdata->vars[pos];
926  	   assert(var != NULL);
927  	
928  	   /* we are catching the following events:
929  	    *
930  	    * - SCIP_EVENTTYPE_BOUNDCHANGED: Is used to count the number of variable fixed locally to zero and one. That helps
931  	    *                                to speed up the propagation
932  	    *
933  	    * - SCIP_EVENTTYPE_VARDELETED: Is caught to remove a deleted variable from the constraint
934  	    *
935  	    * - SCIP_EVENTTYPE_VARFIXED: Is used to get informed if a variable of the constraint was aggregated which means was
936  	    *                            detected to be equal or a negated variable of on other variable. in case of a negation
937  	    *                            this could lead to a redundant constraint if the (other) active variable is also part
938  	    *                            of the constraint.
939  	    */
940  	   eventtype =  SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_VARDELETED | SCIP_EVENTTYPE_VARFIXED;
941  	
942  	   /* catch bound change events on variable */
943  	   SCIP_CALL( SCIPcatchVarEvent(scip, var, eventtype, eventhdlr, (SCIP_EVENTDATA*)cons, NULL) );
944  	
945  	   /* update the fixed variables counters for this variable */
946  	   if( SCIPisEQ(scip, SCIPvarGetUbLocal(var), 0.0) )
947  	   {
948  	      consdata->nfixedzeros++;
949  	
950  	      /* during presolving, we may fix the last unfixed variable or do an aggregation if there are two unfixed variables */
951  	      if( SCIPconsIsActive(cons) && ((SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE) && (consdata->nfixedzeros >= consdata->nvars - 2)) )
952  	      {
953  	         consdata->presolpropagated = FALSE;
954  	
955  	         /* during solving, we only propagate again if there is only one unfixed variable left */
956  	         if( consdata->nfixedzeros >= consdata->nvars - 1 )
957  	         {
958  	            SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
959  	         }
960  	      }
961  	   }
962  	   else if( SCIPisEQ(scip, SCIPvarGetLbLocal(var), 1.0) )
963  	   {
964  	      consdata->nfixedones++;
965  	
966  	      if( SCIPconsIsActive(cons) )
967  	      {
968  	         consdata->presolpropagated = FALSE;
969  	         SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
970  	      }
971  	   }
972  	
973  	   return SCIP_OKAY;
974  	}
975  	
976  	/** drops events for variable at given position */
977  	static
978  	SCIP_RETCODE dropEvent(
979  	   SCIP*                 scip,               /**< SCIP data structure */
980  	   SCIP_CONS*            cons,               /**< set partitioning / packing / covering constraint */
981  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
982  	   int                   pos                 /**< array position of variable to catch bound change events for */
983  	   )
984  	{
985  	   SCIP_CONSDATA* consdata;
986  	   SCIP_EVENTTYPE eventtype;
987  	   SCIP_VAR* var;
988  	
989  	   consdata = SCIPconsGetData(cons);
990  	   assert(consdata != NULL);
991  	   assert(eventhdlr != NULL);
992  	   assert(0 <= pos && pos < consdata->nvars);
993  	   assert(consdata->vars != NULL);
994  	
995  	   var = consdata->vars[pos];
996  	   assert(var != NULL);
997  	
998  	   eventtype =  SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_VARDELETED | SCIP_EVENTTYPE_VARFIXED;
999  	
1000 	   /* drop events on variable */
1001 	   SCIP_CALL( SCIPdropVarEvent(scip, var, eventtype, eventhdlr, (SCIP_EVENTDATA*)cons, -1) );
1002 	
1003 	   /* update the fixed variables counters for this variable */
1004 	   if( SCIPisEQ(scip, SCIPvarGetUbLocal(var), 0.0) )
1005 	      consdata->nfixedzeros--;
1006 	   else if( SCIPisEQ(scip, SCIPvarGetLbLocal(var), 1.0) )
1007 	      consdata->nfixedones--;
1008 	
1009 	   return SCIP_OKAY;
1010 	}
1011 	
1012 	/** catches bound change events for all variables in transformed setppc constraint */
1013 	static
1014 	SCIP_RETCODE catchAllEvents(
1015 	   SCIP*                 scip,               /**< SCIP data structure */
1016 	   SCIP_CONS*            cons,               /**< set partitioning / packing / covering constraint */
1017 	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler to call for the event processing */
1018 	   )
1019 	{
1020 	   SCIP_CONSDATA* consdata;
1021 	   int i;
1022 	
1023 	   consdata = SCIPconsGetData(cons);
1024 	   assert(consdata != NULL);
1025 	
1026 	   if( consdata->catchevents == TRUE )
1027 	      return SCIP_OKAY;
1028 	
1029 	   /* catch event for every single variable */
1030 	   for( i = 0; i < consdata->nvars; ++i )
1031 	   {
1032 	      SCIP_CALL( catchEvent(scip, cons, eventhdlr, i) );
1033 	   }
1034 	
1035 	   consdata->catchevents = TRUE;
1036 	
1037 	   return SCIP_OKAY;
1038 	}
1039 	
1040 	/** drops bound change events for all variables in transformed setppc constraint */
1041 	static
1042 	SCIP_RETCODE dropAllEvents(
1043 	   SCIP*                 scip,               /**< SCIP data structure */
1044 	   SCIP_CONS*            cons,               /**< set partitioning / packing / covering constraint */
1045 	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler to call for the event processing */
1046 	   )
1047 	{
1048 	   SCIP_CONSDATA* consdata;
1049 	   int i;
1050 	
1051 	   consdata = SCIPconsGetData(cons);
1052 	   assert(consdata != NULL);
1053 	
1054 	   if( consdata->catchevents == FALSE )
1055 	      return SCIP_OKAY;
1056 	
1057 	   /* drop event of every single variable */
1058 	   for( i = 0; i < consdata->nvars; ++i )
1059 	   {
1060 	      SCIP_CALL( dropEvent(scip, cons, eventhdlr, i) );
1061 	   }
1062 	
1063 	   consdata->catchevents = FALSE;
1064 	
1065 	   return SCIP_OKAY;
1066 	}
1067 	
1068 	/** adds coefficient in setppc constraint */
1069 	static
1070 	SCIP_RETCODE addCoef(
1071 	   SCIP*                 scip,               /**< SCIP data structure */
1072 	   SCIP_CONS*            cons,               /**< setppc constraint */
1073 	   SCIP_VAR*             var                 /**< variable to add to the constraint */
1074 	   )
1075 	{
1076 	   SCIP_CONSDATA* consdata;
1077 	   SCIP_Bool transformed;
1078 	
1079 	   assert(var != NULL);
1080 	
1081 	   consdata = SCIPconsGetData(cons);
1082 	   assert(consdata != NULL);
1083 	
1084 	   /* are we in the transformed problem? */
1085 	   transformed = SCIPconsIsTransformed(cons);
1086 	
1087 	   /* always use transformed variables in transformed constraints */
1088 	   if( transformed )
1089 	   {
1090 	      SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
1091 	   }
1092 	   assert(var != NULL);
1093 	   assert(transformed == SCIPvarIsTransformed(var));
1094 	
1095 	   SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
1096 	   consdata->vars[consdata->nvars] = var;
1097 	   consdata->nvars++;
1098 	   if( consdata->validsignature )
1099 	      consdata->signature |= SCIPhashSignature64(SCIPvarGetIndex(var));
1100 	   consdata->sorted = (consdata->nvars == 1);
1101 	   consdata->changed = TRUE;
1102 	
1103 	   /* capture the variable */
1104 	   SCIP_CALL( SCIPcaptureVar(scip, var) );
1105 	
1106 	   /* if we are in transformed problem, catch the variable's events */
1107 	   if( transformed )
1108 	   {
1109 	      SCIP_CONSHDLR* conshdlr;
1110 	      SCIP_CONSHDLRDATA* conshdlrdata;
1111 	
1112 	      /* get event handler */
1113 	      conshdlr = SCIPconsGetHdlr(cons);
1114 	      assert(conshdlr != NULL);
1115 	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
1116 	      assert(conshdlrdata != NULL);
1117 	      assert(conshdlrdata->eventhdlr != NULL);
1118 	
1119 	      /* catch bound change events of variable */
1120 	      if( consdata->catchevents )
1121 	      {
1122 	         SCIP_CALL( catchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
1123 	      }
1124 	
1125 	      if( !consdata->existmultaggr && SCIPvarGetStatus(SCIPvarGetProbvar(var)) == SCIP_VARSTATUS_MULTAGGR )
1126 	         consdata->existmultaggr = TRUE;
1127 	
1128 	#ifdef VARUSES
1129 	      /* if the constraint is currently active, increase the variable usage counter */
1130 	      if( SCIPconsIsActive(cons) )
1131 	      {
1132 	         SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, var) );
1133 	      }
1134 	#endif
1135 	   }
1136 	
1137 	   /* install the rounding locks for the new variable */
1138 	   SCIP_CALL( lockRounding(scip, cons, var) );
1139 	
1140 	   /* add the new coefficient to the LP row */
1141 	   if( consdata->row != NULL )
1142 	   {
1143 	      SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, 1.0) );
1144 	   }
1145 	
1146 	   consdata->merged = FALSE;
1147 	   consdata->cliqueadded = FALSE;
1148 	
1149 	   return SCIP_OKAY;
1150 	}
1151 	
1152 	/** deletes coefficient at given position from setppc constraint data */
1153 	static
1154 	SCIP_RETCODE delCoefPos(
1155 	   SCIP*                 scip,               /**< SCIP data structure */
1156 	   SCIP_CONS*            cons,               /**< set partitioning / packing / covering constraint */
1157 	   int                   pos                 /**< position of coefficient to delete */
1158 	   )
1159 	{
1160 	   SCIP_CONSDATA* consdata;
1161 	   SCIP_VAR* var;
1162 	
1163 	   assert(scip != NULL);
1164 	   assert(cons != NULL);
1165 	
1166 	   consdata = SCIPconsGetData(cons);
1167 	   assert(consdata != NULL);
1168 	   assert(0 <= pos && pos < consdata->nvars);
1169 	
1170 	   var = consdata->vars[pos];
1171 	   assert(var != NULL);
1172 	   assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
1173 	
1174 	   /* remove the rounding locks for the deleted variable */
1175 	   SCIP_CALL( unlockRounding(scip, cons, var) );
1176 	
1177 	   /* if we are in transformed problem, delete the event data of the variable */
1178 	   if( SCIPconsIsTransformed(cons) )
1179 	   {
1180 	      SCIP_CONSHDLR* conshdlr;
1181 	      SCIP_CONSHDLRDATA* conshdlrdata;
1182 	
1183 	      /* get event handler */
1184 	      conshdlr = SCIPconsGetHdlr(cons);
1185 	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
1186 	      assert(conshdlrdata != NULL);
1187 	      assert(conshdlrdata->eventhdlr != NULL);
1188 	
1189 	      /* drop bound change events of variable */
1190 	      if( consdata->catchevents )
1191 	      {
1192 	         SCIP_CALL( dropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
1193 	      }
1194 	
1195 	      /* the last variable of the constraint was deleted; mark it for propagation (so that it can be deleted) */
1196 	      if( consdata->nvars == 1 )
1197 	      {
1198 	         consdata->presolpropagated = FALSE;
1199 	      }
1200 	   }
1201 	
1202 	   /* delete coefficient from the LP row */
1203 	   if( consdata->row != NULL )
1204 	   {
1205 	      SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -1.0) );
1206 	   }
1207 	
1208 	   /* move the last variable to the free slot */
1209 	   if( pos != consdata->nvars - 1 )
1210 	   {
1211 	      consdata->vars[pos] = consdata->vars[consdata->nvars-1];
1212 	      consdata->sorted = FALSE;
1213 	   }
1214 	   consdata->nvars--;
1215 	   consdata->validsignature = FALSE;
1216 	   consdata->changed = TRUE;
1217 	
1218 	   /* release variable */
1219 	   SCIP_CALL( SCIPreleaseVar(scip, &var) );
1220 	
1221 	   return SCIP_OKAY;
1222 	}
1223 	
1224 	/** preform dual presolving
1225 	 *
1226 	 *  In case a part (more than one variable) in the setppc constraint is independent of everything else (is locked only by
1227 	 *  this constraint), we can perform dual reductions:
1228 	 *
1229 	 *  (1) set covering
1230 	 *
1231 	 *      - fix all independent variables with negative object coefficient to one
1232 	 *      - fix all remaining independent variables to zero
1233 	 *
1234 	 *      (i) all variables are independent and the constraint is not modifiable
1235 	 *
1236 	 *          - fix the variable with the smallest object coefficient to one
1237 	 *
1238 	 *     (ii) a variable x has exactly 0 uplocks and arbitrary downlocks and a variable y has exactly 1 downlock and
1239 	 *          arbitrary uplocks and obj(x) <= obj(y) and obj(y) >= 0
1240 	 *
1241 	 *          - fix y to 0, because it is dominated by x
1242 	 *
1243 	 *  (2) set partitioning
1244 	 *
1245 	 *      (i) all variables are independent and the constraint is not modifiable
1246 	 *
1247 	 *          - fix the variable with the smallest object coefficient to one
1248 	 *          - fix all remaining independent variables to zero
1249 	 *
1250 	 *     (ii) a variable x has exactly 1 uplock and arbitrary downlocks and a variable y has exactly 1 downlock and
1251 	 *          arbitrary uplocks and obj(x) <= obj(y)
1252 	 *
1253 	 *          - fix y to 0, because it is dominated by x
1254 	 *
1255 	 *  (3) set packing
1256 	 *
1257 	 *      (i) all variables are independent and the constraint is not modifiable
1258 	 *
1259 	 *          - fix the variable with the smallest object coefficient to one if the object coefficient is negative or zero
1260 	 *          - fix all remaining independent variables to zero
1261 	 *
1262 	 *     (ii) a variable x has exactly 1 uplock and arbitrary downlocks and a variable y has exactly 0 downlocks and
1263 	 *          arbitrary uplocks and obj(x) <= obj(y)
1264 	 *
1265 	 *          - fix y to 0, because it is dominated by x
1266 	 *
1267 	 *
1268 	 *  Note: the following dual reduction for set covering and set packing constraints is already performed by the presolver
1269 	 *       "dualfix"
1270 	 *       (1) in case of a set covering constraint the following dual reduction can be performed:
1271 	 *           - if a variable in a set covering constraint is only locked by that constraint and has negative or zero
1272 	 *             objective coefficient than it can be fixed to one
1273 	 *       (2) in case of a set packing constraint the following dual reduction can be performed:
1274 	 *           - if a variable in a set packing constraint is only locked by that constraint and has positive or zero
1275 	 *             objective coefficient than it can be fixed to zero
1276 	 *
1277 	 *  Note: all dual reduction (ii) could also be performed by the "domcol" presolver, but because the pairwise comparison of
1278 	 *       columns is only done heuristically (and here it should be even cheaper) we perform them here (too).
1279 	 *
1280 	 *  Moreover, if there exists a variable that is only locked by a covering or packing constraint with two variables, one
1281 	 *  can aggregate variables.
1282 	 */
1283 	static
1284 	SCIP_RETCODE dualPresolving(
1285 	   SCIP*                 scip,               /**< SCIP data structure */
1286 	   SCIP_CONS*            cons,               /**< setppc constraint */
1287 	   int*                  nfixedvars,         /**< pointer to count number of fixings */
1288 	   int*                  ndelconss,          /**< pointer to count number of deleted constraints  */
1289 	   int*                  naggrvars,          /**< pointer to count number of variables aggregated */
1290 	   SCIP_RESULT*          result              /**< pointer to store the result SCIP_SUCCESS, if presolving was performed */
1291 	   )
1292 	{
1293 	   SCIP_CONSDATA* consdata;
1294 	   SCIP_SETPPCTYPE setppctype;
1295 	   SCIP_VAR** vars;
1296 	   SCIP_VAR* activevar;
1297 	   SCIP_VAR* var;
1298 	   SCIP_Real bestobjval;
1299 	   SCIP_Real objval;
1300 	   SCIP_Real objsign;
1301 	   SCIP_Real fixval;
1302 	   SCIP_Bool infeasible;
1303 	   SCIP_Bool fixed;
1304 	   SCIP_Bool negated;
1305 	   int noldfixed;
1306 	   int nposfixings;
1307 	   int nlockdowns;
1308 	   int nlockups;
1309 	   int nvars;
1310 	   int indepidx = -1;
1311 	   int idx;
1312 	   int v;
1313 	
1314 	   assert(scip != NULL);
1315 	   assert(cons != NULL);
1316 	   assert(nfixedvars != NULL);
1317 	   assert(ndelconss != NULL);
1318 	   assert(result != NULL);
1319 	
1320 	   /* constraints for which the check flag is set to FALSE, did not contribute to the lock numbers; therefore, we cannot
1321 	    * use the locks to decide for a dual reduction using this constraint; for example after a restart the cuts which are
1322 	    * added to the problems have the check flag set to FALSE
1323 	    */
1324 	   if( !SCIPconsIsChecked(cons) )
1325 	      return SCIP_OKAY;
1326 	
1327 	   assert(SCIPconsIsActive(cons));
1328 	
1329 	   consdata = SCIPconsGetData(cons);
1330 	   assert(consdata != NULL);
1331 	
1332 	   /* modifiable non-covering constraints cannot be deleted if one variable is fixed to one, because the propagation for
1333 	    * newly inserted variables must be considered later
1334 	    */
1335 	   if( consdata->nfixedones == 1 && SCIPconsIsModifiable(cons) )
1336 	      return SCIP_OKAY;
1337 	
1338 	   /* all fixed variables should be removed at that point */
1339 	   assert(consdata->nfixedones == 0);
1340 	   assert(consdata->nfixedzeros == 0);
1341 	
1342 	   nvars = consdata->nvars;
1343 	
1344 	   /* we don't want to consider small constraints (note that the constraints can be modifiable, so we can't delete this
1345 	    * constraint)
1346 	    */
1347 	   if( nvars < 2 )
1348 	      return SCIP_OKAY;
1349 	
1350 	   setppctype = (SCIP_SETPPCTYPE)consdata->setppctype;
1351 	   vars = consdata->vars;
1352 	   idx = -1;
1353 	   bestobjval = SCIP_INVALID;
1354 	
1355 	   /* collect the rounding locks depending on the setppc type */
1356 	   switch( setppctype )
1357 	   {
1358 	   case SCIP_SETPPCTYPE_PARTITIONING:
1359 	      nlockdowns = 1;
1360 	      nlockups = 1;
1361 	      objsign = 0.0;
1362 	      break;
1363 	   case SCIP_SETPPCTYPE_PACKING:
1364 	      nlockdowns = 0;
1365 	      nlockups = 1;
1366 	      objsign = -1.0;
1367 	      break;
1368 	   case SCIP_SETPPCTYPE_COVERING:
1369 	      nlockdowns = 1;
1370 	      nlockups = 0;
1371 	      objsign = 1.0;
1372 	      break;
1373 	   default:
1374 	      SCIPerrorMessage("unknown setppc type\n");
1375 	      SCIPABORT();
1376 	      return SCIP_INVALIDDATA; /*lint !e527*/
1377 	   }
1378 	
1379 	   nposfixings = 0;
1380 	
1381 	   /* check if we can apply the dual reduction; therefore count the number of variables where the setppc has the only
1382 	    * locks on this constraint
1383 	    */
1384 	   for( v = 0; v < nvars; ++v )
1385 	   {
1386 	      var = vars[v];
1387 	      assert(var != NULL);
1388 	
1389 	      /* the variable should not be (globally) fixed */
1390 	      assert(SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5);
1391 	
1392 	      if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlockdowns
1393 	         && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlockups )
1394 	      {
1395 	         activevar = var;
1396 	         negated = FALSE;
1397 	
1398 	         /* get the active variable */
1399 	         SCIP_CALL( SCIPvarGetProbvarBinary(&activevar, &negated) );
1400 	         assert(SCIPvarIsActive(activevar));
1401 	
1402 	         if( negated )
1403 	            objval = -SCIPvarGetObj(activevar);
1404 	         else
1405 	            objval = SCIPvarGetObj(activevar);
1406 	
1407 	         /* check if the current variable has a smaller objective coefficient */
1408 	         if( idx == -1 || objval < bestobjval )
1409 	         {
1410 	            idx = v;
1411 	            bestobjval = objval;
1412 	         }
1413 	
1414 	         /* determine independent variable, i.e., only locked by the current constraint */
1415 	         if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlockdowns )
1416 	         {
1417 	            assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlockups);
1418 	
1419 	            /* store variables that have the right objective sign */
1420 	            if ( objval * objsign >= 0.0 )
1421 	               indepidx = v;
1422 	         }
1423 	      }
1424 	
1425 	      /* in case another constraint has also downlocks on that variable we cannot perform a dual reduction on these
1426 	       * variables
1427 	       */
1428 	      if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlockdowns
1429 	         && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlockups )
1430 	         ++nposfixings;
1431 	   }
1432 	
1433 	   if( idx == -1 || nposfixings == 0 )
1434 	      return SCIP_OKAY;
1435 	
1436 	   SCIPdebugMsg(scip, "dual fixing constraint: \n");
1437 	   SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
1438 	   SCIPdebug( SCIPinfoMessage(scip, NULL, "\n") );
1439 	
1440 	   assert(idx >= 0 && idx < nvars);
1441 	   assert(bestobjval < SCIPinfinity(scip));
1442 	
1443 	   noldfixed = *nfixedvars;
1444 	
1445 	   /* In the special case of two variables, where one variable is independent and will be minimized for covering or
1446 	    * maximized for packing or does not appear in the objective, we can aggregate variables:
1447 	    *  - Covering: var1 + var2 >= 1 and the objective of var1 is non-negative.
1448 	    *  - Packing:  var1 + var2 <= 1 and the objective of var1 is non-positive.
1449 	    * In both cases, var1 + var2 = 1 holds in every optimal solution.
1450 	    */
1451 	   if( setppctype != SCIP_SETPPCTYPE_PARTITIONING && nvars == 2 && indepidx >= 0 )
1452 	   {
1453 	      SCIP_Bool redundant;
1454 	      SCIP_Bool aggregated;
1455 	      int idx2;
1456 	
1457 	      idx2 = 1 - indepidx;
1458 	      assert( 0 <= idx2 && idx2 < 2 );
1459 	
1460 	      SCIP_CALL( SCIPaggregateVars(scip, vars[indepidx], vars[idx2], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
1461 	      assert(!infeasible);
1462 	      assert(redundant);
1463 	      assert(aggregated);
1464 	      ++(*naggrvars);
1465 	
1466 	      /* remove constraint since it is redundant */
1467 	      SCIP_CALL( SCIPdelCons(scip, cons) );
1468 	      ++(*ndelconss);
1469 	
1470 	      *result = SCIP_SUCCESS;
1471 	
1472 	      return SCIP_OKAY;
1473 	   }
1474 	
1475 	   /* in case of set packing and set partitioning we fix the dominated variables to zero */
1476 	   if( setppctype != SCIP_SETPPCTYPE_COVERING )
1477 	   {
1478 	      /* first part of all variables */
1479 	      for( v = nvars - 1; v >= 0; --v )
1480 	      {
1481 	         if( v == idx )
1482 	            continue;
1483 	
1484 	         var = vars[v];
1485 	         assert(var != NULL);
1486 	
1487 	         /* in case another constraint has also downlocks on that variable we cannot perform a dual reduction on these
1488 	          * variables
1489 	          */
1490 	         if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlockdowns
1491 	            && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlockups )
1492 	         {
1493 	            activevar = var;
1494 	            negated = FALSE;
1495 	
1496 	            /* get the active variable */
1497 	            SCIP_CALL( SCIPvarGetProbvarBinary(&activevar, &negated) );
1498 	            assert(SCIPvarIsActive(activevar));
1499 	
1500 	            if( negated )
1501 	               objval = -SCIPvarGetObj(activevar);
1502 	            else
1503 	               objval = SCIPvarGetObj(activevar);
1504 	
1505 	            if( objval >= bestobjval )
1506 	            {
1507 	               SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
1508 	               assert(!infeasible);
1509 	               assert(fixed);
1510 	
1511 	               SCIPdebugMsg(scip, " -> dual-fixed dominated variable <%s> == 0.0\n", SCIPvarGetName(var));
1512 	               ++(*nfixedvars);
1513 	            }
1514 	         }
1515 	      }
1516 	   }
1517 	   /* if we got a set covering constraint and not all variables are locked from this constraint it might not get
1518 	    * redundant (which is case if it is not possible to fix at least one variable to one), we fix all redundant
1519 	    * variables to their best bound
1520 	    */
1521 	   else
1522 	   {
1523 	      /* first part of all variables */
1524 	      for( v = nvars - 1; v >= 0; --v )
1525 	      {
1526 	         if( v == idx )
1527 	            continue;
1528 	
1529 	         var = vars[v];
1530 	         assert(var != NULL);
1531 	
1532 	         /* in case another constraint has also downlocks on that variable we cannot perform a dual reduction on these
1533 	          * variables
1534 	          */
1535 	         if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlockdowns
1536 	            && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlockups )
1537 	         {
1538 	            activevar = var;
1539 	            negated = FALSE;
1540 	
1541 	            /* get the active variable */
1542 	            SCIP_CALL( SCIPvarGetProbvarBinary(&activevar, &negated) );
1543 	            assert(SCIPvarIsActive(activevar));
1544 	            assert(negated
1545 	               || (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == SCIPvarGetNLocksDownType(activevar, SCIP_LOCKTYPE_MODEL)
1546 	                  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == SCIPvarGetNLocksUpType(activevar, SCIP_LOCKTYPE_MODEL)));
1547 	            assert(!negated
1548 	               || (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == SCIPvarGetNLocksUpType(activevar, SCIP_LOCKTYPE_MODEL)
1549 	                  && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == SCIPvarGetNLocksDownType(activevar, SCIP_LOCKTYPE_MODEL)));
1550 	
1551 	            if( negated )
1552 	               objval = -SCIPvarGetObj(activevar);
1553 	            else
1554 	               objval = SCIPvarGetObj(activevar);
1555 	
1556 	            if( objval > 0.0 )
1557 	               fixval = 0.0;
1558 	            else
1559 	               fixval = 1.0;
1560 	
1561 	            /* if variables has a negative objective contribution, and is uplocked by another constraint we cannot fix
1562 	             * the variables to 1
1563 	             */
1564 	            if( (fixval == 1.0 && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) > nlockups) || objval < bestobjval )
1565 	               continue;
1566 	
1567 	            SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
1568 	            assert(!infeasible);
1569 	            assert(fixed);
1570 	
1571 	            SCIPdebugMsg(scip, " -> dual-fixed dominated variable <%s> == %g\n", SCIPvarGetName(var), fixval);
1572 	            ++(*nfixedvars);
1573 	         }
1574 	      }
1575 	   }
1576 	
1577 	   /* if all variables but the domination variable is fixed and the constraint is not modifiable or the constraint is a
1578 	    * covering constraint and the bestobjval is less than or equal to zero, we can fix the domination variable (with best
1579 	    * objective coefficient) and the constraint gets redundant
1580 	    */
1581 	   if( ((*nfixedvars - noldfixed == nvars - 1) && !SCIPconsIsModifiable(cons)) || (setppctype == SCIP_SETPPCTYPE_COVERING && bestobjval <= 0.0) )
1582 	   {
1583 	      /* in case of a set packing constraint with positive objective values, all variables can be fixed to zero; in all
1584 	       * other cases the variable with the smallest objective values is fixed to one
1585 	       */
1586 	      if( (setppctype == SCIP_SETPPCTYPE_PACKING && bestobjval > 0.0
1587 	         && SCIPvarGetNLocksDownType(vars[idx], SCIP_LOCKTYPE_MODEL) == 0)
1588 	         || setppctype != SCIP_SETPPCTYPE_PACKING || bestobjval <= 0.0 )
1589 	      {
1590 	         if( setppctype == SCIP_SETPPCTYPE_PACKING && bestobjval > 0.0 )
1591 	            fixval = 0.0;
1592 	         else
1593 	            fixval = 1.0;
1594 	
1595 	         SCIP_CALL( SCIPfixVar(scip, vars[idx], fixval, &infeasible, &fixed) );
1596 	         assert(!infeasible);
1597 	         assert(fixed);
1598 	
1599 	         SCIPdebugMsg(scip, " -> dual-fixed best variable <%s> == %g\n", SCIPvarGetName(vars[idx]), fixval);
1600 	         ++(*nfixedvars);
1601 	      }
1602 	
1603 	      /* check that we really have a non-violated constraint in hand before deleting */
1604 	      assert((setppctype == SCIP_SETPPCTYPE_PACKING && consdata->nfixedones <= 1) ||
1605 	         (setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata->nfixedones == 1) ||
1606 	         (setppctype == SCIP_SETPPCTYPE_COVERING && consdata->nfixedones >= 1));
1607 	
1608 	      /* remove constraint since it is redundant */
1609 	      SCIP_CALL( SCIPdelCons(scip, cons) );
1610 	      ++(*ndelconss);
1611 	   }
1612 	
1613 	   assert(*nfixedvars >= noldfixed);
1614 	
1615 	   /* set result pointer to SCIP_SUCCESS, if variables could be fixed */
1616 	   if( *nfixedvars != noldfixed )
1617 	      *result = SCIP_SUCCESS;
1618 	
1619 	   return SCIP_OKAY;
1620 	}
1621 	
1622 	/** find pairs of negated variables in constraint:
1623 	 *  partitioning/packing: all other variables must be zero, constraint is redundant
1624 	 *  covering: constraint is redundant
1625 	 *
1626 	 *  find sets of equal variables in constraint:
1627 	 *  partitioning/packing: variable must be zero
1628 	 *  covering: multiple entries of variable can be replaced by single entry
1629 	 */
1630 	static
1631 	SCIP_RETCODE mergeMultiples(
1632 	   SCIP*                 scip,               /**< SCIP data structure */
1633 	   SCIP_CONS*            cons,               /**< knapsack constraint */
1634 	   int*                  nfixedvars,         /**< pointer to store number of fixed variables */
1635 	   int*                  ndelconss,          /**< pointer to store number of deleted constraints */
1636 	   int*                  nchgcoefs,          /**< pointer to store number of changed coefficients */
1637 	   SCIP_Bool*            cutoff              /**< pointer to store whether a fixing leads to a cutoff */
1638 	   )
1639 	{
1640 	   SCIP_CONSDATA* consdata;
1641 	   int v;
1642 	
1643 	   assert(scip != NULL);
1644 	   assert(cons != NULL);
1645 	   assert(nfixedvars != NULL);
1646 	   assert(ndelconss != NULL);
1647 	   assert(nchgcoefs != NULL);
1648 	   assert(cutoff != NULL);
1649 	
1650 	   consdata = SCIPconsGetData(cons);
1651 	   assert(consdata != NULL);
1652 	
1653 	   if( consdata->merged || SCIPconsIsDeleted(cons) )
1654 	      return SCIP_OKAY;
1655 	
1656 	   if( consdata->nvars <= 1 )
1657 	   {
1658 	      consdata->merged = TRUE;
1659 	      return SCIP_OKAY;
1660 	   }
1661 	
1662 	   assert(consdata->vars != NULL || consdata->nvars == 0);
1663 	
1664 	   /* sorting array after indices of variables, that's only for faster merging */
1665 	   SCIPsortPtr((void**)consdata->vars, SCIPvarCompActiveAndNegated, consdata->nvars);
1666 	   /* setppc sorting now lost */
1667 	   consdata->sorted = FALSE;
1668 	
1669 	   /* loop backwards through the items: deletion only affects rear items */
1670 	   for( v = consdata->nvars - 1; v > 0; --v )
1671 	   {
1672 	      SCIP_VAR* var1;
1673 	      SCIP_VAR* var2;
1674 	      SCIP_Bool negated1;
1675 	      SCIP_Bool negated2;
1676 	
1677 	      negated1 = FALSE;
1678 	      negated2 = FALSE;
1679 	
1680 	      var1 = consdata->vars[v];
1681 	      assert(SCIPvarIsBinary(var1));
1682 	      assert(SCIPvarIsActive(var1) || SCIPvarGetStatus(var1) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(var1) == SCIP_VARSTATUS_FIXED);
1683 	      if( SCIPvarGetStatus(var1) == SCIP_VARSTATUS_NEGATED )
1684 	      {
1685 	         var1 = SCIPvarGetNegatedVar(var1);
1686 	         negated1 = TRUE;
1687 	      }
1688 	      assert(var1 != NULL);
1689 	
1690 	      var2 = consdata->vars[v-1];
1691 	      assert(SCIPvarIsBinary(var2));
1692 	      assert(SCIPvarIsActive(var2) || SCIPvarGetStatus(var2) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(var2) == SCIP_VARSTATUS_FIXED);
1693 	      if( SCIPvarGetStatus(var2) == SCIP_VARSTATUS_NEGATED )
1694 	      {
1695 	         var2 = SCIPvarGetNegatedVar(var2);
1696 	         negated2 = TRUE;
1697 	      }
1698 	      assert(var2 != NULL);
1699 	
1700 	      if( var1 == var2 )
1701 	      {
1702 	         SCIP_Bool infeasible;
1703 	         SCIP_Bool fixed;
1704 	
1705 	         /* one variables is active and the other is the same negated variable */
1706 	         if( negated1 != negated2  )
1707 	         {
1708 	            /* all other variable have to be zero if it's a partitioning or packing constraint */
1709 	            if( consdata->setppctype != SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
1710 	            {
1711 	               int i;
1712 	
1713 	               assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
1714 	                  || consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
1715 	
1716 	               for( i = consdata->nvars - 1; i >= 0; --i )
1717 	                  if( i != v && i != (v-1) )
1718 	                  {
1719 	                     SCIP_CALL( SCIPfixVar(scip, consdata->vars[i], 0.0, &infeasible, &fixed) );
1720 	                     if( infeasible )
1721 	                     {
1722 	                        SCIPdebugMsg(scip, "setppc constraint <%s>: infeasible fixing <%s> == 0\n",
1723 	                           SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]));
1724 	                        *cutoff = TRUE;
1725 	                        return SCIP_OKAY;
1726 	                     }
1727 	
1728 	                     if( fixed )
1729 				++(*nfixedvars);
1730 	                  }
1731 	            }
1732 	            /* all setppc-type constraints are redundant */
1733 	            SCIP_CALL( SCIPdelCons(scip, cons) );
1734 	            ++(*ndelconss);
1735 	            return SCIP_OKAY;
1736 	         }
1737 	         /* both variables are either active or negated */
1738 	         else
1739 	         {
1740 	            /* this variable can be fixed to zero if it's a partitioning or packing constraint */
1741 	            if( consdata->setppctype != SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
1742 	            {
1743 	               assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
1744 	                  || consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
1745 	
1746 	               SCIP_CALL( SCIPfixVar(scip, var1, negated1 ? 1.0 : 0.0, &infeasible, &fixed) );
1747 	               if( infeasible )
1748 	               {
1749 	                  SCIPdebugMsg(scip, "setppc constraint <%s>: infeasible fixing <%s> == %g\n",
1750 	                     SCIPconsGetName(cons), SCIPvarGetName(var1), negated1 ? 1.0 : 0.0);
1751 	                  *cutoff = TRUE;
1752 	                  return SCIP_OKAY;
1753 	               }
1754 	
1755 	               if( fixed )
1756 			  ++(*nfixedvars);
1757 	            }
1758 	            /* multiple entries of variable can be replaced by single entry */
1759 	            else
1760 	            {
1761 	               SCIP_CALL( delCoefPos(scip, cons, v) ); /* only some changed behind position v-1, so it's okay */
1762 	               ++(*nchgcoefs);
1763 	            }
1764 	         }
1765 	         consdata->changed = TRUE;
1766 	      }
1767 	   }
1768 	   consdata->merged = TRUE;
1769 	
1770 	   return SCIP_OKAY;
1771 	}
1772 	
1773 	/** deletes all zero-fixed variables and replace aggregated variables */
1774 	static
1775 	SCIP_RETCODE applyFixings(
1776 	   SCIP*                 scip,               /**< SCIP data structure */
1777 	   SCIP_CONS*            cons,               /**< set partitioning / packing / covering constraint */
1778 	   int*                  naddconss,          /**< pointer to count number of added constraints, or NULL indicating we
1779 	                                              *   can not resolve multi-aggregations
1780 	                                              */
1781 	   int*                  ndelconss,          /**< pointer to count number of deleted constraints, or NULL indicating we
1782 	                                              *   can not resolve multi-aggregations
1783 	                                              */
1784 	   int*                  nfixedvars,         /**< pointer to store number of fixed variables, or NULL indicating we can
1785 	                                              *   not resolve multi-aggregations
1786 	                                              */
1787 	   SCIP_Bool*            cutoff              /**< pointer to store whether a fixing leads to a cutoff, or NULL
1788 	                                              *   indicating we can not resolve multi-aggregations
1789 	                                              */
1790 	   )
1791 	{
1792 	   SCIP_CONSDATA* consdata;
1793 	   int v;
1794 	
1795 	   assert(scip != NULL);
1796 	   assert(cons != NULL);
1797 	
1798 	   consdata = SCIPconsGetData(cons);
1799 	   assert(consdata != NULL);
1800 	
1801 	   /* all multi-aggregations should be resolved */
1802 	   consdata->existmultaggr = FALSE;
1803 	
1804 	   v = 0;
1805 	   while( v < consdata->nvars )
1806 	   {
1807 	      SCIP_VAR* var;
1808 	
1809 	      var = consdata->vars[v];
1810 	      assert(SCIPvarIsBinary(var));
1811 	
1812 	      if( SCIPvarGetUbGlobal(var) < 0.5 )
1813 	      {
1814 	         assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), 0.0));
1815 	         SCIP_CALL( delCoefPos(scip, cons, v) );
1816 	      }
1817 	      else
1818 	      {
1819 	         SCIP_VAR* repvar;
1820 	         SCIP_Bool negated;
1821 	
1822 	         /* get binary representative of variable */
1823 	         SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
1824 	
1825 	         /* resolve multi-aggregation */
1826 	         if( SCIPvarGetStatus(repvar) == SCIP_VARSTATUS_MULTAGGR || (SCIPvarGetStatus(repvar) == SCIP_VARSTATUS_NEGATED && SCIPvarGetStatus(SCIPvarGetNegatedVar(repvar)) == SCIP_VARSTATUS_MULTAGGR) )
1827 	         {
1828 	            SCIP_VAR** consvars;
1829 	            SCIP_Real* consvals;
1830 	            SCIP_Real constant = 0.0;
1831 	            SCIP_Bool easycase;
1832 	            int nconsvars;
1833 	            int requiredsize;
1834 	            int v2;
1835 	
1836 	            nconsvars = 1;
1837 	            SCIP_CALL( SCIPallocBufferArray(scip, &consvars, 1) );
1838 	            SCIP_CALL( SCIPallocBufferArray(scip, &consvals, 1) );
1839 	            consvars[0] = repvar;
1840 	            consvals[0] = 1.0;
1841 	
1842 	            /* get active variables for new constraint */
1843 	            SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
1844 	            /* if space was not enough we need to resize the buffers */
1845 	            if( requiredsize > nconsvars )
1846 	            {
1847 	               SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
1848 	               SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
1849 	
1850 	               SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
1851 	               assert(requiredsize <= nconsvars);
1852 	            }
1853 	
1854 	            easycase = FALSE;
1855 	
1856 	            if( SCIPisZero(scip, constant) )
1857 	            {
1858 	               /* add active representation */
1859 	               for( v2 = nconsvars - 1; v2 >= 0; --v2 )
1860 	               {
1861 	                  if( !SCIPvarIsBinary(consvars[v2]) )
1862 	                     break;
1863 	
1864 	                  if( !SCIPisEQ(scip, consvals[v2], 1.0) )
1865 	                     break;
1866 	               }
1867 	
1868 	               if( v2 < 0 )
1869 	                  easycase = TRUE;
1870 	            }
1871 	            else if( SCIPisFeasEQ(scip, constant, 1.0) )
1872 	            {
1873 	               /* check for another multi-aggregation */
1874 	               for( v2 = consdata->nvars - 1; v2 > v; --v2 )
1875 	               {
1876 	                  if( SCIPvarGetStatus(SCIPvarGetProbvar(consdata->vars[v])) == SCIP_VARSTATUS_MULTAGGR )
1877 	                     break;
1878 	               }
1879 	
1880 	               /* constraint is redundant */
1881 	               if( v2 == v && nconsvars == 0 )
1882 	               {
1883 	                  /* we can fix */
1884 	                  if( consdata->nvars > 1 && (SCIP_SETPPCTYPE)consdata->setppctype != SCIP_SETPPCTYPE_COVERING )
1885 	                  {
1886 	                     if( nfixedvars != NULL )
1887 	                     {
1888 	                        SCIP_Bool fixed;
1889 	
1890 	                        assert(cutoff != NULL);
1891 	
1892 	                        for( v2 = consdata->nvars - 1; v2 >= 0; --v2 )
1893 	                        {
1894 	                           if( consdata->vars[v2] != var )
1895 	                           {
1896 	                              SCIPdebugMsg(scip, "trying to fix <%s> to 0 due to at least one variable is already fixed to 1\n", SCIPvarGetName(consdata->vars[v2]));
1897 	
1898 	                              /* fix all remaining variables to zero, constraint is already feasible or infeasible */
1899 	                              SCIP_CALL( SCIPfixVar(scip, consdata->vars[v2], 0.0, cutoff, &fixed) );
1900 	                              if( *cutoff )
1901 	                              {
1902 	                                 SCIPdebugMsg(scip, "setppc constraint <%s>: infeasible fixing <%s> == 0\n",
1903 	                                    SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[v2]));
1904 	
1905 	                                 SCIPfreeBufferArray(scip, &consvals);
1906 	                                 SCIPfreeBufferArray(scip, &consvars);
1907 	
1908 	                                 goto TERMINATE;
1909 	                              }
1910 	
1911 	                              if( fixed )
1912 	                                 ++(*nfixedvars);
1913 	                           }
1914 	                        }
1915 	                     }
1916 	                  }
1917 	
1918 	                  if( ndelconss != NULL && (nfixedvars != NULL || consdata->nvars == 1 || (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING) )
1919 	                  {
1920 	                     /* delete old constraint */
1921 	                     SCIP_CALL( SCIPdelCons(scip, cons) );
1922 	                     ++(*ndelconss);
1923 	                  }
1924 	                  SCIPfreeBufferArray(scip, &consvals);
1925 	                  SCIPfreeBufferArray(scip, &consvars);
1926 	
1927 	                  goto TERMINATE;
1928 	               }
1929 	            }
1930 	
1931 	            /* we can easily add the coefficients and still have a setppc constraint */
1932 	            if( easycase )
1933 	            {
1934 	               /* delete old (multi-aggregated) variable */
1935 	               SCIP_CALL( delCoefPos(scip, cons, v) );
1936 	
1937 	               /* add active representation */
1938 	               for( v2 = nconsvars - 1; v2 >= 0; --v2 )
1939 	               {
1940 	                  assert(SCIPvarIsBinary(consvars[v2]));
1941 	                  assert(SCIPvarIsActive(consvars[v2]) || (SCIPvarGetStatus(consvars[v2]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(consvars[v2]))));
1942 	
1943 	                  SCIP_CALL( addCoef(scip, cons, consvars[v2]) );
1944 	               }
1945 	            }
1946 	            /* we need to degrade this setppc constraint to a linear constraint */
1947 	            else if( (ndelconss != NULL && naddconss != NULL) || SCIPconsIsAdded(cons) )
1948 	            {
1949 	               char name[SCIP_MAXSTRLEN];
1950 	               SCIP_CONS* newcons;
1951 	               SCIP_Real lhs;
1952 	               SCIP_Real rhs;
1953 	               int size;
1954 	               int k;
1955 	
1956 	               /* it might happen that there are more than one multi-aggregated variable, so we need to get the whole
1957 	                * probvar sum over all variables
1958 	                */
1959 	
1960 	               size = MAX(nconsvars, 1) + consdata->nvars - 1;
1961 	
1962 	               /* memory needed is at least old number of variables - 1 + number of variables in first multi-aggregation */
1963 	               SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, size) );
1964 	               SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, size) );
1965 	
1966 	               nconsvars = consdata->nvars;
1967 	
1968 	               /* add constraint variables to new linear variables */
1969 	               for( k = consdata->nvars - 1; k >= 0; --k )
1970 	               {
1971 	                  consvars[k] = consdata->vars[k];
1972 	                  consvals[k] = 1.0;
1973 	               }
1974 	
1975 	               constant = 0.0;
1976 	
1977 	               /* get active variables for new constraint */
1978 	               SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, size, &constant, &requiredsize, TRUE) );
1979 	
1980 	               /* if space was not enough (we found another multi-aggregation), we need to resize the buffers */
1981 	               if( requiredsize > nconsvars )
1982 	               {
1983 	                  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
1984 	                  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
1985 	
1986 	                  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
1987 	                  assert(requiredsize <= nconsvars);
1988 	               }
1989 	
1990 	               /* compute sides */
1991 	               if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
1992 	               {
1993 	                  lhs = -SCIPinfinity(scip);
1994 	                  rhs = 1.0 - constant;
1995 	               }
1996 	               else if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
1997 	               {
1998 	                  lhs = 1.0 - constant;
1999 	                  rhs = 1.0 - constant;
2000 	               }
2001 	               else
2002 	               {
2003 	                  assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING);
2004 	                  lhs = 1.0 - constant;
2005 	                  rhs = SCIPinfinity(scip);
2006 	               }
2007 	
2008 	               /* create linear constraint */
2009 	               (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", SCIPconsGetName(cons));
2010 	               SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, nconsvars, consvars, consvals, lhs, rhs,
2011 	                  SCIPconsIsInitial(cons),
2012 	                  SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
2013 	                  SCIPconsIsPropagated(cons),  SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons),
2014 	                  SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
2015 	               SCIP_CALL( SCIPaddCons(scip, newcons) );
2016 	
2017 	               SCIPdebugMsg(scip, "added linear constraint: ");
2018 	               SCIPdebugPrintCons(scip, newcons, NULL);
2019 	               SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
2020 	
2021 	               SCIPfreeBufferArray(scip, &consvals);
2022 	               SCIPfreeBufferArray(scip, &consvars);
2023 	
2024 	               /* delete old constraint */
2025 	               SCIP_CALL( SCIPdelCons(scip, cons) );
2026 	               if( ndelconss != NULL && naddconss != NULL )
2027 	               {
2028 	                  ++(*ndelconss);
2029 	                  ++(*naddconss);
2030 	               }
2031 	
2032 	               goto TERMINATE;
2033 	            }
2034 	            /* we need to degrade this setppc constraint to a linear constraint*/
2035 	            else
2036 	            {
2037 	               /* check, if the variable should be replaced with the representative */
2038 	               if( repvar != var )
2039 	               {
2040 	                  /* delete old (aggregated) variable */
2041 	                  SCIP_CALL( delCoefPos(scip, cons, v) );
2042 	
2043 	                  /* add representative instead */
2044 	                  SCIP_CALL( addCoef(scip, cons, repvar) );
2045 	               }
2046 	
2047 	               SCIPwarningMessage(scip, "setppc constraint <%s> has a multi-aggregated variable, which was not resolved and therefore could lead to aborts\n", SCIPconsGetName(cons));
2048 	               ++v;
2049 	            }
2050 	
2051 	            SCIPfreeBufferArray(scip, &consvals);
2052 	            SCIPfreeBufferArray(scip, &consvars);
2053 	         }
2054 	         else
2055 	         {
2056 	            /* check, if the variable should be replaced with the representative */
2057 	            if( repvar != var )
2058 	            {
2059 	               /* delete old (aggregated) variable */
2060 	               SCIP_CALL( delCoefPos(scip, cons, v) );
2061 	
2062 	               /* add representative instead */
2063 	               SCIP_CALL( addCoef(scip, cons, repvar) );
2064 	            }
2065 	            else
2066 	               ++v;
2067 	         }
2068 	      }
2069 	   }
2070 	
2071 	 TERMINATE:
2072 	   /* all multi-aggregations should be resolved */
2073 	   consdata->existmultaggr = FALSE;
2074 	
2075 	   return SCIP_OKAY;
2076 	}
2077 	
2078 	/** analyzes conflicting assignment on given constraint where all of the variables where assigned to zero,
2079 	 *  and adds conflict constraint to problem
2080 	 */
2081 	static
2082 	SCIP_RETCODE analyzeConflictZero(
2083 	   SCIP*                 scip,               /**< SCIP data structure */
2084 	   SCIP_CONS*            cons                /**< set partitioning / packing / covering constraint that detected the conflict */
2085 	   )
2086 	{
2087 	   SCIP_CONSDATA* consdata;
2088 	   int v;
2089 	
2090 	   /* conflict analysis can only be applied in solving stage and if it is applicable */
2091 	   if( (SCIPgetStage(scip) != SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) || !SCIPisConflictAnalysisApplicable(scip) )
2092 	      return SCIP_OKAY;
2093 	
2094 	   consdata = SCIPconsGetData(cons);
2095 	   assert(consdata != NULL);
2096 	   assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
2097 	      || consdata->setppctype == SCIP_SETPPCTYPE_COVERING); /*lint !e641*/
2098 	
2099 	   /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
2100 	   SCIP_CALL( SCIPinitConflictAnalysis(scip, SCIP_CONFTYPE_PROPAGATION, FALSE) );
2101 	
2102 	   for( v = 0; v < consdata->nvars; ++v )
2103 	   {
2104 	      SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
2105 	   }
2106 	
2107 	   /* analyze the conflict */
2108 	   SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
2109 	
2110 	   return SCIP_OKAY;
2111 	}
2112 	
2113 	/** analyzes conflicting assignment on given constraint where two of the variables where assigned to one,
2114 	 *  and adds conflict constraint to problem
2115 	 */
2116 	static
2117 	SCIP_RETCODE analyzeConflictOne(
2118 	   SCIP*                 scip,               /**< SCIP data structure */
2119 	   SCIP_CONS*            cons                /**< set partitioning / packing / covering constraint that detected the conflict */
2120 	   )
2121 	{
2122 	   SCIP_CONSDATA* consdata;
2123 	   int v;
2124 	   int n;
2125 	
2126 	   /* conflict analysis can only be applied in solving stage and if it is applicable */
2127 	   if( (SCIPgetStage(scip) != SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) || !SCIPisConflictAnalysisApplicable(scip) )
2128 	      return SCIP_OKAY;
2129 	
2130 	   consdata = SCIPconsGetData(cons);
2131 	   assert(consdata != NULL);
2132 	   assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
2133 	      || consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
2134 	
2135 	   /* initialize conflict analysis, and add the two variables assigned to one to conflict candidate queue */
2136 	   SCIP_CALL( SCIPinitConflictAnalysis(scip, SCIP_CONFTYPE_PROPAGATION, FALSE) );
2137 	
2138 	   n = 0;
2139 	   for( v = 0; v < consdata->nvars && n < 2; ++v )
2140 	   {
2141 	      if( SCIPvarGetLbLocal(consdata->vars[v]) > 0.5 )
2142 	      {
2143 	         SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
2144 	         n++;
2145 	      }
2146 	   }
2147 	   assert(n == 2);
2148 	
2149 	   /* analyze the conflict */
2150 	   SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
2151 	
2152 	   return SCIP_OKAY;
2153 	}
2154 	
2155 	/** checks constraint for violation only looking at the fixed variables, applies further fixings if possible */
2156 	static
2157 	SCIP_RETCODE processFixings(
2158 	   SCIP*                 scip,               /**< SCIP data structure */
2159 	   SCIP_CONS*            cons,               /**< set partitioning / packing / covering constraint to be processed */
2160 	   SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if the node can be cut off */
2161 	   int*                  nfixedvars,         /**< pointer to count number of deleted variables */
2162 	   SCIP_Bool*            addcut,             /**< pointer to store whether this constraint must be added as a cut */
2163 	   SCIP_Bool*            mustcheck           /**< pointer to store whether this constraint must be checked for feasibility */
2164 	   )
2165 	{
2166 	   SCIP_CONSDATA* consdata;
2167 	#ifndef NDEBUG
2168 	   int oldnfixedvars;
2169 	#endif
2170 	
2171 	   assert(cons != NULL);
2172 	   assert(SCIPconsGetHdlr(cons) != NULL);
2173 	   assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
2174 	   assert(cutoff != NULL);
2175 	   assert(nfixedvars != NULL);
2176 	   assert(addcut != NULL);
2177 	   assert(mustcheck != NULL);
2178 	
2179 	#ifndef NDEBUG
2180 	   oldnfixedvars = *nfixedvars;
2181 	#endif
2182 	
2183 	   consdata = SCIPconsGetData(cons);
2184 	   assert(consdata != NULL);
2185 	   assert(consdata->nvars == 0 || consdata->vars != NULL);
2186 	   assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nvars);
2187 	   assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nvars);
2188 	
2189 	   *addcut = FALSE;
2190 	   *mustcheck = TRUE;
2191 	
2192 	   /*SCIPdebugMsg(scip, "processing constraint <%s> with respect to fixed variables (%d fixed to 0.0, %d fixed to 1.0)\n",
2193 	     SCIPconsGetName(cons), consdata->nfixedzeros, consdata->nfixedones);*/
2194 	
2195 	   if( consdata->nfixedones == 1 )
2196 	   {
2197 	      /* exactly one variable is fixed to 1:
2198 	       * - a set covering constraint is feasible anyway and can be disabled
2199 	       * - all other variables in a set partitioning or packing constraint must be zero
2200 	       */
2201 	      if( consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
2202 	      {
2203 	         SCIPdebugMsg(scip, " -> disabling set covering constraint <%s>\n", SCIPconsGetName(cons));
2204 	         SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2205 	      }
2206 	      else
2207 	      {
2208 	         if( consdata->nfixedzeros < consdata->nvars - 1 )
2209 	         {
2210 	            SCIP_VAR** vars;
2211 	            SCIP_VAR* var;
2212 	#ifndef NDEBUG
2213 	            SCIP_Bool fixedonefound;
2214 	#endif
2215 	            SCIP_Bool infeasible;
2216 	            SCIP_Bool tightened;
2217 	            int nvars;
2218 	            int v;
2219 	            int oneidx = -1;
2220 	
2221 	            SCIPdebugMsg(scip, " -> fixing all other variables to zero in set packing/partitioning constraint <%s>\n",
2222 	               SCIPconsGetName(cons));
2223 	
2224 	            /* unfixed variables exist: fix them to zero;
2225 	             * this could result in additional variables fixed to one due to aggregations; in this case, the
2226 	             * constraint is infeasible in local bounds
2227 	             */
2228 	            vars = consdata->vars;
2229 	            nvars = consdata->nvars;
2230 	#ifndef NDEBUG
2231 	            fixedonefound = FALSE;
2232 	#endif
2233 	            for( v = 0; v < nvars && consdata->nfixedones == 1; ++v )
2234 	            {
2235 	               var = vars[v];
2236 	               assert(SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), 1.0));
2237 	               if( SCIPvarGetLbLocal(var) < 0.5 )
2238 	               {
2239 	                  SCIP_CALL( SCIPinferBinvarCons(scip, var, FALSE, cons, oneidx, &infeasible, &tightened) );
2240 	                  assert(!infeasible);
2241 	
2242 	                  if( tightened )
2243 	                     ++(*nfixedvars);
2244 	
2245 	                  SCIPdebugMsg(scip, "   -> fixed <%s> to zero (tightened=%u)\n", SCIPvarGetName(var), tightened);
2246 	               }
2247 	               else
2248 	               {
2249 	#ifndef NDEBUG
2250 	                  fixedonefound = TRUE;
2251 	#endif
2252 	                  oneidx = v;
2253 	               }
2254 	            }
2255 	            /* the fixed to one variable must have been found, and at least one variable must have been fixed */
2256 	            assert(consdata->nfixedones >= 2 || (fixedonefound && *nfixedvars > oldnfixedvars));
2257 	
2258 	            SCIP_CALL( SCIPresetConsAge(scip, cons) );
2259 	         }
2260 	
2261 	         /* now all other variables are fixed to zero:
2262 	          * the constraint is feasible, and if it's not modifiable, it is redundant
2263 	          */
2264 	         if( !SCIPconsIsModifiable(cons) && consdata->nfixedones == 1 )
2265 	         {
2266 	            SCIPdebugMsg(scip, " -> disabling set packing/partitioning constraint <%s>\n", SCIPconsGetName(cons));
2267 	            SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2268 	         }
2269 	      }
2270 	      *mustcheck = FALSE;
2271 	   }
2272 	
2273 	   if( consdata->nfixedones >= 2 )
2274 	   {
2275 	      /* at least two variables are fixed to 1:
2276 	       * - a set covering constraint is feasible anyway and can be disabled
2277 	       * - a set partitioning or packing constraint is infeasible
2278 	       */
2279 	      if( consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
2280 	      {
2281 	         SCIPdebugMsg(scip, " -> disabling set covering constraint <%s>\n", SCIPconsGetName(cons));
2282 	         SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2283 	      }
2284 	      else
2285 	      {
2286 	         SCIPdebugMsg(scip, " -> conflict on set packing/partitioning constraint <%s>\n", SCIPconsGetName(cons));
2287 	
2288 	         SCIP_CALL( SCIPresetConsAge(scip, cons) );
2289 	
2290 	         /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
2291 	         SCIP_CALL( analyzeConflictOne(scip, cons) );
2292 	
2293 	         *cutoff = TRUE;
2294 	      }
2295 	      *mustcheck = FALSE;
2296 	   }
2297 	   else if( consdata->nfixedzeros == consdata->nvars )
2298 	   {
2299 	      /* all variables are fixed to zero:
2300 	       * - a set packing constraint is feasible anyway, and if it's unmodifiable, it can be disabled
2301 	       * - a set partitioning or covering constraint is infeasible, and if it's unmodifiable, the node
2302 	       *   can be cut off -- otherwise, the constraint must be added as a cut and further pricing must
2303 	       *   be performed
2304 	       */
2305 	      assert(consdata->nfixedones == 0);
2306 	
2307 	      if( consdata->setppctype == SCIP_SETPPCTYPE_PACKING ) /*lint !e641*/
2308 	      {
2309 	         if( !SCIPconsIsModifiable(cons) )
2310 	         {
2311 	            SCIPdebugMsg(scip, " -> disabling set packing constraint <%s>\n", SCIPconsGetName(cons));
2312 	            SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2313 	         }
2314 	      }
2315 	      else
2316 	      {
2317 	         SCIPdebugMsg(scip, " -> set covering/partitioning constraint <%s> is infeasible\n", SCIPconsGetName(cons));
2318 	
2319 	         SCIP_CALL( SCIPresetConsAge(scip, cons) );
2320 	         if( SCIPconsIsModifiable(cons) )
2321 	            *addcut = TRUE;
2322 	         else
2323 	         {
2324 	            /* use conflict analysis to get a conflict constraint out of the conflicting assignment */
2325 	            SCIP_CALL( analyzeConflictZero(scip, cons) );
2326 	
2327 	            *cutoff = TRUE;
2328 	         }
2329 	      }
2330 	      *mustcheck = FALSE;
2331 	   }
2332 	   else if( consdata->nfixedzeros == consdata->nvars - 1 && consdata->nfixedones == 0 )
2333 	   {
2334 	      /* all variables except one are fixed to zero:
2335 	       * - a set packing constraint is feasible anyway, and if it's unmodifiable, it can be disabled
2336 	       * - an unmodifiable set partitioning or covering constraint is feasible and can be disabled after the
2337 	       *   remaining variable is fixed to one
2338 	       * - a modifiable set partitioning or covering constraint must be checked manually
2339 	       */
2340 	      if( consdata->setppctype == SCIP_SETPPCTYPE_PACKING ) /*lint !e641*/
2341 	      {
2342 	         if( !SCIPconsIsModifiable(cons) )
2343 	         {
2344 	            SCIPdebugMsg(scip, " -> disabling set packing constraint <%s>\n", SCIPconsGetName(cons));
2345 	            SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2346 	         }
2347 	         *mustcheck = FALSE;
2348 	      }
2349 	      else if( !SCIPconsIsModifiable(cons) )
2350 	      {
2351 	         SCIP_VAR** vars;
2352 	         SCIP_VAR* var;
2353 	         SCIP_Bool infeasible;
2354 	         SCIP_Bool tightened;
2355 	         int nvars;
2356 	         int v;
2357 	
2358 	         /* search the single variable that can be fixed */
2359 	         vars = consdata->vars;
2360 	         nvars = consdata->nvars;
2361 	         for( v = 0; v < nvars; ++v )
2362 	         {
2363 	            var = vars[v];
2364 	            assert(SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)));
2365 	            assert(SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), 1.0));
2366 	            if( SCIPvarGetUbLocal(var) > 0.5 )
2367 	            {
2368 	               SCIPdebugMsg(scip, " -> fixing remaining variable <%s> to one in set covering/partitioning constraint <%s>\n",
2369 	                  SCIPvarGetName(var), SCIPconsGetName(cons));
2370 	               SCIP_CALL( SCIPinferBinvarCons(scip, var, TRUE, cons, 0, &infeasible, &tightened) );
2371 	               assert(!infeasible);
2372 	               assert(tightened);
2373 	
2374 	               ++(*nfixedvars);
2375 	               break;
2376 	            }
2377 	         }
2378 	         assert(v < nvars);
2379 	         assert(consdata->nfixedzeros == consdata->nvars - 1);
2380 	         assert(consdata->nfixedones == 1);
2381 	
2382 	         SCIP_CALL( SCIPdelConsLocal(scip, cons) );
2383 	         *mustcheck = FALSE;
2384 	      }
2385 	   }
2386 	   assert(consdata->nfixedzeros + consdata->nfixedones <= consdata->nvars);
2387 	
2388 	   return SCIP_OKAY;
2389 	}
2390 	
2391 	/** checks constraint for violation, returns TRUE iff constraint is feasible */
2392 	static
2393 	SCIP_Bool checkCons(
2394 	   SCIP*                 scip,               /**< SCIP data structure */
2395 	   SCIP_CONSDATA*        consdata,           /**< set partitioning / packing / covering constraint to be checked */
2396 	   SCIP_SOL*             sol                 /**< primal CIP solution */
2397 	   )
2398 	{
2399 	   SCIP_VAR** vars;
2400 	   SCIP_Real solval;
2401 	   SCIP_Real sum;
2402 	   SCIP_Real sumbound;
2403 	   SCIP_Real absviol;
2404 	   SCIP_Real relviol;
2405 	   SCIP_Bool check;
2406 	   int nvars;
2407 	   int v;
2408 	
2409 	   /* calculate the constraint's activity */
2410 	   vars = consdata->vars;
2411 	   nvars = consdata->nvars;
2412 	   sum = 0.0;
2413 	   sumbound = ((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING ? 1.0 : 1.0 + 2*SCIPfeastol(scip));
2414 	   for( v = 0; v < nvars && sum < sumbound; ++v )  /* if sum >= sumbound, the feasibility is clearly decided */
2415 	   {
2416 	      assert(SCIPvarIsBinary(vars[v]));
2417 	
2418 	      solval = SCIPgetSolVal(scip, sol, vars[v]);
2419 	      assert(SCIPisFeasGE(scip, solval, 0.0) && SCIPisFeasLE(scip, solval, 1.0));
2420 	
2421 	      sum += solval;
2422 	   }
2423 	
2424 	   absviol = sum - 1.0;
2425 	   relviol = SCIPrelDiff(sum, 1.0);
2426 	   switch( consdata->setppctype )
2427 	   {
2428 	   case SCIP_SETPPCTYPE_PARTITIONING:
2429 	      /* in case of partitioning, the violation is equal to the absolute difference between sum and 1 */
2430 	      absviol = REALABS(absviol);
2431 	      relviol = REALABS(relviol);
2432 	      check = SCIPisFeasEQ(scip, sum, 1.0);
2433 	      break;
2434 	   case SCIP_SETPPCTYPE_PACKING:
2435 	      /* in case of packing, the violation is equal to how much sum exceeds 1 */
2436 	      check = SCIPisFeasLE(scip, sum, 1.0);
2437 	      break;
2438 	   case SCIP_SETPPCTYPE_COVERING:
2439 	      /* in case of covering, the violation is equal to how much 1 exceeds sum */
2440 	      absviol = -absviol;
2441 	      relviol = -relviol;
2442 	      check = SCIPisFeasGE(scip, sum, 1.0);
2443 	      break;
2444 	   default:
2445 	      SCIPerrorMessage("unknown setppc type\n");
2446 	      SCIPABORT();
2447 	      return FALSE; /*lint !e527*/
2448 	   }
2449 	
2450 	   if( sol != NULL )
2451 	      SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
2452 	
2453 	   return check;
2454 	}
2455 	
2456 	/** creates an LP row in a set partitioning / packing / covering constraint data object */
2457 	static
2458 	SCIP_RETCODE createRow(
2459 	   SCIP*                 scip,               /**< SCIP data structure */
2460 	   SCIP_CONS*            cons                /**< set partitioning / packing / covering constraint */
2461 	   )
2462 	{
2463 	   SCIP_CONSDATA* consdata;
2464 	   SCIP_Real lhs;
2465 	   SCIP_Real rhs;
2466 	
2467 	   consdata = SCIPconsGetData(cons);
2468 	   assert(consdata != NULL);
2469 	   assert(consdata->row == NULL);
2470 	
2471 	   switch( consdata->setppctype )
2472 	   {
2473 	   case SCIP_SETPPCTYPE_PARTITIONING:
2474 	      lhs = 1.0;
2475 	      rhs = 1.0;
2476 	      break;
2477 	   case SCIP_SETPPCTYPE_PACKING:
2478 	      lhs = -SCIPinfinity(scip);
2479 	      rhs = 1.0;
2480 	      break;
2481 	   case SCIP_SETPPCTYPE_COVERING:
2482 	      lhs = 1.0;
2483 	      rhs = SCIPinfinity(scip);
2484 	      break;
2485 	   default:
2486 	      SCIPerrorMessage("unknown setppc type\n");
2487 	      return SCIP_INVALIDDATA;
2488 	   }
2489 	
2490 	   SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), lhs, rhs,
2491 	         SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsRemovable(cons)) );
2492 	
2493 	   SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row, consdata->nvars, consdata->vars, 1.0) );
2494 	
2495 	   return SCIP_OKAY;
2496 	}
2497 	
2498 	/** adds setppc constraint as cut to the LP */
2499 	static
2500 	SCIP_RETCODE addCut(
2501 	   SCIP*                 scip,               /**< SCIP data structure */
2502 	   SCIP_CONS*            cons,               /**< setppc constraint */
2503 	   SCIP_Bool*            cutoff              /**< whether a cutoff has been detected */
2504 	   )
2505 	{
2506 	   SCIP_CONSDATA* consdata;
2507 	
2508 	   assert( cutoff != NULL );
2509 	   *cutoff = FALSE;
2510 	
2511 	   consdata = SCIPconsGetData(cons);
2512 	   assert(consdata != NULL);
2513 	
2514 	   if( consdata->row == NULL )
2515 	   {
2516 	      /* convert set partitioning constraint data into LP row */
2517 	      SCIP_CALL( createRow(scip, cons) );
2518 	   }
2519 	   assert(consdata->row != NULL);
2520 	
2521 	   /* insert LP row as cut */
2522 	   if( !SCIProwIsInLP(consdata->row) )
2523 	   {
2524 	      SCIPdebugMsg(scip, "adding constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
2525 	      SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
2526 	   }
2527 	
2528 	   return SCIP_OKAY;
2529 	}
2530 	
2531 	/** adds setppc constraint as row to the NLP, if not added yet */
2532 	static
2533 	SCIP_RETCODE addNlrow(
2534 	   SCIP*                 scip,               /**< SCIP data structure */
2535 	   SCIP_CONS*            cons                /**< setppc constraint */
2536 	   )
2537 	{
2538 	   SCIP_CONSDATA* consdata;
2539 	
2540 	   assert(SCIPisNLPConstructed(scip));
2541 	
2542 	   /* skip deactivated, redundant, or local constraints (the NLP does not allow for local rows at the moment) */
2543 	   if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
2544 	      return SCIP_OKAY;
2545 	
2546 	   consdata = SCIPconsGetData(cons);
2547 	   assert(consdata != NULL);
2548 	
2549 	   if( consdata->nlrow == NULL )
2550 	   {
2551 	      SCIP_Real lhs, rhs;
2552 	      SCIP_Real* coefs;
2553 	      int i;
2554 	
2555 	      SCIP_CALL( SCIPallocBufferArray(scip, &coefs, consdata->nvars) );
2556 	      for( i = 0; i < consdata->nvars; ++i )
2557 	         coefs[i] = 1.0;
2558 	
2559 	      switch( SCIPgetTypeSetppc(scip, cons) )
2560 	      {
2561 	      case SCIP_SETPPCTYPE_PARTITIONING:
2562 	         lhs = 1.0;
2563 	         rhs = 1.0;
2564 	         break;
2565 	
2566 	      case SCIP_SETPPCTYPE_PACKING:
2567 	         lhs = -SCIPinfinity(scip);
2568 	         rhs = 1.0;
2569 	         break;
2570 	
2571 	      case SCIP_SETPPCTYPE_COVERING:
2572 	         lhs = 1.0;
2573 	         rhs = SCIPinfinity(scip);
2574 	         break;
2575 	
2576 	      default:
2577 	         SCIPerrorMessage("unexpected setppc type\n");
2578 	         return SCIP_ERROR;
2579 	      }
2580 	
2581 	      SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons),
2582 	         0.0, consdata->nvars, consdata->vars, coefs, NULL, lhs, rhs, SCIP_EXPRCURV_LINEAR) );
2583 	      assert(consdata->nlrow != NULL);
2584 	
2585 	      SCIPfreeBufferArray(scip, &coefs);
2586 	   }
2587 	
2588 	   if( !SCIPnlrowIsInNLP(consdata->nlrow) )
2589 	   {
2590 	      SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
2591 	   }
2592 	
2593 	   return SCIP_OKAY;
2594 	}
2595 	
2596 	/** checks constraint for violation, and adds it as a cut if possible */
2597 	static
2598 	SCIP_RETCODE separateCons(
2599 	   SCIP*                 scip,               /**< SCIP data structure */
2600 	   SCIP_CONS*            cons,               /**< set partitioning / packing / covering constraint to be separated */
2601 	   SCIP_SOL*             sol,                /**< primal CIP solution, NULL for current LP solution */
2602 	   SCIP_Bool             lpfeas,             /**< is the given solution feasible for the current LP ? */
2603 	   SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if the node can be cut off */
2604 	   SCIP_Bool*            separated,          /**< pointer to store TRUE, if a cut was found */
2605 	   SCIP_Bool*            reduceddom          /**< pointer to store TRUE, if a domain reduction was found */
2606 	   )
2607 	{
2608 	   SCIP_CONSDATA* consdata;
2609 	   SCIP_Bool addcut;
2610 	   SCIP_Bool mustcheck;
2611 	
2612 	   assert(cons != NULL);
2613 	   assert(SCIPconsGetHdlr(cons) != NULL);
2614 	   assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
2615 	   assert(cutoff != NULL);
2616 	   assert(separated != NULL);
2617 	   assert(reduceddom != NULL);
2618 	
2619 	   *cutoff = FALSE;
2620 	
2621 	   consdata = SCIPconsGetData(cons);
2622 	   assert(consdata != NULL);
2623 	   assert(consdata->nvars == 0 || consdata->vars != NULL);
2624 	   assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nvars);
2625 	   assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nvars);
2626 	
2627 	   /* skip constraints already in the LP */
2628 	   if( lpfeas && consdata->row != NULL && SCIProwIsInLP(consdata->row) )
2629 	      return SCIP_OKAY;
2630 	
2631 	   SCIPdebugMsg(scip, "separating constraint <%s>\n", SCIPconsGetName(cons));
2632 	
2633 	   /* check constraint for violation only looking at the fixed variables, apply further fixings if possible */
2634 	   if( lpfeas )
2635 	   {
2636 	      int nfixedvars = 0;
2637 	
2638 	      SCIP_CALL( processFixings(scip, cons, cutoff, &nfixedvars, &addcut, &mustcheck) );
2639 	
2640 	      *reduceddom = (nfixedvars > 0);
2641 	   }
2642 	   else
2643 	   {
2644 	      mustcheck = TRUE;
2645 	      addcut = FALSE;
2646 	   }
2647 	
2648 	   if( mustcheck )
2649 	   {
2650 	      assert(!addcut);
2651 	
2652 	      /* variable's fixings didn't give us any information -> we have to check the constraint */
2653 	      if( lpfeas && consdata->row != NULL )
2654 	      {
2655 	         SCIP_Real feasibility;
2656 	
2657 	         assert(!SCIProwIsInLP(consdata->row));
2658 	         feasibility = SCIPgetRowSolFeasibility(scip, consdata->row, sol);
2659 	         addcut = SCIPisFeasNegative(scip, feasibility);
2660 	      }
2661 	      else
2662 	         addcut = !checkCons(scip, consdata, sol);
2663 	
2664 	      if( !addcut )
2665 	      {
2666 	         /* constraint was feasible -> increase age */
2667 	         SCIP_CALL( SCIPincConsAge(scip, cons) );
2668 	      }
2669 	   }
2670 	
2671 	   if( addcut )
2672 	   {
2673 	      /* insert LP row as cut */
2674 	      SCIP_CALL( addCut(scip, cons, cutoff) );
2675 	      SCIP_CALL( SCIPresetConsAge(scip, cons) );
2676 	      *separated = TRUE;
2677 	   }
2678 	
2679 	   return SCIP_OKAY;
2680 	}
2681 	
2682 	/** enforces the pseudo solution on the given constraint */
2683 	static
2684 	SCIP_RETCODE enforcePseudo(
2685 	   SCIP*                 scip,               /**< SCIP data structure */
2686 	   SCIP_CONS*            cons,               /**< set partitioning / packing / covering constraint to be separated */
2687 	   SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if the node can be cut off */
2688 	   SCIP_Bool*            infeasible,         /**< pointer to store TRUE, if the constraint was infeasible */
2689 	   SCIP_Bool*            reduceddom,         /**< pointer to store TRUE, if a domain reduction was found */
2690 	   SCIP_Bool*            solvelp             /**< pointer to store TRUE, if the LP has to be solved */
2691 	   )
2692 	{
2693 	   SCIP_Bool addcut;
2694 	   SCIP_Bool mustcheck;
2695 	   int nfixedvars = 0;
2696 	
2697 	   assert(!SCIPhasCurrentNodeLP(scip));
2698 	   assert(cons != NULL);
2699 	   assert(SCIPconsGetHdlr(cons) != NULL);
2700 	   assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
2701 	   assert(cutoff != NULL);
2702 	   assert(infeasible != NULL);
2703 	   assert(reduceddom != NULL);
2704 	   assert(solvelp != NULL);
2705 	
2706 	   /* check constraint for violation only looking at the fixed variables, apply further fixings if possible */
2707 	   SCIP_CALL( processFixings(scip, cons, cutoff, &nfixedvars, &addcut, &mustcheck) );
2708 	
2709 	   *reduceddom = (nfixedvars > 0);
2710 	
2711 	   if( mustcheck )
2712 	   {
2713 	      SCIP_CONSDATA* consdata;
2714 	
2715 	      assert(!addcut);
2716 	
2717 	      consdata = SCIPconsGetData(cons);
2718 	      assert(consdata != NULL);
2719 	
2720 	      if( checkCons(scip, consdata, NULL) )
2721 	      {
2722 	         /* constraint was feasible -> increase age */
2723 	         SCIP_CALL( SCIPincConsAge(scip, cons) );
2724 	      }
2725 	      else
2726 	      {
2727 	         /* constraint was infeasible -> reset age */
2728 	         SCIP_CALL( SCIPresetConsAge(scip, cons) );
2729 	         *infeasible = TRUE;
2730 	      }
2731 	   }
2732 	
2733 	   if( addcut )
2734 	   {
2735 	      /* a cut must be added to the LP -> we have to solve the LP immediately */
2736 	      SCIP_CALL( SCIPresetConsAge(scip, cons) );
2737 	      *solvelp = TRUE;
2738 	   }
2739 	
2740 	   return SCIP_OKAY;
2741 	}
2742 	
2743 	/** gets the key of the given element */
2744 	static
2745 	SCIP_DECL_HASHGETKEY(hashGetKeySetppccons)
2746 	{  /*lint --e{715}*/
2747 	   /* the key is the element itself */
2748 	   return elem;
2749 	}
2750 	
2751 	/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
2752 	static
2753 	SCIP_DECL_HASHKEYEQ(hashKeyEqSetppccons)
2754 	{
2755 	#ifndef NDEBUG
2756 	   SCIP* scip;
2757 	#endif
2758 	   SCIP_CONSDATA* consdata1;
2759 	   SCIP_CONSDATA* consdata2;
2760 	   SCIP_Bool coefsequal;
2761 	   int i;
2762 	
2763 	   consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
2764 	   consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
2765 	   assert(consdata1->sorted);
2766 	   assert(consdata2->sorted);
2767 	#ifndef NDEBUG
2768 	   scip = (SCIP*)userptr;
2769 	   assert(scip != NULL);
2770 	#endif
2771 	
2772 	   /* checks trivial case */
2773 	   if( consdata1->nvars != consdata2->nvars )
2774 	      return FALSE;
2775 	
2776 	   coefsequal = TRUE;
2777 	
2778 	   for( i = 0; i < consdata1->nvars; ++i )
2779 	   {
2780 	      /* tests if variables are equal */
2781 	      if( consdata1->vars[i] != consdata2->vars[i] )
2782 	      {
2783 	         assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
2784 	            SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
2785 	         coefsequal = FALSE;
2786 	         break;
2787 	      }
2788 	      assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
2789 	   }
2790 	
2791 	   return coefsequal;
2792 	}
2793 	
2794 	/** returns the hash value of the key */
2795 	static
2796 	SCIP_DECL_HASHKEYVAL(hashKeyValSetppccons)
2797 	{
2798 	   SCIP_CONSDATA* consdata;
2799 	   int minidx;
2800 	   int mididx;
2801 	   int maxidx;
2802 	#ifndef NDEBUG
2803 	   SCIP* scip;
2804 	
2805 	   scip = (SCIP*)userptr;
2806 	   assert(scip != NULL);
2807 	#endif
2808 	
2809 	   consdata = SCIPconsGetData((SCIP_CONS*)key);
2810 	   assert(consdata != NULL);
2811 	   assert(consdata->nvars > 0);
2812 	
2813 	   /* sorts the constraints */
2814 	   consdataSort(consdata);
2815 	
2816 	   minidx = SCIPvarGetIndex(consdata->vars[0]);
2817 	   mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
2818 	   maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
2819 	   assert(minidx >= 0 && minidx <= maxidx);
2820 	
2821 	   return SCIPhashFour(consdata->nvars, minidx, mididx, maxidx);
2822 	}
2823 	
2824 	/** add extra clique-constraints resulting from a given cliquepartition to SCIP */
2825 	static
2826 	SCIP_RETCODE addExtraCliques(
2827 	   SCIP*const            scip,               /**< SCIP data structure */
2828 	   SCIP_VAR**const       binvars,            /**< binary variables to create clique constraints */
2829 	   int const             nbinvars,           /**< number of binary variables to create clique constraints */
2830 	   int*const             cliquepartition,    /**< clique partition of binary variables */
2831 	   int const             ncliques,           /**< number of cliques in cliquepartition */
2832 	   SCIP_CONS**const      usefulconss,        /**< storage for created constraints */
2833 	   int*const             nusefulconss,       /**< pointer to store number of useful created constraints */
2834 	   int const             nrounds,            /**< actual presolving round */
2835 	   int*const             nfixedvars,         /**< pointer to count number of deleted variables */
2836 	   int*const             naddconss,          /**< pointer to count number of added constraints */
2837 	   int*const             ndelconss,          /**< pointer to count number of deleted constraints */
2838 	   int*const             nchgcoefs,          /**< pointer to count number of deleted coefficients */
2839 	   SCIP_Bool*const       cutoff              /**< pointer to store if the problem is infeasible due to a fixing */
2840 	   )
2841 	{
2842 	   SCIP_CONS* cliquecons;
2843 	   char name[SCIP_MAXSTRLEN];
2844 	   int lastclqidx;
2845 	   int nadded;
2846 	   int c;
2847 	   int v;
2848 	
2849 	   assert(scip != NULL);
2850 	   assert(binvars != NULL || nbinvars == 0);
2851 	   assert(cliquepartition != NULL || nbinvars == 0);
2852 	   assert(ncliques >= 0 && ncliques <= nbinvars);
2853 	   assert(usefulconss != NULL);
2854 	   assert(nusefulconss != NULL);
2855 	   assert(nfixedvars != NULL);
2856 	   assert(naddconss != NULL);
2857 	   assert(ndelconss != NULL);
2858 	   assert(nchgcoefs != NULL);
2859 	   assert(cutoff != NULL);
2860 	
2861 	   /* no given binary variables */
2862 	   if( nbinvars == 0 || ncliques == 0 )
2863 	      return SCIP_OKAY;
2864 	
2865 	   assert(binvars != NULL);
2866 	   assert(cliquepartition != NULL);
2867 	
2868 	   /* no useful clique information */
2869 	   if( ncliques == nbinvars )
2870 	      return SCIP_OKAY;
2871 	
2872 	   lastclqidx = 0;
2873 	
2874 	   /* @todo: maybe sort cliques and accordingly the variables so it will be faster to add the constraints */
2875 	   for( c = 0; c < ncliques - 1; ++c )
2876 	   {
2877 	      if( lastclqidx >= cliquepartition[c] )
2878 		 continue;
2879 	
2880 	      nadded = 0;
2881 	
2882 	      /* name the clique constraint */
2883 	      (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "extra_clq_%d_round_%d", cliquepartition[c], nrounds);
2884 	      SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, 0, NULL,
2885 		    TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
2886 	
2887 	      /* add variables to clique constraint */
2888 	      for( v = c; v < nbinvars - 1; ++v )
2889 	      {
2890 		 if( cliquepartition[c] == cliquepartition[v] )
2891 		 {
2892 		    SCIP_CALL( addCoef(scip, cliquecons, binvars[v]) );
2893 		    ++nadded;
2894 		 }
2895 	      }
2896 	
2897 	      /* @todo: try to find a good value for what are enough variables to create this constraint, maybe at least
2898 	       *        (nmaxvars(over all conss)-nminvars(over all conss))/2 */
2899 	      if( nadded >= 2 )
2900 	      {
2901 		 SCIP_CONSDATA* cliqueconsdata;
2902 	
2903 		 SCIPdebugMsg(scip, " -> adding clique constraint: ");
2904 		 SCIPdebugPrintCons(scip, cliquecons, NULL);
2905 		 SCIP_CALL( SCIPaddCons(scip, cliquecons) );
2906 		 ++(*naddconss);
2907 	
2908 		 /* we only want to consider merged constraints */
2909 		 SCIP_CALL( mergeMultiples(scip, cliquecons, nfixedvars, ndelconss, nchgcoefs, cutoff) );
2910 		 if( *cutoff )
2911 		 {
2912 		    SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
2913 	
2914 		    return SCIP_OKAY;
2915 		 }
2916 	
2917 		 cliqueconsdata = SCIPconsGetData(cliquecons);
2918 		 assert(cliqueconsdata != NULL);
2919 	
2920 		 /* the artificial constraints could be deleted while merging */
2921 		 if( !SCIPconsIsDeleted(cliquecons) && nadded - cliqueconsdata->nfixedzeros >= 2 )
2922 		 {
2923 		    assert(cliqueconsdata->nfixedones == 0);
2924 	
2925 		    /* save the type and constraint */
2926 		    usefulconss[*nusefulconss] = cliquecons;
2927 		    ++(*nusefulconss);
2928 		 }
2929 		 SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
2930 	      }
2931 	      else
2932 	      {
2933 		 SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
2934 	      }
2935 	      lastclqidx = cliquepartition[c];
2936 	   }
2937 	
2938 	   return SCIP_OKAY;
2939 	}
2940 	
2941 	
2942 	/** start to collect setpartitioning and setpacking constraints, and try to remove fixed variables and merged these
2943 	 *  constraints
2944 	 */
2945 	static
2946 	SCIP_RETCODE collectCliqueConss(
2947 	   SCIP*const            scip,               /**< SCIP data structure */
2948 	   SCIP_CONS**const      conss,              /**< constraint set */
2949 	   int const             nconss,             /**< number of constraints in constraint set */
2950 	   SCIP_CONS**const      usefulconss,        /**< storage for created constraints */
2951 	   int*const             nusefulconss,       /**< pointer to store number of useful created constraints */
2952 	   int*const             nfixedvars,         /**< pointer to count number of deleted variables */
2953 	   int*const             ndelconss,          /**< pointer to count number of deleted constraints */
2954 	   int*const             nchgcoefs,          /**< pointer to count number of deleted coefficients */
2955 	   SCIP_Bool*const       cutoff              /**< pointer to store if the problem is infeasible due to a fixing */
2956 	   )
2957 	{
2958 	   SCIP_CONS* cons;
2959 	   SCIP_CONSDATA* consdata;
2960 	   SCIP_Bool addcut;
2961 	   SCIP_Bool mustcheck;
2962 	   int nlocaladdconss = 0;
2963 	   int c;
2964 	
2965 	   assert(scip != NULL);
2966 	   assert(conss != NULL || nconss == 0);
2967 	   assert(usefulconss != NULL);
2968 	   assert(nusefulconss != NULL);
2969 	   assert(nfixedvars != NULL);
2970 	   assert(ndelconss != NULL);
2971 	   assert(nchgcoefs != NULL);
2972 	   assert(cutoff != NULL);
2973 	
2974 	   if( nconss == 0 )
2975 	      return SCIP_OKAY;
2976 	
2977 	   assert(conss != NULL);
2978 	
2979 	   for( c = nconss - 1; c >= 0; --c )
2980 	   {
2981 	      cons = conss[c];
2982 	
2983 	      /* we only want to consider constraints with either active or negated of active variables, applyfixings removes
2984 	       * aggregated and fixed variables to zero, processFixings removes fixings to one but no aggregation
2985 	       *
2986 	       * @todo: maybe write a new method for deleting aggregations and all fixings
2987 	       */
2988 	      SCIP_CALL( applyFixings(scip, cons, &nlocaladdconss, ndelconss, nfixedvars, cutoff) );
2989 	      if( *cutoff )
2990 	         return SCIP_OKAY;
2991 	
2992 	      if( SCIPconsIsDeleted(cons) )
2993 	      {
2994 	         /* reset nlocaladdconss and continue */
2995 	         nlocaladdconss = 0;
2996 	         continue;
2997 	      }
2998 	      assert(nlocaladdconss == 0);
2999 	
3000 	      SCIP_CALL( processFixings(scip, cons, cutoff, nfixedvars, &addcut, &mustcheck) );
3001 	      if( *cutoff )
3002 	         return SCIP_OKAY;
3003 	
3004 	      consdata = SCIPconsGetData(cons);
3005 	      assert(consdata != NULL);
3006 	
3007 	      /* we only want to consider merged constraints */
3008 	      SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, cutoff) );
3009 	      if( *cutoff )
3010 	         return SCIP_OKAY;
3011 	
3012 	      if( SCIPconsIsModifiable(cons) || !SCIPconsIsActive(cons) )
3013 	         continue;
3014 	
3015 	      assert(consdata->nfixedones == 0);
3016 	
3017 	      if( consdata->nvars == 0 )
3018 	         continue;
3019 	
3020 	      /* @todo: check for covering constraints with only two variables which are equal to a packing constraint with
3021 	       * negated variables */
3022 	      if( consdata->setppctype != SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3023 	      {
3024 	         assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
3025 	
3026 	         usefulconss[*nusefulconss] = cons;
3027 	         ++(*nusefulconss);
3028 	      }
3029 	   }
3030 	
3031 	   return SCIP_OKAY;  /*lint !e438*/
3032 	}
3033 	
3034 	/** creating all necessary data in array structure, collect all clique constraint variables and occurrences,
3035 	 *  @note works only with merged and active not set-covering constraints
3036 	 */
3037 	static
3038 	SCIP_RETCODE collectCliqueData(
3039 	   SCIP*const            scip,               /**< SCIP data structure */
3040 	   SCIP_CONS**const      usefulconss,        /**< clique constraints */
3041 	   int const             nusefulconss,       /**< number of clique constraints */
3042 	   SCIP_VAR**const       usefulvars,         /**< storage for all found variables */
3043 	   int*const             nusefulvars,        /**< pointer to store number of added variables */
3044 	   SCIP_HASHMAP*const    vartoindex,         /**< hashmap mapping variables to indices */
3045 	   int*const             varnconss,          /**< storage for remembering the number of constraints a variable occurs */
3046 	   int*const             maxnvarconsidx,     /**< storage for the maximal number of occurrences of a variable */
3047 	   int**const            varconsidxs,        /**< storage for constraint indices in which the corresponding variable exists */
3048 	   int*const             maxnvars            /**< pointer to store maximal number of variables of a constraint */
3049 	   )
3050 	{
3051 	   SCIP_CONS* cons;
3052 	   SCIP_CONSDATA* consdata;
3053 	   int varindex;
3054 	   int c;
3055 	   int v;
3056 	
3057 	   assert(scip != NULL);
3058 	   assert(usefulconss != NULL || nusefulconss == 0);
3059 	   assert(usefulvars != NULL);
3060 	   assert(nusefulvars != NULL);
3061 	   assert(vartoindex != NULL);
3062 	   assert(varnconss != NULL);
3063 	   assert(maxnvarconsidx != NULL);
3064 	   assert(varconsidxs != NULL);
3065 	   assert(maxnvars != NULL);
3066 	
3067 	   if( nusefulconss == 0 )
3068 	      return SCIP_OKAY;
3069 	
3070 	   assert(usefulconss != NULL);
3071 	
3072 	   for( c = nusefulconss - 1; c >= 0; --c )
3073 	   {
3074 	      cons = usefulconss[c];
3075 	
3076 	      assert(SCIPconsIsActive(cons));
3077 	
3078 	      consdata = SCIPconsGetData(cons);
3079 	      assert(consdata != NULL);
3080 	
3081 	      /* here we should have no covering constraints anymore and the constraint data should be merged */
3082 	      assert(consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
3083 	      assert(consdata->merged);
3084 	
3085 	      /* save maximal number of vars */
3086 	      if( consdata->nvars > *maxnvars )
3087 	         *maxnvars = consdata->nvars;
3088 	
3089 	      /* adding variables and information about occurrences to local data structure */
3090 	      for( v = consdata->nvars - 1; v >= 0; --v )
3091 	      {
3092 	         SCIP_VAR* var;
3093 	
3094 	         var = consdata->vars[v];
3095 	         assert(var != NULL);
3096 	
3097 	         /* don't remember fixed vars */
3098 	         if( SCIPvarGetLbLocal(var) > 0.5 || SCIPvarGetUbLocal(var) < 0.5 )
3099 	            continue;
3100 	
3101 		 /* only collect active or negated active variables */
3102 		 assert(SCIPvarIsActive(var) || (SCIPvarIsNegated(var) && SCIPvarIsActive(SCIPvarGetNegationVar(var))));
3103 	
3104 	         if( !SCIPhashmapExists(vartoindex, (void*) var) )
3105 	         {
3106 	            SCIP_VAR* tmpvar;
3107 	
3108 	            usefulvars[*nusefulvars] = var;
3109 	            ++(*nusefulvars);
3110 	            varindex = *nusefulvars;
3111 	            SCIP_CALL( SCIPhashmapInsertInt(vartoindex, (void*) var, varindex) );
3112 	
3113 	            /* get the maximal number of occurrences of this variable, if this variables  */
3114 	            tmpvar = SCIPvarIsNegated(var) ? SCIPvarGetNegatedVar(var) : var;
3115 	            maxnvarconsidx[varindex] = SCIPvarGetNLocksDownType(tmpvar, SCIP_LOCKTYPE_MODEL)
3116 	               + SCIPvarGetNLocksUpType(tmpvar, SCIP_LOCKTYPE_MODEL);
3117 	            SCIP_CALL( SCIPallocBufferArray(scip, &(varconsidxs[varindex]), maxnvarconsidx[varindex]) );  /*lint !e866*/
3118 	         }
3119 	         else
3120 	         {
3121 	            assert(SCIPhashmapExists(vartoindex, (void*) var));
3122 	            varindex = SCIPhashmapGetImageInt(vartoindex, (void*) var);
3123 	         }
3124 	
3125 	         /* the number of occurrences of a variable is not limited by the locks (so maybe we have to increase memory),
3126 	          * because for examples converted cuts are not check and therefore they have no locks on their variables */
3127 	         if( varnconss[varindex] == maxnvarconsidx[varindex] )
3128 	         {
3129 	            maxnvarconsidx[varindex] = SCIPcalcMemGrowSize(scip, maxnvarconsidx[varindex] + 1);
3130 	            SCIP_CALL( SCIPreallocBufferArray(scip, &(varconsidxs[varindex]), maxnvarconsidx[varindex]) ); /*lint !e866*/
3131 	         }
3132 	
3133 	         assert(varnconss[varindex] < maxnvarconsidx[varindex]);
3134 	         /* add the constraint number to the variable list */
3135 	         varconsidxs[varindex][varnconss[varindex]] = c;
3136 	         /* increase number of occurrences for variables */
3137 	         ++(varnconss[varindex]);
3138 	      }
3139 	   } /* data structure created */
3140 	
3141 	   return SCIP_OKAY;
3142 	}
3143 	
3144 	/** correct clique data due to an aggregation */
3145 	static
3146 	void deleteCliqueDataEntry(
3147 	   SCIP_VAR*const        var,                /**< variable which appears less */
3148 	   int const             considx,            /**< constraint index which to remove */
3149 	   SCIP_HASHMAP*const    vartoindex,         /**< hashmap mapping variables to indices */
3150 	   int*const             varnconss,          /**< storage for remembering the number of constraints a variable occurs */
3151 	   int**const            varconsidxs         /**< storage for constraint indices in which the corresponding variable exists */
3152 	   )
3153 	{
3154 	   int varindex;
3155 	   int i;
3156 	#ifndef NDEBUG
3157 	   SCIP_Bool found = FALSE;
3158 	#endif
3159 	
3160 	   assert(var != NULL);
3161 	   assert(SCIPvarGetLbLocal(var) < 0.5 && SCIPvarGetUbLocal(var) > 0.5);
3162 	   assert(considx >= 0);
3163 	   assert(vartoindex != NULL);
3164 	   assert(varnconss != NULL);
3165 	   assert(varconsidxs != NULL);
3166 	
3167 	   assert(SCIPhashmapExists(vartoindex, (void*) var));
3168 	   varindex = SCIPhashmapGetImageInt(vartoindex, (void*) var);
3169 	
3170 	   /* remove entry of variable at the given position */
3171 	   for( i = 0; i < varnconss[varindex]; ++i )
3172 	   {
3173 	      if( varconsidxs[varindex][i] == considx )
3174 	      {
3175 		 varconsidxs[varindex][i] = varconsidxs[varindex][varnconss[varindex] - 1];
3176 	#ifndef NDEBUG
3177 		 found = TRUE;
3178 	#endif
3179 		 --(varnconss[varindex]);
3180 		 break;
3181 	      }
3182 	   }
3183 	   assert(found);
3184 	}
3185 	
3186 	/* correct local data structure, add constraint entry to variable data  */
3187 	static
3188 	SCIP_RETCODE addCliqueDataEntry(
3189 	   SCIP*const            scip,               /**< SCIP data structure */
3190 	   SCIP_VAR*const        addvar,             /**< variable which was added */
3191 	   int const             considx,            /**< constraint index which to add */
3192 	   SCIP_Bool const       maybenew,           /**< could be a new variables, a negated of an already existing */
3193 	   SCIP_VAR**const       usefulvars,         /**< storage for all found variables */
3194 	   int*const             nusefulvars,        /**< pointer to store number of added variables */
3195 	   SCIP_HASHMAP*const    vartoindex,         /**< hashmap mapping variables to indices */
3196 	   int*const             varnconss,          /**< storage for remembering the number of constraints a variable occurs */
3197 	   int*const             maxnvarconsidx,     /**< storage for the maximal number of occurrences of a variable */
3198 	   int**const            varconsidxs         /**< storage for constraint indices in which the corresponding variable exists */
3199 	   )
3200 	{
3201 	   int varindex;
3202 	
3203 	   assert(scip != NULL);
3204 	   assert(addvar != NULL);
3205 	   assert(SCIPvarGetLbLocal(addvar) < 0.5 && SCIPvarGetUbLocal(addvar) > 0.5);
3206 	   assert(usefulvars != NULL);
3207 	   assert(nusefulvars != NULL);
3208 	   assert(vartoindex != NULL);
3209 	   assert(varnconss != NULL);
3210 	   assert(maxnvarconsidx != NULL);
3211 	   assert(varconsidxs != NULL);
3212 	
3213 	   /* we add the variable to the hashmap if its new */
3214 	   if( maybenew && !SCIPhashmapExists(vartoindex, (void*) addvar) )
3215 	   {
3216 	      assert(SCIPvarIsActive(addvar) || SCIPvarIsNegated(addvar));
3217 	      assert(SCIPvarGetNegatedVar(addvar) != NULL && SCIPhashmapExists(vartoindex, (void*) SCIPvarGetNegatedVar(addvar)));
3218 	
3219 	      /* @note because we can only have created a negated variable, and we already allocated enough memory for
3220 	       * all (even not existing) negated variables the usefulvars array should be big enough
3221 	       */
3222 	      SCIPsortedvecInsertDownPtr((void**)usefulvars, SCIPvarCompActiveAndNegated, addvar, nusefulvars, NULL);
3223 	      varindex = *nusefulvars;
3224 	      SCIP_CALL( SCIPhashmapInsertInt(vartoindex, (void*) addvar, varindex) );
3225 	
3226 	      assert(varconsidxs[varindex] == NULL);
3227 	
3228 	      maxnvarconsidx[varindex] = 1;
3229 	      SCIP_CALL( SCIPallocBufferArray(scip, &(varconsidxs[varindex]), maxnvarconsidx[varindex]) ); /*lint !e866*/
3230 	      varnconss[varindex] = 0;
3231 	   }
3232 	   else
3233 	   {
3234 	      varindex = SCIPhashmapGetImageInt(vartoindex, (void*) addvar);
3235 	
3236 	      /* grow the needed memory if we added a variable */
3237 	      if( varnconss[varindex] == maxnvarconsidx[varindex] )
3238 	      {
3239 		 maxnvarconsidx[varindex] = SCIPcalcMemGrowSize(scip, maxnvarconsidx[varindex] + 1);
3240 		 SCIP_CALL( SCIPreallocBufferArray(scip, &(varconsidxs[varindex]), maxnvarconsidx[varindex]) ); /*lint !e866*/
3241 	      }
3242 	   }
3243 	   assert(varnconss[varindex] < maxnvarconsidx[varindex]);
3244 	   varconsidxs[varindex][varnconss[varindex]] = considx;
3245 	
3246 	   /* increase number of occurrences for variables */
3247 	   ++(varnconss[varindex]);
3248 	
3249 	   return SCIP_OKAY;
3250 	}
3251 	
3252 	
3253 	/** check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
3254 	 *  possible
3255 	 */
3256 	static
3257 	SCIP_RETCODE presolvePropagateCons(
3258 	   SCIP*const            scip,               /**< SCIP data structure */
3259 	   SCIP_CONS*const       cons,               /**< constraint */
3260 	   SCIP_Bool const       aggregate,          /**< try to aggregate if possible */
3261 	   SCIP_VAR**            undoneaggrvars,     /**< array to store aggregation variables, if aggregation is not performed
3262 						      *   yet; both variables are standing next to each other; or NULL if
3263 						      *   aggregate == TRUE
3264 						      */
3265 	   SCIP_Bool*            undoneaggrtypes,    /**< array to store aggregation type, if aggregation is not performed yet;
3266 						      *   type FALSE means the aggregation is of the form x + y = 1; type TRUE means
3267 						      *   the aggregation is of the form x = y; or NULL if aggregate == TRUE
3268 						      */
3269 	   int*const             naggregations,      /**< pointer to store number of aggregations which are not yet performed;
3270 						      *   or NULL if aggregate == TRUE
3271 						      */
3272 	   int*const             saggregations,      /**< pointer to store size of the array for aggregation type and two times
3273 						      *   the value is the size of the array for the aggregation variables which
3274 						      *   are not yet performed; or NULL if aggregate == TRUE
3275 						      */
3276 	   int*const             nfixedvars,         /**< pointer to count number of deleted variables */
3277 	   int*const             naggrvars,          /**< pointer to count number of aggregated variables */
3278 	   int*const             ndelconss,          /**< pointer to count number of deleted constraints */
3279 	   SCIP_Bool*const       cutoff              /**< pointer to store if the problem is infeasible due to a fixing */
3280 	   )
3281 	{
3282 	   SCIP_CONSDATA* consdata;
3283 	   SCIP_VAR** vars;
3284 	   int nvars;
3285 	   int v;
3286 	   SCIP_Bool fixed;
3287 	
3288 	   assert(scip != NULL);
3289 	   assert(cons != NULL);
3290 	   assert(nfixedvars != NULL);
3291 	   assert(naggrvars != NULL);
3292 	   assert(ndelconss != NULL);
3293 	   assert(cutoff != NULL);
3294 	
3295 	   if( !SCIPconsIsActive(cons) )
3296 	      return SCIP_OKAY;
3297 	
3298 	   consdata = SCIPconsGetData(cons);
3299 	   assert(consdata != NULL);
3300 	
3301 	   if( consdata->presolpropagated )
3302 	      return SCIP_OKAY;
3303 	
3304 	   consdata->presolpropagated = TRUE;
3305 	
3306 	   vars = consdata->vars;
3307 	   nvars = consdata->nvars;
3308 	
3309 	   /* no variables left */
3310 	   if( nvars == 0 && !SCIPconsIsModifiable(cons) )
3311 	   {
3312 	      if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3313 	      {
3314 		 SCIPdebugMsg(scip, "empty set-partition/-covering constraint <%s> found -> cutoff\n", SCIPconsGetName(cons));
3315 		 *cutoff = TRUE;
3316 	
3317 		 return SCIP_OKAY;
3318 	      }
3319 	      else
3320 	      {
3321 		 assert(consdata->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
3322 	
3323 		 /* delete constraint */
3324 		 SCIPdebugMsg(scip, " -> deleting constraint <%s>, no variables left\n", SCIPconsGetName(cons));
3325 		 SCIP_CALL( SCIPdelCons(scip, cons) );
3326 		 ++(*ndelconss);
3327 	
3328 		 return SCIP_OKAY;
3329 	      }
3330 	   }
3331 	
3332 	   /* more then two variables are fixed */
3333 	   if( consdata->nfixedones > 1 )
3334 	   {
3335 	      /* at least two variables are fixed to 1:
3336 	       * - a set covering constraint is feasible anyway and can be deleted
3337 	       * - a set partitioning or packing constraint is infeasible
3338 	       */
3339 	      if( consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3340 	      {
3341 		 /* delete constraint */
3342 		 SCIPdebugMsg(scip, " -> deleting set-covering constraint <%s>, at least two variables are fixed to 1\n", SCIPconsGetName(cons));
3343 		 SCIP_CALL( SCIPdelCons(scip, cons) );
3344 		 ++(*ndelconss);
3345 	
3346 		 return SCIP_OKAY;
3347 	      }
3348 	
3349 	      SCIPdebugMsg(scip, "set partitioning / packing constraint <%s> is infeasible, %d variables fixed to one\n", SCIPconsGetName(cons), consdata->nfixedones);
3350 	      *cutoff = TRUE;
3351 	
3352 	      return SCIP_OKAY;
3353 	   }
3354 	
3355 	   if( consdata->nfixedones == 1 )
3356 	   {
3357 	      /* exactly one variable is fixed to 1:
3358 	       * - a set covering constraint is feasible anyway and can be disabled
3359 	       * - all other variables in a set partitioning or packing constraint must be zero
3360 	       */
3361 	      if( consdata->setppctype != SCIP_SETPPCTYPE_COVERING && consdata->nfixedzeros < nvars - 1 ) /*lint !e641*/
3362 	      {
3363 	         assert(vars != NULL);
3364 	
3365 		 for( v = nvars - 1; v >= 0; --v )
3366 		 {
3367 		    if( SCIPvarGetLbLocal(vars[v]) + 0.5 < SCIPvarGetUbLocal(vars[v]) )
3368 		    {
3369 		       SCIPdebugMsg(scip, "trying to fix <%s> to 0 due to at least one variable is already fixed to 1\n", SCIPvarGetName(vars[v]));
3370 	
3371 		       /* fix all remaining variables to zero, constraint is already feasible or infeasible */
3372 		       SCIP_CALL( SCIPfixVar(scip, vars[v], 0.0, cutoff, &fixed) );
3373 		       if( *cutoff )
3374 		       {
3375 			  SCIPdebugMsg(scip, "setppc constraint <%s>: infeasible fixing <%s> == 0\n",
3376 			     SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
3377 	
3378 			  return SCIP_OKAY;
3379 		       }
3380 	
3381 		       assert(fixed);
3382 		       ++(*nfixedvars);
3383 		    }
3384 		 }
3385 	      }
3386 	
3387 	      if( !SCIPconsIsModifiable(cons) || consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3388 	      {
3389 		 /* delete constraint */
3390 		 SCIPdebugMsg(scip, " -> deleting constraint <%s>, all variables are fixed\n", SCIPconsGetName(cons));
3391 		 assert(SCIPconsIsActive(cons));
3392 		 SCIP_CALL( SCIPdelCons(scip, cons) );
3393 		 ++(*ndelconss);
3394 	      }
3395 	
3396 	      return SCIP_OKAY;
3397 	   }
3398 	
3399 	   /* other propagations can only be done on not modifiable constraints */
3400 	   if( SCIPconsIsModifiable(cons) )
3401 	      return SCIP_OKAY;
3402 	
3403 	   assert(vars != NULL);
3404 	
3405 	   /* all variables were fixed to zero then either delete the constraint or stop with infeasibility */
3406 	   if( consdata->nfixedzeros == nvars )
3407 	   {
3408 	      assert(consdata->nfixedones == 0);
3409 	
3410 	      /* all variables are fixed to zero:
3411 	       * - a set packing constraint is feasible anyway and can be deleted
3412 	       * - a set partitioning or covering constraint is infeasible, and so is the whole problem
3413 	       */
3414 	      if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3415 	      {
3416 		 SCIPdebugMsg(scip, "set partitioning / covering constraint <%s> is infeasible\n", SCIPconsGetName(cons));
3417 		 *cutoff = TRUE;
3418 	
3419 		 return SCIP_OKAY;
3420 	      }
3421 	
3422 	      /* delete constraint */
3423 	      SCIPdebugMsg(scip, " -> deleting set-packing constraint <%s>, all variables are fixed to zero\n", SCIPconsGetName(cons));
3424 	      assert(SCIPconsIsActive(cons));
3425 	      SCIP_CALL( SCIPdelCons(scip, cons) );
3426 	      ++(*ndelconss);
3427 	
3428 	      return SCIP_OKAY;
3429 	   }
3430 	
3431 	   /* all but one variable were fixed to zero then delete the constraint and for setpartition fix the remaining variable to 1 */
3432 	   if( consdata->nfixedzeros + 1 == nvars )
3433 	   {
3434 	      assert(consdata->nfixedones == 0);
3435 	
3436 	      /* all variables except one are fixed to zero:
3437 	       * - a set packing constraint is feasible anyway, and can be deleted
3438 	       * - a set partitioning or covering constraint is feasible and can be deleted after the
3439 	       *   remaining variable is fixed to one
3440 	       */
3441 	      if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || consdata->setppctype == SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
3442 	      {
3443 		 fixed = FALSE;
3444 		 for( v = nvars - 1; v >= 0; --v )
3445 		 {
3446 		    assert(SCIPvarGetLbLocal(vars[v]) < 0.5);
3447 		    if( SCIPvarGetUbLocal(vars[v]) > 0.5 )
3448 		    {
3449 		       SCIPdebugMsg(scip, "trying to fix <%s> to 1 due to it's the last unfixed variable is the set-partitioning/covering constraint\n", SCIPvarGetName(vars[v]));
3450 	
3451 		       /* fix the remaining set partition variable */
3452 		       SCIP_CALL( SCIPfixVar(scip, vars[v], 1.0, cutoff, &fixed) );
3453 		       if( *cutoff )
3454 		       {
3455 	                  SCIPdebugMsg(scip, "setppc constraint <%s>: infeasible fixing <%s> == 1\n",
3456 	                     SCIPconsGetName(cons), SCIPvarGetName(vars[v]));
3457 	
3458 			  return SCIP_OKAY;
3459 		       }
3460 	
3461 		       assert(fixed);
3462 		       ++(*nfixedvars);
3463 		       break;
3464 		    }
3465 		 }
3466 		 assert(fixed);
3467 	      }
3468 	
3469 	      /* delete constraint */
3470 	      SCIPdebugMsg(scip, " -> deleting constraint <%s>, all %svariables are fixed\n", SCIPconsGetName(cons), consdata->setppctype == (int) SCIP_SETPPCTYPE_PACKING ? "but one " : "");
3471 	      assert(SCIPconsIsActive(cons));
3472 	      SCIP_CALL( SCIPdelCons(scip, cons) );
3473 	      ++(*ndelconss);
3474 	
3475 	      return SCIP_OKAY;
3476 	   }
3477 	
3478 	   /* all but two variable were fixed to zero in a setpartitioning constraint then delete the constraint and
3479 	    * aggregate the remaining two variables
3480 	    */
3481 	   if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata->nfixedzeros + 2 == nvars ) /*lint !e641*/
3482 	   {
3483 	      SCIP_VAR* var;
3484 	
3485 	      var = NULL;
3486 	      for( v = nvars - 1; v >= 0; --v )
3487 	      {
3488 		 assert(SCIPvarGetLbLocal(vars[v]) < 0.5);
3489 	
3490 		 if( SCIPvarGetUbLocal(vars[v]) > 0.5 )
3491 		 {
3492 		    if( var == NULL )
3493 		       var = vars[v];
3494 		    else
3495 		    {
3496 		       SCIP_Bool redundant;
3497 		       SCIP_Bool aggregated;
3498 	#ifdef VARUSES
3499 		       SCIP_CONSHDLR* conshdlr;
3500 		       SCIP_CONSHDLRDATA* conshdlrdata;
3501 	
3502 		       /* get event handler and event handler data */
3503 		       conshdlr = SCIPconsGetHdlr(cons);
3504 		       assert(conshdlr != NULL);
3505 		       conshdlrdata = SCIPconshdlrGetData(conshdlr);
3506 		       assert(conshdlrdata != NULL);
3507 	#endif
3508 		       if( aggregate )
3509 		       {
3510 			  SCIPdebugMsg(scip, "trying to aggregate <%s> and <%s> due to they are the last two unfixed variables in the set partitionning constraint <%s>\n", SCIPvarGetName(var), SCIPvarGetName(vars[v]), SCIPconsGetName(cons));
3511 	
3512 	#ifdef VARUSES
3513 			  /* in order to not mess up the variable usage counting, we have to decrease usage counting, aggregate,
3514 			   * and increase usage counting again
3515 			   */
3516 			  SCIP_CALL( conshdlrdataDecVaruses(scip, conshdlrdata, var) );
3517 			  SCIP_CALL( conshdlrdataDecVaruses(scip, conshdlrdata, vars[v]) );
3518 	#endif
3519 	
3520 			  /* aggregate last remaining variables in the set partitioning constraint */
3521 			  SCIP_CALL( SCIPaggregateVars(scip, var, vars[v], 1.0, 1.0, 1.0, cutoff, &redundant, &aggregated) );
3522 			  if( *cutoff )
3523 			  {
3524 			     SCIPdebugMsg(scip, "set partitioning constraint <%s>: aggregate <%s> + <%s> == 1\n",
3525 				SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(vars[v]));
3526 	
3527 			     return SCIP_OKAY;
3528 			  }
3529 	
3530 	#ifdef VARUSES
3531 			  /* increase variable usage counting again */
3532 			  SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, var) );
3533 			  SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, vars[v]) );
3534 	#endif
3535 	
3536 			  if( aggregated )
3537 			     ++(*naggrvars);
3538 	
3539 			  if( redundant )
3540 			  {
3541 			     /* delete constraint */
3542 			     SCIPdebugMsg(scip, " -> deleting constraint <%s>, all variables are fixed\n", SCIPconsGetName(cons));
3543 			     assert(SCIPconsIsActive(cons));
3544 			     SCIP_CALL( SCIPdelCons(scip, cons) );
3545 			     ++(*ndelconss);
3546 			  }
3547 		       }
3548 		       else
3549 		       {
3550 			  assert(undoneaggrvars != NULL);
3551 			  assert(undoneaggrtypes != NULL);
3552 			  assert(naggregations != NULL);
3553 			  assert(saggregations != NULL);
3554 	
3555 			  SCIPdebugMsg(scip, "memorize the aggregation of <%s> + <%s> = 1, because they are the last two unfixed variable in the set partitioning constraints <%s>\n", SCIPvarGetName(var), SCIPvarGetName(vars[v]), SCIPconsGetName(cons));
3556 	
3557 			  /* resize the aggregation arrays if necessary */
3558 			  if( *saggregations == *naggregations )
3559 			  {
3560 			     *saggregations = SCIPcalcMemGrowSize(scip, *naggregations + 1);
3561 			     assert(*saggregations > *naggregations);
3562 			     SCIP_CALL( SCIPreallocBufferArray(scip, &undoneaggrtypes, *saggregations) );
3563 			     SCIP_CALL( SCIPreallocBufferArray(scip, &undoneaggrvars, 2 * (*saggregations)) );
3564 	
3565 			     /* clear the aggregation type array to set the default to the aggregation of the form x + y = 1 */
3566 			     BMSclearMemoryArray(&(undoneaggrtypes[*naggregations]), *saggregations - *naggregations); /*lint !e866*/
3567 			  }
3568 	
3569 			  /* memorize aggregation variables*/
3570 			  assert(undoneaggrtypes[*naggregations] == FALSE);
3571 			  undoneaggrvars[2 * (*naggregations)] = var;
3572 			  undoneaggrvars[2 * (*naggregations) + 1] = vars[v];
3573 			  ++(*naggregations);
3574 	
3575 			  if( !SCIPdoNotAggr(scip) )
3576 			  {
3577 			     /* delete constraint */
3578 			     SCIPdebugMsg(scip, " -> deleting constraint <%s>, all variables are fixed\n", SCIPconsGetName(cons));
3579 			     assert(SCIPconsIsActive(cons));
3580 			     SCIP_CALL( SCIPdelCons(scip, cons) );
3581 			     ++(*ndelconss);
3582 			  }
3583 		       }
3584 	
3585 		       return SCIP_OKAY;
3586 		    }
3587 		 }
3588 	      }
3589 	      /* we should never be here, because the last to unfixed variables should have been either aggregated or a cutoff
3590 	       * should be applied
3591 	       */
3592 	      assert(FALSE); /*lint !e506*/
3593 	   }
3594 	
3595 	   return SCIP_OKAY;
3596 	}
3597 	
3598 	/** check for overlapping constraint */
3599 	static
3600 	SCIP_RETCODE checkForOverlapping(
3601 	   SCIP*const            scip,               /**< SCIP data structure */
3602 	   SCIP_CONS*const       cons,               /**< constraint which may overlap */
3603 	   int const             considx,            /**< constraint index to avoid checking against itself */
3604 	   int const             endidx,             /**< end index to check against given constraint */
3605 	   SCIP_CONS**const      usefulconss,        /**< clique constraints */
3606 	   int const             nusefulconss,       /**< number of clique constraints */
3607 	   SCIP_VAR**const       usefulvars,         /**< storage for all found variables */
3608 	   int*const             nusefulvars,        /**< pointer to store number of added variables */
3609 	   SCIP_HASHMAP*const    vartoindex,         /**< hashmap mapping variables to indices */
3610 	   int*const             varnconss,          /**< storage for remembering the number of constraints a variable occurs */
3611 	   int*const             maxnvarconsidx,     /**< storage for the maximal number of occurrences of a variable */
3612 	   int**const            varconsidxs,        /**< storage for constraint indices in which the corresponding variable exists */
3613 	   int*const             countofoverlapping, /**< the amount of variables of cons which overlap in all other constraint */
3614 	   SCIP_Bool const       shrinking,          /**< try to replace some variables with one variable */
3615 	   SCIP_Bool*const       chgcons,            /**< pointer to store if the given constraint was changed, due to
3616 						      *   added/deleted variables
3617 						      */
3618 	   SCIP_VAR**            undoneaggrvars,     /**< array to store aggregation variables, if aggregation is not performed
3619 						      *   yet; both variables are standing next to each other;
3620 						      */
3621 	   SCIP_Bool*            undoneaggrtypes,    /**< array to store aggregation type, if aggregation is not performed yet;
3622 						      *   type FALSE means the aggregation is of the form x + y = 1; type TRUE means
3623 						      *   the aggregation is of the form x = y;
3624 						      */
3625 	   int*const             naggregations,      /**< pointer to store number of aggregations which are not yet performed; */
3626 	   int*const             saggregations,      /**< pointer to store size of the array for aggregation type and two times
3627 						      *   the value is the size of the array for the aggregation variables which
3628 						      *   are not yet performed;
3629 						      */
3630 	   int*const             nfixedvars,         /**< pointer to count number of deleted variables */
3631 	   int*const             naggrvars,          /**< pointer to count number of aggregated variables */
3632 	   int*const             nchgcoefs,          /**< pointer to count number of changed coefficients */
3633 	   int*const             ndelconss,          /**< pointer to count number of deleted constraints */
3634 	   SCIP_Bool*const       cutoff              /**< pointer to store if the problem is infeasible due to a fixing */
3635 	   )
3636 	{
3637 	   SCIP_CONS* cons1;
3638 	   SCIP_CONSDATA* consdata1;
3639 	   SCIP_CONSDATA* consdata;
3640 	   SCIP_VAR** vars;
3641 	   SCIP_VAR** vars1;
3642 	   SCIP_VAR* var;
3643 	   SCIP_VAR* var1;
3644 	   SCIP_Bool fixed;
3645 	   SCIP_Bool overlapdestroyed;
3646 	   int nvars;
3647 	   int nvars1;
3648 	   int oldnfixedzeros;
3649 	   int c;
3650 	   int v;
3651 	   int v1;
3652 	#ifndef NDEBUG
3653 	   int oldnaggrvars;
3654 	#endif
3655 	
3656 	   assert(scip != NULL);
3657 	   assert(cons != NULL);
3658 	   assert(usefulconss != NULL && nusefulconss > 0);
3659 	   assert(0 <= considx && considx < nusefulconss);
3660 	   assert(usefulconss[considx] == cons);
3661 	   assert(0 <= endidx && endidx <= nusefulconss);
3662 	   assert(countofoverlapping != NULL);
3663 	   assert(chgcons != NULL);
3664 	   assert(undoneaggrvars != NULL);
3665 	   assert(undoneaggrtypes != NULL);
3666 	   assert(naggregations != NULL);
3667 	   assert(saggregations != NULL);
3668 	   assert(nfixedvars != NULL);
3669 	   assert(naggrvars != NULL);
3670 	   assert(nchgcoefs != NULL);
3671 	   assert(ndelconss != NULL);
3672 	   assert(cutoff != NULL);
3673 	
3674 	   if( !SCIPconsIsActive(cons) )
3675 	      return SCIP_OKAY;
3676 	
3677 	   consdata = SCIPconsGetData(cons);
3678 	   assert(consdata != NULL);
3679 	
3680 	   nvars = consdata->nvars;
3681 	
3682 	   if( nvars == 0 )
3683 	      return SCIP_OKAY;
3684 	
3685 	   vars = consdata->vars;
3686 	   assert(vars != NULL);
3687 	
3688 	   oldnfixedzeros = consdata->nfixedzeros;
3689 	   overlapdestroyed = FALSE;
3690 	
3691 	   /* first check for redundancy for all unprocessed constraints with cons */
3692 	   for( c = endidx - 1; c >= 0; --c )
3693 	   {
3694 	      cons1 = usefulconss[c];
3695 	
3696 	      if( !SCIPconsIsActive(cons1) )
3697 		 continue;
3698 	
3699 	      /* avoid checking constraint against itself */
3700 	      if( considx == c )
3701 		 continue;
3702 	
3703 	      assert(usefulconss[c] != cons);
3704 	
3705 	#ifndef NDEBUG
3706 	      oldnaggrvars = *naggrvars;
3707 	#endif
3708 	
3709 	      /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
3710 	       * possible
3711 	       */
3712 	      SCIP_CALL( presolvePropagateCons(scip, cons1, FALSE, undoneaggrvars, undoneaggrtypes, naggregations, saggregations, nfixedvars, naggrvars, ndelconss, cutoff) );
3713 	
3714 	      if( *cutoff )
3715 		 return SCIP_OKAY;
3716 	
3717 	      /* we can't handle aggregated variables later on so we should have saved them for later */
3718 	      assert(*naggrvars == oldnaggrvars);
3719 	
3720 	      if( !SCIPconsIsActive(cons1) )
3721 		 continue;
3722 	
3723 	      consdata1 = SCIPconsGetData(cons1);
3724 	      assert(consdata1 != NULL);
3725 	
3726 	      nvars1 = consdata1->nvars;
3727 	
3728 	      if( nvars1 == 0 )
3729 		 continue;
3730 	
3731 	      /* no more variables from cons as nvars1 can overlap */
3732 	      assert(countofoverlapping[c] <= nvars1);
3733 	
3734 	      /* constraint should not be redundant or infeasible */
3735 	      assert(consdata1->nfixedones == 0);
3736 	
3737 	      SCIPdebugMsg(scip, "constraint <%s> overlaps with constraint <%s> by %d variables\n", SCIPconsGetName(cons), SCIPconsGetName(cons1), countofoverlapping[c]);
3738 	
3739 	      /* cons1 includes cons */
3740 	      if( !overlapdestroyed && countofoverlapping[c] == nvars - consdata->nfixedzeros )
3741 	      {
3742 		 if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
3743 		 {
3744 		    if( nvars - consdata->nfixedzeros < nvars1 )
3745 		    {
3746 	#ifndef NDEBUG
3747 		       SCIP_Bool negated0;
3748 		       SCIP_Bool negated1;
3749 	#endif
3750 	
3751 		       /* both constraints should stay merged */
3752 		       assert(consdata->merged);
3753 		       assert(consdata1->merged);
3754 	
3755 		       vars1 = consdata1->vars;
3756 		       assert(vars1 != NULL);
3757 	
3758 		       /* sorting array after indices of variables, negated and active counterparts would stand side by side */
3759 		       SCIPsortDownPtr((void**)vars1, SCIPvarCompActiveAndNegated, nvars1);
3760 		       /* standard setppc-sorting now lost */
3761 		       consdata1->sorted = FALSE;
3762 	
3763 		       /* iterate over the both cliques variables the "same" time */
3764 		       for( v = nvars - 1, v1 = nvars1 - 1; v >= 0 && v1 >= 0; )
3765 		       {
3766 			  if( SCIPvarGetLbLocal(vars1[v1]) > 0.5 || SCIPvarGetUbLocal(vars1[v1]) < 0.5 )
3767 			  {
3768 			     --v1;
3769 			     continue;
3770 			  }
3771 			  if( SCIPvarGetLbLocal(vars[v]) > 0.5 || SCIPvarGetUbLocal(vars[v]) < 0.5 )
3772 			  {
3773 			     --v;
3774 			     continue;
3775 			  }
3776 	
3777 			  /* all variables inside the second clique constraint should be either active or negated of an active one */
3778 			  assert(SCIPvarIsActive(vars1[v1]) || (SCIPvarGetStatus(vars1[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars1[v1]))));
3779 	
3780 			  /* get not negated variable and clique value in cons */
3781 			  if( SCIPvarGetStatus(vars[v]) != SCIP_VARSTATUS_NEGATED )
3782 			  {
3783 			     var = vars[v];
3784 	#ifndef NDEBUG
3785 			     negated0 = FALSE;
3786 	#endif
3787 			  }
3788 			  else
3789 			  {
3790 			     var = SCIPvarGetNegationVar(vars[v]);
3791 	#ifndef NDEBUG
3792 			     negated0 = TRUE;
3793 	#endif
3794 			  }
3795 	
3796 			  /* get active variable and clique value of next variable */
3797 			  if( SCIPvarIsActive(vars1[v1]) )
3798 			  {
3799 			     var1 = vars1[v1];
3800 	#ifndef NDEBUG
3801 			     negated1 = FALSE;
3802 	#endif
3803 			  }
3804 			  else
3805 			  {
3806 			     assert(SCIPvarGetStatus(vars1[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars1[v1])));
3807 			     var1 = SCIPvarGetNegationVar(vars1[v1]);
3808 	#ifndef NDEBUG
3809 			     negated1 = TRUE;
3810 	#endif
3811 			  }
3812 	
3813 			  /* variable index in the constraint smaller than the other one, so go to the next variable in cons */
3814 			  if( SCIPvarGetIndex(var) < SCIPvarGetIndex(var1)  )
3815 			     --v;
3816 			  /* variable index in the constraint is greater than the other one, so fix this variable */
3817 			  else if( SCIPvarGetIndex(var) > SCIPvarGetIndex(var1)  )
3818 			  {
3819 			     SCIPdebugMsg(scip, "trying to fix <%s> to 0 because it is in the same clique with a complete set partitioning constraint\n", SCIPvarGetName(vars1[v1]));
3820 	
3821 			     /* fix all variables except the one which has the negated var in the clique to zero */
3822 			     SCIP_CALL( SCIPfixVar(scip, vars1[v1], 0.0, cutoff, &fixed) );
3823 			     if( *cutoff )
3824 			     {
3825 				SCIPdebugMsg(scip, "fixing led to cutoff\n");
3826 	
3827 				return SCIP_OKAY;
3828 			     }
3829 	
3830 			     assert(fixed);
3831 			     ++(*nfixedvars);
3832 			     --v1;
3833 			  }
3834 			  else
3835 			  {
3836 			     /* because the constraint's are merged it is not possible that one constraint contains a negated
3837 			      * variable of another and because all variables in cons are in cons1 this should be really the
3838 			      * same variable here; so we can decrease v and v1
3839 			      */
3840 			     assert(negated0 == negated1);
3841 	
3842 			     --v;
3843 			     --v1;
3844 			  }
3845 		       }
3846 		       /* maybe we ended because of cons(v reached -1) so try to add rest of cons1 to cons */
3847 		       for( ; v1 >= 0; --v1)
3848 		       {
3849 			  if( SCIPvarGetLbLocal(vars1[v1]) > 0.5 || SCIPvarGetUbLocal(vars1[v1]) < 0.5 )
3850 			     continue;
3851 	
3852 			  SCIPdebugMsg(scip, "trying to fix <%s> to 0 because it is in the same clique with a complete set partitioning constraint\n", SCIPvarGetName(vars1[v1]));
3853 	
3854 			  /* fix all variables except the one which has the negated var in the clique to zero */
3855 			  SCIP_CALL( SCIPfixVar(scip, vars1[v1], 0.0, cutoff, &fixed) );
3856 			  if( *cutoff )
3857 			  {
3858 			     SCIPdebugMsg(scip, "fixing led to cutoff\n");
3859 	
3860 			     return SCIP_OKAY;
3861 			  }
3862 	
3863 			  assert(fixed);
3864 			  ++(*nfixedvars);
3865 		       }
3866 		    }
3867 	
3868 		    /* if caused by all fixings now this set partitioning constraint doesn't have any variable which was
3869 		     * fixed to one, it's infeasible */
3870 		    if( consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->nfixedzeros == nvars1 && consdata1->nfixedones != 1 ) /*lint !e641*/
3871 		    {
3872 		       SCIPdebugMsg(scip, "all variables in the set-partitioning constraint <%s> are fixed to zero, this leads to a cutoff\n", SCIPconsGetName(cons1));
3873 		       *cutoff = TRUE;
3874 	
3875 		       return SCIP_OKAY;
3876 		    }
3877 	
3878 		    assert(SCIPconsIsActive(cons1));
3879 		    /* delete second constraint */
3880 		    SCIPdebugMsg(scip, " -> deleting constraint <%s> number <%d> because it includes the setpartitioning constraint <%s> number <%d>\n", SCIPconsGetName(cons1), c, SCIPconsGetName(cons), considx);
3881 	
3882 	            SCIP_CALL( SCIPupdateConsFlags(scip, cons, cons1) );
3883 		    SCIP_CALL( SCIPdelCons(scip, cons1) );
3884 		    ++(*ndelconss);
3885 		 }
3886 		 /* could already be deleted because the constraint was included in another set partition constraint */
3887 		 else if( SCIPconsIsActive(cons) )
3888 		 {
3889 		    /* delete cons due to redundancy to cons1 */
3890 		    SCIPdebugMsg(scip, " -> deleting constraint <%s> number <%d> due to inclusion in constraint <%s> number <%d>\n", SCIPconsGetName(cons), considx, SCIPconsGetName(cons1), c);
3891 	
3892 	            SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons) );
3893 		    SCIP_CALL( SCIPdelCons(scip, cons) );
3894 		    ++(*ndelconss);
3895 		 }
3896 	      }
3897 	      /* cons includes cons1
3898 	       *
3899 	       * @note that zero fixations from above can only appear through a set-partitioning constraint, this means if
3900 	       *       cons was the set-partitioning constraint only variables which are not in this constraint could be fixed
3901 	       *       to zero, and this also means that the overlapping variables in this particular case are still active or
3902 	       *       fixed to 1
3903 	       *       later on it could be possible that even variables in cons are fixed to zero, which can lead to wrong
3904 	       *       results when checking if countofoverlapping[c] + consdata1->nfixedzeros == nvars1, because a fixed
3905 	       *       variable could be counted twice
3906 	       */
3907 	      else if( (!overlapdestroyed && countofoverlapping[c] + consdata1->nfixedzeros == nvars1) || countofoverlapping[c] == nvars1 )
3908 	      {
3909 		 /* even in deleted constraints we may fix unfixed variables */
3910 		 if( consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
3911 		 {
3912 		    const int oldnfixedvars = *nfixedvars;
3913 	#ifndef NDEBUG
3914 		    SCIP_Bool negated0;
3915 		    SCIP_Bool negated1;
3916 	#endif
3917 		    /* both constraints should stay merged */
3918 		    assert(consdata->merged);
3919 		    assert(consdata1->merged);
3920 	
3921 		    vars1 = consdata1->vars;
3922 	
3923 		    /* sorting array after indices of variables, negated and active counterparts would stand side by side */
3924 		    SCIPsortDownPtr((void**)vars1, SCIPvarCompActiveAndNegated, nvars1);
3925 		    /* standard setppc-sorting now lost */
3926 		    consdata1->sorted = FALSE;
3927 	
3928 		    /* iterate over the both cliques variables the "same" time */
3929 		    for( v = nvars - 1, v1 = nvars1 - 1; v >= 0 && v1 >= 0; )
3930 		    {
3931 		       if( SCIPvarGetLbLocal(vars1[v1]) > 0.5 || SCIPvarGetUbLocal(vars1[v1]) < 0.5 )
3932 		       {
3933 			  --v1;
3934 			  continue;
3935 		       }
3936 		       if( SCIPvarGetLbLocal(vars[v]) > 0.5 || SCIPvarGetUbLocal(vars[v]) < 0.5 )
3937 		       {
3938 			  --v;
3939 			  continue;
3940 		       }
3941 	
3942 		       /* all variables inside the second clique constraint should be either active or negated of an active one */
3943 		       assert(SCIPvarIsActive(vars1[v1]) || (SCIPvarGetStatus(vars1[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars1[v1]))));
3944 		       /* all variables inside the first clique constraint should be either active or negated of an active one */
3945 		       assert(SCIPvarIsActive(vars[v]) || (SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[v]))));
3946 	
3947 		       /* get not negated variable and clique value in cons */
3948 		       if( SCIPvarIsActive(vars[v]) )
3949 		       {
3950 			  var = vars[v];
3951 	#ifndef NDEBUG
3952 			  negated0 = FALSE;
3953 	#endif
3954 		       }
3955 		       else
3956 		       {
3957 			  assert(SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[v])));
3958 			  var = SCIPvarGetNegationVar(vars[v]);
3959 	#ifndef NDEBUG
3960 			  negated0 = TRUE;
3961 	#endif
3962 		       }
3963 	
3964 		       /* get active variable and clique value of next variable */
3965 		       if( SCIPvarIsActive(vars1[v1]) )
3966 		       {
3967 			  var1 = vars1[v1];
3968 	#ifndef NDEBUG
3969 			  negated1 = FALSE;
3970 	#endif
3971 		       }
3972 		       else
3973 		       {
3974 			  assert(SCIPvarGetStatus(vars1[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars1[v1])));
3975 			  var1 = SCIPvarGetNegationVar(vars1[v1]);
3976 	#ifndef NDEBUG
3977 			  negated1 = TRUE;
3978 	#endif
3979 		       }
3980 	
3981 		       /* variable index in the constraint smaller than the other one, so go to the next variable in cons */
3982 		       if( SCIPvarGetIndex(var) < SCIPvarGetIndex(var1)  )
3983 		       {
3984 			  SCIPdebugMsg(scip, "trying to fix <%s> to 0 because it is in the same clique with a complete set partitioning constraint\n", SCIPvarGetName(var));
3985 	
3986 			  /* fix all variables except the one which has the negated var in the clique to zero */
3987 			  SCIP_CALL( SCIPfixVar(scip, vars[v], 0.0, cutoff, &fixed) );
3988 			  if( *cutoff )
3989 			  {
3990 			     SCIPdebugMsg(scip, "fixing led to cutoff\n");
3991 	
3992 			     return SCIP_OKAY;
3993 			  }
3994 	
3995 			  assert(fixed);
3996 			  ++(*nfixedvars);
3997 	
3998 			  --v;
3999 		       }
4000 		       /* variable index in the constraint is greater than the other one, so fix this variable */
4001 		       else if( SCIPvarGetIndex(var) > SCIPvarGetIndex(var1)  )
4002 			  --v1;
4003 		       else
4004 		       {
4005 			  /* because the constraint's are merged it is not possible that one constraint contains a negated
4006 			   * variable of another and because all variables in cons1 are in cons this should be really the same
4007 			   * variable here; so we can decrease v and v1
4008 			   */
4009 			  assert(negated0 == negated1);
4010 	
4011 			  --v;
4012 			  --v1;
4013 		       }
4014 		    }
4015 	
4016 		    /* maybe we ended because of cons1(v1 reached -1) so try to add rest of cons to cons1 */
4017 		    for( ; v >= 0; --v)
4018 		    {
4019 		       if( SCIPvarGetLbLocal(vars[v]) > 0.5 || SCIPvarGetUbLocal(vars[v]) < 0.5 )
4020 			  continue;
4021 	
4022 		       SCIPdebugMsg(scip, "trying to fix <%s> to 0 because it is in the same clique with a complete set partitioning constraint\n", SCIPvarGetName(vars[v]));
4023 	
4024 		       /* fix all variables except the one which has the negated var in the clique to zero */
4025 		       SCIP_CALL( SCIPfixVar(scip, vars[v], 0.0, cutoff, &fixed) );
4026 		       if( *cutoff )
4027 		       {
4028 			  SCIPdebugMsg(scip, "fixing led to cutoff\n");
4029 	
4030 			  return SCIP_OKAY;
4031 		       }
4032 	
4033 		       assert(fixed);
4034 		       ++(*nfixedvars);
4035 		    }
4036 	
4037 		    /* if caused by all fixings now this set partitioning constraint doesn't have any variable which was
4038 		     * fixed to one, it's infeasible */
4039 		    if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata->nfixedzeros == nvars && consdata->nfixedones != 1 ) /*lint !e641*/
4040 		    {
4041 		       SCIPdebugMsg(scip, "all variables in the set-partitioning constraint <%s> are fixed to zero, this leads to a cutoff\n", SCIPconsGetName(cons1));
4042 		       *cutoff = TRUE;
4043 	
4044 		       return SCIP_OKAY;
4045 		    }
4046 	
4047 		    /* could already be deleted because the constraint was included in another set partition constraint */
4048 		    if( SCIPconsIsActive(cons) )
4049 		    {
4050 		       /* delete cons because it include another set partitioning constraint */
4051 		       SCIPdebugMsg(scip, " -> deleting constraint <%s> number <%d> because it includes the setpartitioning constraint <%s> number <%d>\n", SCIPconsGetName(cons), considx, SCIPconsGetName(cons1), c);
4052 		       assert(SCIPconsIsActive(cons));
4053 	
4054 	               SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons) );
4055 		       SCIP_CALL( SCIPdelCons(scip, cons) );
4056 		       ++(*ndelconss);
4057 		    }
4058 	
4059 		    /* due to fixings in cons0 mark overlapping invalid for checking with fixedzero variables together */
4060 		    if( oldnfixedvars < *nfixedvars )
4061 		       overlapdestroyed = TRUE;
4062 		 }
4063 		 else
4064 		 {
4065 		    assert(consdata1->setppctype == SCIP_SETPPCTYPE_PACKING); /*lint !e641*/
4066 	
4067 		    /* delete cons1 due to redundancy to cons */
4068 		    SCIPdebugMsg(scip, " -> deleting constraint <%s> number <%d> due to inclusion in constraint <%s> number <%d>\n", SCIPconsGetName(cons1), c, SCIPconsGetName(cons), considx);
4069 		    assert(SCIPconsIsActive(cons1));
4070 	
4071 	            SCIP_CALL( SCIPupdateConsFlags(scip, cons, cons1) );
4072 		    SCIP_CALL( SCIPdelCons(scip, cons1) );
4073 		    ++(*ndelconss);
4074 		 }
4075 	      }
4076 	      /* if cons has only one unfixed variable which is not in cons1 and cons1 has one variable which does not appear in
4077 	       * cons and both constraints are setpartitioning constraints we might aggregate both not overlapping variables and
4078 	       * delete one constraint
4079 	       */
4080 	      else if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && countofoverlapping[c] == nvars - oldnfixedzeros - 1 && countofoverlapping[c] == nvars1 - 1 ) /*lint !e641*/
4081 	      {
4082 		 SCIP_VAR* aggvar1;
4083 		 SCIP_VAR* aggvar2;
4084 		 SCIP_Bool negated0;
4085 		 SCIP_Bool negated1;
4086 	
4087 		 aggvar1 = NULL;
4088 		 aggvar2 = NULL;
4089 	
4090 		 /* both constraints should stay merged */
4091 		 assert(consdata->merged);
4092 		 assert(consdata1->merged);
4093 	
4094 		 vars1 = consdata1->vars;
4095 	
4096 		 /* sorting array after indices of variables, negated and active counterparts would stand side by side */
4097 		 SCIPsortDownPtr((void**)vars1, SCIPvarCompActiveAndNegated, nvars1);
4098 		 /* standard setppc-sorting now lost */
4099 		 consdata1->sorted = FALSE;
4100 	
4101 		 /* iterate over the both cliques variables the "same" time */
4102 		 for( v = nvars - 1, v1 = nvars1 - 1; v >= 0 && v1 >= 0; )
4103 		 {
4104 		    if( SCIPvarGetLbLocal(vars1[v1]) > 0.5 || SCIPvarGetUbLocal(vars1[v1]) < 0.5 )
4105 		    {
4106 		       --v1;
4107 		       continue;
4108 		    }
4109 		    if( SCIPvarGetLbLocal(vars[v]) > 0.5 || SCIPvarGetUbLocal(vars[v]) < 0.5 )
4110 		    {
4111 		       --v;
4112 		       continue;
4113 		    }
4114 	
4115 		    /* all variables inside the second clique constraint should be either active or negated of an active one */
4116 		    assert(SCIPvarIsActive(vars1[v1]) || (SCIPvarGetStatus(vars1[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars1[v1]))));
4117 		    /* all variables inside the first clique constraint should be either active or negated of an active one */
4118 		    assert(SCIPvarIsActive(vars[v]) || (SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[v]))));
4119 	
4120 		    /* get not negated variable and clique value in cons */
4121 		    if( SCIPvarIsActive(vars[v]) )
4122 		    {
4123 		       var = vars[v];
4124 		       negated0 = FALSE;
4125 		    }
4126 		    else
4127 		    {
4128 		       assert(SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[v])));
4129 		       var = SCIPvarGetNegationVar(vars[v]);
4130 		       negated0 = TRUE;
4131 		    }
4132 	
4133 		    /* get active variable and clique value of next variable */
4134 		    if( SCIPvarIsActive(vars1[v1]) )
4135 		    {
4136 		       var1 = vars1[v1];
4137 		       negated1 = FALSE;
4138 		    }
4139 		    else
4140 		    {
4141 		       assert(SCIPvarGetStatus(vars1[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars1[v1])));
4142 		       var1 = SCIPvarGetNegationVar(vars1[v1]);
4143 		       negated1 = TRUE;
4144 		    }
4145 	
4146 		    /* variable index in the constraint smaller than the other one, so go to the next variable in cons */
4147 		    if( SCIPvarGetIndex(var) < SCIPvarGetIndex(var1)  )
4148 		    {
4149 		       assert(aggvar1 == NULL);
4150 		       aggvar1 = vars[v];
4151 	
4152 		       if( aggvar2 != NULL )
4153 			  break;
4154 	
4155 		       --v;
4156 		    }
4157 		    /* variable index in the constraint is greater than the other one, so fix this variable */
4158 		    else if( SCIPvarGetIndex(var) > SCIPvarGetIndex(var1)  )
4159 		    {
4160 		       assert(aggvar2 == NULL);
4161 		       aggvar2 = vars1[v1];
4162 	
4163 		       if( aggvar1 != NULL )
4164 			  break;
4165 	
4166 		       --v1;
4167 		    }
4168 		    else
4169 		    {
4170 		       /* because the constraint's are merged it is not possible that one constraint contains a negated variable
4171 			* of another, but both variables in both constraints still can be negated to each other
4172 			*/
4173 		       if( negated0 != negated1 )
4174 		       {
4175 			  /* cons is except for one variable equal to cons1 and the unequal variable in cons is negated
4176 			   * to the one in cons1, so the problem is infeasible
4177 			   */
4178 			  SCIPdebugMsg(scip, "two set-partitioning constraint <%s> and <%s> have only one variable not in common, but this variable <%s> appears in one constraint as the negated version as in the other constraint\n", SCIPconsGetName(cons), SCIPconsGetName(cons1), SCIPvarGetName(vars[v]));
4179 			  *cutoff = TRUE;
4180 	
4181 			  return SCIP_OKAY;
4182 		       }
4183 		       --v;
4184 		       --v1;
4185 		    }
4186 		 }
4187 	
4188 		 /* due to fixings, it is possible that there are no active variables left, we we did not recognize which variables we could aggregate */
4189 		 if( aggvar1 == NULL && aggvar2 == NULL )
4190 		    continue;
4191 	
4192 		 /* determine second aggregation var, if not yet done */
4193 		 if( aggvar2 == NULL )
4194 		 {
4195 		    for( ; v1 >= 0; --v1)
4196 		    {
4197 		       if( SCIPvarGetLbLocal(vars1[v1]) > 0.5 || SCIPvarGetUbLocal(vars1[v1]) < 0.5 )
4198 			  continue;
4199 	
4200 		       aggvar2 = vars1[v1];
4201 		       break;
4202 		    }
4203 		 }
4204 		 /* determine first aggregation var, if not yet done */
4205 		 else if( aggvar1 == NULL )
4206 		 {
4207 		    /* maybe we ended because of cons1(v1 reached -1) so find the aggvar1 in cons */
4208 		    for( ; v >= 0; --v)
4209 		    {
4210 		       if( SCIPvarGetLbLocal(vars[v]) > 0.5 || SCIPvarGetUbLocal(vars[v]) < 0.5 )
4211 			  continue;
4212 	
4213 		       aggvar1 = vars[v];
4214 		       break;
4215 		    }
4216 		 }
4217 	
4218 		 /* due to fixings, it is possible that there are no active variables left, we we did not recognize which variables we could aggregate */
4219 		 if( aggvar1 == NULL || aggvar2 == NULL )
4220 		    continue;
4221 	
4222 		 SCIPdebugMsg(scip, "memorize the aggregation of <%s> == <%s>, because they are the last two variable which are different in these two set partitioning constraints <%s> <%s>\n", SCIPvarGetName(aggvar1), SCIPvarGetName(aggvar2), SCIPconsGetName(cons), SCIPconsGetName(cons1));
4223 	
4224 		 /* resize the aggregation arrays if necessary */
4225 		 if( *saggregations == *naggregations )
4226 		 {
4227 		    *saggregations = SCIPcalcMemGrowSize(scip, *naggregations + 1);
4228 		    assert(*saggregations > *naggregations);
4229 		    SCIP_CALL( SCIPreallocBufferArray(scip, &undoneaggrtypes, *saggregations) );
4230 		    SCIP_CALL( SCIPreallocBufferArray(scip, &undoneaggrvars, 2 * (*saggregations)) );
4231 	
4232 		    /* clear the aggregation type array to set the default to the aggregation of the form x + y = 1 */
4233 		    BMSclearMemoryArray(&(undoneaggrtypes[*naggregations]), *saggregations - *naggregations); /*lint !e866*/
4234 		 }
4235 	
4236 		 /* memorize aggregation variables*/
4237 		 undoneaggrtypes[*naggregations] = TRUE;
4238 		 undoneaggrvars[2 * (*naggregations)] = aggvar1;
4239 		 undoneaggrvars[2 * (*naggregations) + 1] = aggvar2;
4240 		 ++(*naggregations);
4241 	
4242 		 if( !SCIPdoNotAggr(scip) )
4243 		 {
4244 		    /* delete constraint */
4245 		    SCIPdebugMsg(scip, " -> deleting constraint <%s> number <%d> because it is dominated by constraint <%s>\n", SCIPconsGetName(cons1), c, SCIPconsGetName(cons));
4246 		    assert(SCIPconsIsActive(cons1));
4247 	
4248 	            SCIP_CALL( SCIPupdateConsFlags(scip, cons, cons1) );
4249 		    SCIP_CALL( SCIPdelCons(scip, cons1) );
4250 		    ++(*ndelconss);
4251 		 }
4252 	      }
4253 	      /* w.l.o.g. cons is a setpartitioning constraint and countofoverlapping == nvars - oldnfixedzeros - 1 we can
4254 	       * delete all overlapping variables in cons1 and add the negated variable of the not overlapped variable to cons
4255 	       * 1; the result should be a shorter constraint with the same impact
4256 	       */
4257 	      else if( shrinking && !overlapdestroyed && countofoverlapping[c] > 1 && ((consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && countofoverlapping[c] == nvars - oldnfixedzeros - 1) || (consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING && countofoverlapping[c] == nvars1 - 1)) ) /*lint !e641*/
4258 	      {
4259 		 SCIP_CONSDATA* consdatachange;
4260 		 SCIP_VAR** varstostay;
4261 		 SCIP_VAR** varstochange;
4262 		 SCIP_CONS* constochange;
4263 		 SCIP_CONS* constostay;
4264 		 SCIP_VAR* addvar;
4265 		 SCIP_Bool negated0;
4266 		 SCIP_Bool negated1;
4267 		 int nvarstostay;
4268 		 int nvarstochange;
4269 		 int constochangeidx;
4270 	#ifndef NDEBUG
4271 		 const int oldnchgcoefs = *nchgcoefs;
4272 	#endif
4273 	
4274 		 addvar = NULL;
4275 	
4276 		 assert((consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING) != (consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING) || countofoverlapping[c] != nvars - 1 || countofoverlapping[c] != nvars1 - 1); /*lint !e641*/
4277 	
4278 		 /* both constraints should stay merged */
4279 		 assert(consdata->merged);
4280 		 assert(consdata1->merged);
4281 	
4282 		 /* sorting array after indices of variables, negated and active counterparts would stand side by side */
4283 		 SCIPsortDownPtr((void**)(consdata1->vars), SCIPvarCompActiveAndNegated, nvars1);
4284 		 /* standard setppc-sorting now lost */
4285 		 consdata1->sorted = FALSE;
4286 	
4287 		 /* initialize variables */
4288 		 if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && countofoverlapping[c] == nvars - oldnfixedzeros - 1) /*lint !e641*/
4289 		 {
4290 		    varstostay = vars;
4291 		    varstochange = consdata1->vars;
4292 		    nvarstostay = nvars;
4293 		    nvarstochange = nvars1;
4294 		    constostay = cons;
4295 		    constochange = cons1;
4296 		    consdatachange = consdata1;
4297 		    constochangeidx = c;
4298 		 }
4299 		 else
4300 		 {
4301 		    varstostay = consdata1->vars;
4302 		    varstochange = vars;
4303 		    nvarstostay = nvars1;
4304 		    nvarstochange = nvars;
4305 		    constostay = cons1;
4306 		    constochange = cons;
4307 		    consdatachange = consdata;
4308 		    constochangeidx = considx;
4309 	
4310 		    *chgcons = TRUE;
4311 		 }
4312 	
4313 		 /* iterate over the both cliques variables the "same" time, here we need the backward loop, because we
4314 		  * delete some variables and we don not want to loose order
4315 		  */
4316 		 for( v = nvarstostay - 1, v1 = nvarstochange - 1; v >= 0 && v1 >= 0; )
4317 		 {
4318 		    if( SCIPvarGetLbLocal(varstochange[v1]) > 0.5 || SCIPvarGetUbLocal(varstochange[v1]) < 0.5 )
4319 		    {
4320 		       --v1;
4321 		       continue;
4322 		    }
4323 		    if( SCIPvarGetLbLocal(varstostay[v]) > 0.5 || SCIPvarGetUbLocal(varstostay[v]) < 0.5 )
4324 		    {
4325 		       --v;
4326 		       continue;
4327 		    }
4328 	
4329 		    /* all variables inside the second clique constraint should be either active or negated of an active one */
4330 		    assert(SCIPvarIsActive(varstochange[v1]) || (SCIPvarGetStatus(varstochange[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(varstochange[v1]))));
4331 		    /* all variables inside the first clique constraint should be either active or negated of an active one */
4332 		    assert(SCIPvarIsActive(varstostay[v]) || (SCIPvarGetStatus(varstostay[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(varstostay[v]))));
4333 	
4334 		    /* get not negated variable and clique value in constostay */
4335 		    if( SCIPvarIsActive(varstostay[v]) )
4336 		    {
4337 		       var = varstostay[v];
4338 		       negated0 = FALSE;
4339 		    }
4340 		    else
4341 		    {
4342 		       assert(SCIPvarGetStatus(varstostay[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(varstostay[v])));
4343 		       var = SCIPvarGetNegationVar(varstostay[v]);
4344 		       negated0 = TRUE;
4345 		    }
4346 	
4347 		    /* get active variable and clique value of in constochange*/
4348 		    if( SCIPvarIsActive(varstochange[v1]) )
4349 		    {
4350 		       var1 = varstochange[v1];
4351 		       negated1 = FALSE;
4352 		    }
4353 		    else
4354 		    {
4355 		       assert(SCIPvarGetStatus(varstochange[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(varstochange[v1])));
4356 		       var1 = SCIPvarGetNegationVar(varstochange[v1]);
4357 		       negated1 = TRUE;
4358 		    }
4359 	
4360 		    /* variable index in the constraint smaller than the other one, so go to the next variable in cons */
4361 		    if( SCIPvarGetIndex(var) < SCIPvarGetIndex(var1)  )
4362 		    {
4363 		       assert(addvar == NULL);
4364 		       addvar = varstostay[v];
4365 		       --v;
4366 		    }
4367 		    /* variable index in the constraint is greater than the other one, so fix this variable */
4368 		    else if( SCIPvarGetIndex(var) > SCIPvarGetIndex(var1)  )
4369 		    {
4370 		       --v1;
4371 		    }
4372 		    else
4373 		    {
4374 		       /* because the constraint's are merged it is not possible that one constraint contains a negated variable
4375 			* of another, but both constraint might have a variable in negated form of the other
4376 			*/
4377 		       if( negated0 != negated1 )
4378 		       {
4379 			  assert(addvar == NULL);
4380 	
4381 			  SCIPdebugMsg(scip, "-> trying to fix <%s> to 0 because it would exist twice in a constraint\n", SCIPvarGetName(varstochange[v1]));
4382 	
4383 			  /* fix variable to zero */
4384 			  SCIP_CALL( SCIPfixVar(scip, varstochange[v1], 0.0, cutoff, &fixed) );
4385 			  if( *cutoff )
4386 			  {
4387 			     SCIPdebugMsg(scip, "fixing led to cutoff\n");
4388 	
4389 			     return SCIP_OKAY;
4390 			  }
4391 	
4392 			  assert(fixed);
4393 			  ++(*nfixedvars);
4394 	
4395 			  /* the above fixing is equal to the fixation of varstostay[v] to 1, so we can call presolvePropagateCons() for consstay */
4396 			  SCIP_CALL( presolvePropagateCons(scip, constostay, FALSE, NULL, NULL, NULL, NULL, nfixedvars, naggrvars, ndelconss, cutoff) );
4397 	
4398 			  return SCIP_OKAY;
4399 		       }
4400 		       else
4401 		       {
4402 			  /* correct local data structure, remove variable from constraint entry where it will be removed */
4403 			  deleteCliqueDataEntry(varstochange[v1], constochangeidx, vartoindex, varnconss, varconsidxs);
4404 	
4405 			  SCIPdebugMsg(scip, " -> deleting variable <%s> in constraint <%s> number %d, because it will be replaced\n", SCIPvarGetName(varstochange[v1]), SCIPconsGetName(constochange), constochangeidx);
4406 			  /* delete overlapping variables in constochange */
4407 			  SCIP_CALL( delCoefPos(scip, constochange, v1) );
4408 			  ++(*nchgcoefs);
4409 		       }
4410 	
4411 		       --v;
4412 		       --v1;
4413 		    }
4414 		 }
4415 		 assert(addvar != NULL || v >= 0);
4416 		 /* we should have removed exactly countofoverlapping[c] variables from the constochange */
4417 		 assert(*nchgcoefs - oldnchgcoefs == countofoverlapping[c]);
4418 	
4419 		 /* determine addvar if not yet found */
4420 		 if( addvar == NULL )
4421 		 {
4422 		    for( ; v >= 0; --v)
4423 		    {
4424 		       if( SCIPvarGetLbLocal(varstostay[v]) > 0.5 || SCIPvarGetUbLocal(varstostay[v]) < 0.5 )
4425 			  continue;
4426 	
4427 		       /* all variables inside the first clique constraint should be either active or negated of an active one */
4428 		       assert(SCIPvarIsActive(varstostay[v]) || (SCIPvarGetStatus(varstostay[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(varstostay[v]))));
4429 	
4430 		       addvar = varstostay[v];
4431 		       break;
4432 		    }
4433 		 }
4434 		 assert(addvar != NULL);
4435 	
4436 		 /* get representative variable for all deleted variables */
4437 		 SCIP_CALL( SCIPgetNegatedVar(scip, addvar, &addvar) );
4438 		 assert(addvar != NULL);
4439 	
4440 		 SCIPdebugMsg(scip, " -> adding variable <%s> to constraint <%s> number %d\n", SCIPvarGetName(addvar), SCIPconsGetName(constochange), constochangeidx);
4441 		 /* add representative for overlapping instead */
4442 		 SCIP_CALL( addCoef(scip, constochange, addvar) );
4443 		 ++(*nchgcoefs);
4444 	
4445 		 /* constraint should be still merged because this added variable is new in this constraint */
4446 		 consdatachange->merged = TRUE;
4447 		 assert(constochangeidx == (cons == constochange ? considx : c));
4448 	
4449 		 /* correct local data structure, add constraint entry to variable data  */
4450 		 SCIP_CALL( addCliqueDataEntry(scip, addvar, constochangeidx, TRUE, usefulvars, nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs) );
4451 	
4452 		 /* cons changed so much, that it cannot be used for more overlapping checks */
4453 		 if( *chgcons )
4454 		    return SCIP_OKAY;
4455 	      }
4456 	   }
4457 	
4458 	   return SCIP_OKAY;
4459 	}
4460 	
4461 	/** try to lift variables to given constraint */
4462 	/** @todo try another variant by determine lifting variables as the intersection of all cliques variables of the
4463 	 *        constraint variables, note that the intersection changes after one variable was added
4464 	 */
4465 	static
4466 	SCIP_RETCODE liftCliqueVariables(
4467 	   SCIP*const            scip,               /**< SCIP data structure */
4468 	   SCIP_CONS*const       cons,               /**< constraint which may overlap */
4469 	   int const             arraypos,           /**< position of constraint in global array */
4470 	   SCIP_VAR**const       usefulvars,         /**< possible variables to lift */
4471 	   int*const             nusefulvars,        /**< pointer to store number of added variables */
4472 	   int const             endidx,             /**< end index for possible lifting variables */
4473 	   SCIP_Bool**           cliquevalues,       /**< pointer to clique values of constraint-variables, either one if the
4474 						      *   variable is active or zero if the variable is negated
4475 						      *   @note this array can be resized in this method
4476 						      */
4477 	   SCIP_HASHMAP*const    vartoindex,         /**< hashmap mapping variables to indices */
4478 	   int*const             varnconss,          /**< array with number of constraints a variable occurs */
4479 	   int*const             maxnvarconsidx,     /**< array with the maximal number of occurrences of a variable */
4480 	   int**const            varconsidxs,        /**< array with constraint indices in which the corresponding variable
4481 						      *   exists
4482 						      */
4483 	   int*const             maxnvars,           /**< pointer to store maximal number of variables of a constraint */
4484 	   int*const             nadded,             /**< pointer to store number of possible added variables */
4485 	   SCIP_Bool*const       chgcons,            /**< pointer to store if the constraint was changed, due to added
4486 						      *   variables
4487 						      */
4488 	   int*const             nfixedvars,         /**< pointer to count number of deleted variables */
4489 	   int*const             ndelconss,          /**< pointer to count number of deleted constraints */
4490 	   SCIP_Bool*const       cutoff              /**< pointer to store if the problem is infeasible due to a fixing */
4491 	   )
4492 	{
4493 	   SCIP_CONSDATA* consdata;
4494 	   SCIP_VAR** vars;
4495 	   SCIP_VAR* var;
4496 	   SCIP_VAR* var1;
4497 	   SCIP_Bool fixed;
4498 	   SCIP_Bool value;
4499 	   int nvars;
4500 	   int nottocheck; /* will be the position for a variable in cons0 which is in negated form in the same clique */
4501 	   int v;
4502 	   int v1;
4503 	   int k;
4504 	
4505 	   assert(scip != NULL);
4506 	   assert(cons != NULL);
4507 	   assert(usefulvars != NULL);
4508 	   assert(cliquevalues != NULL);
4509 	   assert(*cliquevalues != NULL);
4510 	   assert(vartoindex != NULL);
4511 	   assert(varnconss != NULL);
4512 	   assert(maxnvarconsidx != NULL);
4513 	   assert(varconsidxs != NULL);
4514 	   assert(maxnvars != NULL);
4515 	   assert(nadded != NULL);
4516 	   assert(chgcons != NULL);
4517 	   assert(nfixedvars != NULL);
4518 	   assert(ndelconss != NULL);
4519 	   assert(cutoff != NULL);
4520 	
4521 	   if( !SCIPconsIsActive(cons) )
4522 	      return SCIP_OKAY;
4523 	
4524 	   consdata = SCIPconsGetData(cons);
4525 	   assert(consdata != NULL);
4526 	
4527 	   nvars = consdata->nvars;
4528 	
4529 	   if( nvars == 0 )
4530 	      return SCIP_OKAY;
4531 	
4532 	   assert(nvars <= *maxnvars);
4533 	
4534 	   vars = consdata->vars;
4535 	   assert(vars != NULL);
4536 	
4537 	   v1 = endidx;
4538 	
4539 	   /* now we try to add variables with index prior to endidx to cons */
4540 	   for( v = nvars - 1; v >= 0 && v1 >= 0; )
4541 	   {
4542 	      if( SCIPvarGetLbLocal(usefulvars[v1]) > 0.5 || SCIPvarGetUbLocal(usefulvars[v1]) < 0.5 )
4543 	      {
4544 		 --v1;
4545 		 continue;
4546 	      }
4547 	      if( SCIPvarGetUbLocal(vars[v]) < 0.5 )
4548 	      {
4549 		 --v;
4550 		 continue;
4551 	      }
4552 	
4553 	      /* check that constraint variables are still correctly sorted, indices of active variables should be decreasing */
4554 	      assert(v == 0 || SCIPvarCompareActiveAndNegated(vars[v], vars[v - 1]) <= 0);
4555 	
4556 	      /* there should no variables fixed to one occur in our constraint */
4557 	      assert(SCIPvarGetLbLocal(vars[v]) < 0.5 && SCIPvarGetUbLocal(vars[v]) > 0.5);
4558 	      assert(SCIPvarGetLbLocal(usefulvars[v1]) < 0.5 && SCIPvarGetUbLocal(usefulvars[v1]) > 0.5);
4559 	
4560 	      /* all variables which we have inside the clique constraint and which can possibly be added should be either active or negated */
4561 	      assert(SCIPvarIsActive(vars[v]) || (SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[v]))));
4562 	      assert(SCIPvarIsActive(usefulvars[v1]) || (SCIPvarGetStatus(usefulvars[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(usefulvars[v1]))));
4563 	
4564 	      /* constraint should during adding of variables stay merged, because for each variable which is added holds that
4565 	       * the index of this corresponding active variable is pairwise different to all indices of all active
4566 	       * corresponding variables inside the constraint
4567 	       * @note it should not happen that we add one variable and the corresponding counterpart to the same constraint */
4568 	      assert(consdata->merged);
4569 	
4570 	      /* get active variable and clique value in cons */
4571 	      if( (*cliquevalues)[v] )
4572 		 var = vars[v];
4573 	      else
4574 	      {
4575 		 assert(SCIPvarGetStatus(vars[v]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[v])));
4576 		 var = SCIPvarGetNegationVar(vars[v]);
4577 	      }
4578 	
4579 	      /* get active variable and clique value of next variable */
4580 	      if( SCIPvarIsActive(usefulvars[v1]) )
4581 	      {
4582 		 var1 = usefulvars[v1];
4583 		 value = TRUE;
4584 	      }
4585 	      else
4586 	      {
4587 		 assert(SCIPvarGetStatus(usefulvars[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(usefulvars[v1])));
4588 		 var1 = SCIPvarGetNegationVar(usefulvars[v1]);
4589 		 value = FALSE;
4590 	      }
4591 	
4592 	      nottocheck = -1;
4593 	      k = 0;
4594 	
4595 	      /* variable index in the constraint smaller than the other one, so go to the next variable in cons */
4596 	      if( SCIPvarGetIndex(var) < SCIPvarGetIndex(var1)  )
4597 	      {
4598 		 --v;
4599 		 continue;
4600 	      }
4601 	      /* variable index in the constraint is greater than the other one, so check for possible inclusion of the variable */
4602 	      else if( SCIPvarGetIndex(var) > SCIPvarGetIndex(var1)  )
4603 	      {
4604 		 assert(consdata == SCIPconsGetData(cons));
4605 	
4606 		 /* check if every variable in the actual clique is in clique with the new variable */
4607 		 for( k = nvars - 1; k >= 0; --k )
4608 		 {
4609 		    if( SCIPvarGetUbLocal(vars[k]) > 0.5 )
4610 		    {
4611 		       /* there should no variables fixed to one occur in our constraint */
4612 		       assert(SCIPvarGetLbLocal(vars[k]) < 0.5);
4613 		       assert(SCIPvarIsActive(vars[k]) || (SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k]))));
4614 	
4615 		       if( (*cliquevalues)[k] )
4616 		       {
4617 			  assert(SCIPvarIsActive(vars[k]));
4618 			  var = vars[k];
4619 		       }
4620 		       else
4621 		       {
4622 			  assert(SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k])));
4623 			  var = SCIPvarGetNegationVar(vars[k]);
4624 		       }
4625 		       if( !SCIPhaveVarsCommonClique(scip, var1, value, var, (*cliquevalues)[k], TRUE) )
4626 			  break;
4627 		    }
4628 		 }
4629 		 --v1;
4630 	      }
4631 	      /* variable index in the constraint is equal to the index of the other variable, check if these variables are
4632 	       * negated of each other so memorize the position and check for possible inclusion of the new variable and if
4633 	       * possible decrease indices
4634 	       */
4635 	      else
4636 	      {
4637 		 /* one clique contains the negated and the other clique the corresponding active var */
4638 		 if( value != (*cliquevalues)[v] )
4639 		 {
4640 		    nottocheck = v;
4641 	
4642 		    assert(consdata == SCIPconsGetData(cons));
4643 		    assert(nvars <= consdata->nvars);
4644 	
4645 		    /* check if every variable in the actual clique is in clique with the new variable */
4646 		    for( k = nvars - 1; k >= 0; --k )
4647 		    {
4648 		       if( SCIPvarGetUbLocal(vars[k]) > 0.5 )
4649 		       {
4650 			  /* there should no variables fixed to one occur in our constraint */
4651 			  assert(SCIPvarGetLbLocal(vars[k]) < 0.5);
4652 	
4653 			  assert(SCIPvarIsActive(vars[k]) || (SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k]))));
4654 	
4655 			  if( k == nottocheck )
4656 			     continue;
4657 	
4658 			  if( (*cliquevalues)[k] )
4659 			  {
4660 			     assert(SCIPvarIsActive(vars[k]));
4661 			     var = vars[k];
4662 			  }
4663 			  else
4664 			  {
4665 			     assert(SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k])));
4666 			     var = SCIPvarGetNegationVar(vars[k]);
4667 			  }
4668 	
4669 			  if( !SCIPhaveVarsCommonClique(scip, var1, value, var, (*cliquevalues)[k], TRUE) )
4670 			     break;
4671 		       }
4672 		    }
4673 		 }
4674 		 /* don't decrease v because it might happen that the corresponding negated variable of var is next in
4675 		  * usefulvars
4676 		  */
4677 		 --v1;
4678 	      }
4679 	
4680 	      /* if k is smaller than 0 than the possible new variables is in the same clique with all variables of cons,
4681 	       * so we add the new variable to clique constraint or fix some variables */
4682 	      if( k < 0 )
4683 	      {
4684 		 ++(*nadded);
4685 	
4686 		 /* we found a variable which is the negated variable of another one in this clique so we can fix all
4687 		  * other variable to zero and if it's a partitioning constraint we can also fix the variable of the
4688 		  * negated to one and we can delete the constraint too */
4689 		 if( nottocheck >= 0 )
4690 		 {
4691 		    assert(consdata == SCIPconsGetData(cons));
4692 		    assert(nvars <= consdata->nvars);
4693 		    assert(consdata->merged);
4694 	
4695 		    /* process all vars for possible fixing */
4696 		    for( k = consdata->nvars - 1; k >= 0; --k )
4697 		    {
4698 		       if( SCIPvarGetUbLocal(vars[k]) > 0.5 )
4699 		       {
4700 			  /* there should no variables fixed to one occur in our constraint */
4701 			  assert(SCIPvarGetLbLocal(vars[v]) < 0.5);
4702 	
4703 			  assert(SCIPvarIsActive(vars[k]) || (SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k]))));
4704 	
4705 			  if( k != nottocheck )
4706 			  {
4707 			     SCIPdebugMsg(scip, "trying to fix <%s> to 0 because we could lift a negated variable of another constraint variable\n", SCIPvarGetName(vars[k]));
4708 			     /* fix variable to zero */
4709 			     SCIP_CALL( SCIPfixVar(scip, vars[k], 0.0, cutoff, &fixed) );
4710 	
4711 			     if( *cutoff )
4712 			     {
4713 				SCIPdebugMsg(scip, "fixing led to cutoff\n");
4714 	
4715 				return SCIP_OKAY;
4716 			     }
4717 	
4718 			     assert(fixed);
4719 	
4720 			     ++(*nfixedvars);
4721 			  }
4722 		       }
4723 		    }
4724 		    if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
4725 		    {
4726 		       assert(SCIPvarIsActive(vars[nottocheck]) || (SCIPvarGetStatus(vars[nottocheck]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[nottocheck]))));
4727 	
4728 		       SCIPdebugMsg(scip, "trying to fix <%s> to 1 due to this setpartitioning variable is with its negated in the same clique\n", SCIPvarGetName(vars[nottocheck]));
4729 		       /* fix the remaining variable to one, due to it's the only one left to satisfy the constraint */
4730 		       SCIP_CALL( SCIPfixVar(scip, vars[nottocheck], 1.0, cutoff, &fixed) );
4731 		       if( *cutoff )
4732 		       {
4733 			  SCIPdebugMsg(scip, "fixing led to cutoff\n");
4734 	
4735 			  return SCIP_OKAY;
4736 		       }
4737 	
4738 		       assert(fixed);
4739 		       ++(*nfixedvars);
4740 		    }
4741 	
4742 		    /* delete constraint */
4743 		    SCIPdebugMsg(scip, " -> deleting constraint <%s> number <%d> due to active and negated variable in the same clique constraint\n", SCIPconsGetName(cons), arraypos);
4744 		    assert(SCIPconsIsActive(cons));
4745 		    SCIP_CALL( SCIPdelCons(scip, cons) );
4746 		    ++(*ndelconss);
4747 	
4748 		    break;
4749 		 }
4750 		 /* we found a variable which could be added to a partitioning constraint so we can fix it to zero */
4751 		 else if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
4752 		 {
4753 		    SCIPdebugMsg(scip, "trying to fix <%s> to 0 because this variable is in the same clique with a set partition\n", SCIPvarGetName(usefulvars[v1 + 1]));
4754 		    /* fix variable to zero */
4755 		    SCIP_CALL( SCIPfixVar(scip, usefulvars[v1 + 1], 0.0, cutoff, &fixed) );
4756 	
4757 		    if( *cutoff )
4758 		    {
4759 		       SCIPdebugMsg(scip, "fixing led to cutoff\n");
4760 	
4761 		       return SCIP_OKAY;
4762 		    }
4763 	
4764 		    assert(fixed);
4765 	
4766 		    ++(*nfixedvars);
4767 		 }
4768 		 /* we have found a new variable for a set packing constraint cons, so add the found variable to the first constraint */
4769 		 else
4770 		 {
4771 		    SCIP_VAR* addvar;
4772 	
4773 		    assert(SCIPconsIsActive(cons));
4774 	
4775 		    addvar = usefulvars[v1 + 1];
4776 	
4777 		    assert(SCIPvarGetLbLocal(addvar) < 0.5 && SCIPvarGetUbLocal(addvar) > 0.5);
4778 	
4779 		    /* add representative instead */
4780 		    SCIPdebugMsg(scip, " -> adding variable <%s> to constraint <%s> number %d\n", SCIPvarGetName(usefulvars[v1 + 1]), SCIPconsGetName(cons), arraypos);
4781 		    SCIP_CALL( addCoef(scip, cons, addvar) );
4782 		    assert(consdata == SCIPconsGetData(cons));
4783 		    /* we know that this constraint stays merged but later on we have to resort */
4784 		    consdata->merged = TRUE;
4785 	
4786 		    /* second we add the constraint index to the list of indices where this variable occurs */
4787 		    assert(SCIPhashmapExists(vartoindex, (void*) addvar));
4788 	
4789 		    /* correct local data structure, add constraint entry to variable data  */
4790 		    SCIP_CALL( addCliqueDataEntry(scip, addvar, arraypos, FALSE, usefulvars, nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs) );
4791 	
4792 		    /* we need the new pointer to the variables, because due to adding variables it is possible that we
4793 		     * did reallocate the variables array inside the constraint, the index v should stay the same because the
4794 		     * added variable was inserted at the end and we are decreasing v in our for loop
4795 		     */
4796 		    vars = consdata->vars;
4797 		    nvars = consdata->nvars;
4798 	
4799 		    /* we need to update our data structure */
4800 	
4801 		    /* resize clique array if necessary, due to adding variables */
4802 		    if( (*maxnvars) < nvars )
4803 		    {
4804 		       while( (*maxnvars) < nvars )
4805 			  (*maxnvars) *= 2 ;
4806 		       SCIP_CALL( SCIPreallocBufferArray(scip, cliquevalues, (*maxnvars)) );
4807 		    }
4808 		    (*cliquevalues)[nvars - 1] = SCIPvarIsActive(addvar) ? TRUE : FALSE;
4809 	
4810 		    (*chgcons) = TRUE;
4811 		 }
4812 	      }
4813 	   }
4814 	
4815 	   if( !SCIPconsIsActive(cons) )
4816 	      return SCIP_OKAY;
4817 	
4818 	   /* maybe we stopped because of cons(v reached -1) so try to add rest in usefulvars */
4819 	   for( ; v1 >= 0; --v1)
4820 	   {
4821 	      if( SCIPvarGetLbLocal(usefulvars[v1]) > 0.5 || SCIPvarGetUbLocal(usefulvars[v1]) < 0.5 )
4822 		 continue;
4823 	
4824 	      /* get active variable and clique value */
4825 	      if( SCIPvarIsActive(usefulvars[v1]) )
4826 	      {
4827 		 var1 = usefulvars[v1];
4828 		 value = TRUE;
4829 	      }
4830 	      else
4831 	      {
4832 		 assert(SCIPvarGetStatus(usefulvars[v1]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(usefulvars[v1])));
4833 		 var1 = SCIPvarGetNegationVar(usefulvars[v1]);
4834 		 value = FALSE;
4835 	      }
4836 	
4837 	      assert(consdata == SCIPconsGetData(cons));
4838 	      assert(nvars <= consdata->nvars);
4839 	
4840 	      /* check if every variable in the actual clique is in clique with the new variable */
4841 	      for( k = nvars - 1; k >= 0; --k )
4842 	      {
4843 		 if( SCIPvarGetUbLocal(vars[k]) > 0.5 )
4844 		 {
4845 		    /* there should no variables fixed to one occur in our constraint */
4846 		    assert(SCIPvarGetLbLocal(vars[k]) < 0.5);
4847 	
4848 		    assert(SCIPvarIsActive(vars[k]) || (SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k]))));
4849 	
4850 		    if( (*cliquevalues)[k] )
4851 		    {
4852 		       assert(SCIPvarIsActive(vars[k]));
4853 		       var = vars[k];
4854 		    }
4855 		    else
4856 		    {
4857 		       assert(SCIPvarGetStatus(vars[k]) == SCIP_VARSTATUS_NEGATED && SCIPvarIsActive(SCIPvarGetNegationVar(vars[k])));
4858 		       var = SCIPvarGetNegationVar(vars[k]);
4859 		    }
4860 	
4861 		    if( !SCIPvarsHaveCommonClique(var1, value, var, (*cliquevalues)[k], TRUE) )
4862 		       break;
4863 		 }
4864 	      }
4865 	
4866 	      /* add new variable to clique constraint or fix some variables */
4867 	      if( k < 0 )
4868 	      {
4869 		 /* we found a variable which could be added to a partitioning constraint so we can fix it to zero */
4870 		 if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
4871 		 {
4872 		    SCIPdebugMsg(scip, "trying to fix <%s> to 0 because this variable is in the same clique with a set partition\n", SCIPvarGetName(usefulvars[v1]));
4873 	
4874 		    /* fix variable to zero */
4875 		    SCIP_CALL( SCIPfixVar(scip, usefulvars[v1], 0.0, cutoff, &fixed) );
4876 		    if( *cutoff )
4877 		    {
4878 		       SCIPdebugMsg(scip, "fixing led to cutoff\n");
4879 	
4880 		       return SCIP_OKAY;
4881 		    }
4882 		    assert(fixed);
4883 	
4884 		    ++(*nfixedvars);
4885 		    ++(*nadded);
4886 		 }
4887 		 /* add the found variable to the first constraint */
4888 		 else
4889 		 {
4890 		    SCIP_VAR* addvar;
4891 	
4892 		    assert(SCIPconsIsActive(cons));
4893 	
4894 		    addvar = usefulvars[v1];
4895 	
4896 		    assert(SCIPvarGetLbLocal(addvar) < 0.5 && SCIPvarGetUbLocal(addvar) > 0.5);
4897 	
4898 		    /* add representative instead */
4899 		    SCIPdebugMsg(scip, " -> adding variable <%s> to constraint <%s> number %d\n", SCIPvarGetName(addvar), SCIPconsGetName(cons), arraypos);
4900 		    SCIP_CALL( addCoef(scip, cons, addvar) );
4901 		    assert(consdata == SCIPconsGetData(cons));
4902 		    /* we know that this constraint stays merged but later on we have to resort */
4903 		    consdata->merged = TRUE;
4904 	
4905 		    /* second we add the constraint index to the list of indices where this variable occurs */
4906 		    assert(SCIPhashmapExists(vartoindex, (void*) addvar));
4907 	
4908 		    /* correct local data structure, add constraint entry to variable data  */
4909 		    SCIP_CALL( addCliqueDataEntry(scip, addvar, arraypos, FALSE, usefulvars, nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs) );
4910 	
4911 		    /* we need the new pointer to the variables, because due to adding variables it is possible that we
4912 		     * did reallocate the variables array inside the constraint, the index v should stay the same because the
4913 		     * added variable was inserted at the end and we are decreasing v in our for loop
4914 		     */
4915 		    vars = consdata->vars;
4916 		    nvars = consdata->nvars;
4917 	
4918 		    /* we need to update our data structure */
4919 	
4920 		    /* resize clique array if necessary, due to adding variables */
4921 		    if( (*maxnvars) < nvars )
4922 		    {
4923 		       while( (*maxnvars) < nvars )
4924 			  (*maxnvars) *= 2 ;
4925 		       SCIP_CALL( SCIPreallocBufferArray(scip, cliquevalues, (*maxnvars)) );
4926 		    }
4927 		    (*cliquevalues)[nvars - 1] = SCIPvarIsActive(addvar) ? TRUE : FALSE;
4928 	
4929 		    ++(*nadded);
4930 		    (*chgcons) = TRUE;
4931 		 }
4932 	      }
4933 	   }
4934 	
4935 	   return SCIP_OKAY;
4936 	}
4937 	
4938 	/** perform all collected aggregations */
4939 	static
4940 	SCIP_RETCODE performAggregations(
4941 	   SCIP*const            scip,               /**< SCIP data structure */
4942 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
4943 	   SCIP_VAR**const       undoneaggrvars,     /**< aggregation variables storage */
4944 	   SCIP_Bool*const       undoneaggrtypes,    /**< aggregation type storage, type FALSE means the aggregation is of the
4945 						      *   form x + y = 1; type TRUE means the aggregation is of the form x = y;
4946 						      */
4947 	   int const             naggregations,      /**< number of aggregations to performed */
4948 	   int*const             naggrvars,          /**< pointer to count number of aggregated variables */
4949 	   SCIP_Bool*const       cutoff              /**< pointer to store if the problem is infeasible due to a fixing */
4950 	   )
4951 	{  /*lint --e{715}*/
4952 	   SCIP_VAR* var1;
4953 	   SCIP_VAR* var2;
4954 	   SCIP_Bool aggregated;
4955 	   SCIP_Bool redundant;
4956 	   int a;
4957 	
4958 	   assert(scip != NULL);
4959 	   assert(conshdlrdata != NULL);
4960 	   assert(undoneaggrvars != NULL);
4961 	   assert(undoneaggrtypes != NULL);
4962 	   assert(naggregations > 0);
4963 	   assert(naggrvars != NULL);
4964 	   assert(cutoff != NULL);
4965 	
4966 	   /* loop over all open aggregations and try to aggregate them */
4967 	   for( a = 0; a < naggregations; ++a  )
4968 	   {
4969 	      var1 = undoneaggrvars[2 * a];
4970 	      var2 = undoneaggrvars[2 * a + 1];
4971 	      assert(var1 != NULL);
4972 	      assert(var2 != NULL);
4973 	
4974 	      SCIPdebugMsg(scip, "trying to aggregate <%s> %s <%s>%s\n", SCIPvarGetName(var1), undoneaggrtypes[a] ? "=" : "+", SCIPvarGetName(var2), undoneaggrtypes[a] ? "" : " = 1");
4975 	
4976 	#ifdef VARUSES
4977 	      /* in order to not mess up the variable usage counting, we have to decrease usage counting, aggregate,
4978 	       * and increase usage counting again
4979 	       */
4980 	      SCIP_CALL( conshdlrdataDecVaruses(scip, conshdlrdata, var1) );
4981 	      SCIP_CALL( conshdlrdataDecVaruses(scip, conshdlrdata, var2) );
4982 	#endif
4983 	
4984 	      /* aggregate last remaining variables in the set partitioning constraint */
4985 	      if( undoneaggrtypes[a] )
4986 	      {
4987 		 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, -1.0, 0.0, cutoff, &redundant, &aggregated) );
4988 	      }
4989 	      else
4990 	      {
4991 		 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, 1.0, 1.0, cutoff, &redundant, &aggregated) );
4992 	      }
4993 	
4994 	      if( *cutoff )
4995 	      {
4996 		 SCIPdebugMsg(scip, "aggregation was infeasible\n");
4997 	
4998 		 return SCIP_OKAY;
4999 	      }
5000 	      /* binary variables should always be aggregated, or due to fixation the aggregation is redundant */
5001 	      assert(redundant);
5002 	
5003 	      if( aggregated )
5004 		 ++(*naggrvars);
5005 	
5006 	#ifdef VARUSES
5007 	      /* increase variable usage counting again */
5008 	      SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, var1) );
5009 	      SCIP_CALL( conshdlrdataIncVaruses(scip, conshdlrdata, var2) );
5010 	#endif
5011 	   }
5012 	
5013 	   return SCIP_OKAY;
5014 	}
5015 	
5016 	/** check whether we can combine or grow cliques so some constraints become redundant or we can fix variables */
5017 	/** @todo try another variant, by building up the clique graph and delete unnecessary (transitive closure) edges and do
5018 	 *        a bfs search to search for common ancestors to get all possible lifting variables
5019 	 */
5020 	static
5021 	SCIP_RETCODE preprocessCliques(
5022 	   SCIP*const            scip,               /**< SCIP data structure */
5023 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
5024 	   SCIP_CONS**const      conss,              /**< constraint set */
5025 	   int const             nconss,             /**< number of constraints in constraint set */
5026 	   int const             nrounds,            /**< actual presolving round */
5027 	   int*const             firstchange,        /**< pointer to store first changed constraint */
5028 	   int*const             firstclique,        /**< pointer to store first constraint to start adding clique again */
5029 	   int*const             lastclique,         /**< pointer to store last constraint to add cliques again */
5030 	   int*const             nfixedvars,         /**< pointer to count number of deleted variables */
5031 	   int*const             naggrvars,          /**< pointer to count number of aggregated variables */
5032 	   int*const             ndelconss,          /**< pointer to count number of deleted constraints */
5033 	   int*const             nchgcoefs,          /**< pointer to count number of deleted coefficients */
5034 	   SCIP_Bool*const       cutoff              /**< pointer to store if the problem is infeasible due to a fixing */
5035 	   )
5036 	{
5037 	   /* extend cliques/constraints by checking whether some variables are in the same clique, no pairwise clique lifting
5038 	    * which would be slower
5039 	    */
5040 	   SCIP_CONS** usefulconss;                  /* array with pointers of constraint of setpartitioning and setpacking type */
5041 	   SCIP_VAR** usefulvars;                    /* array with pointers of variables in setpartitioning and setpacking constraints */
5042 	   int** varconsidxs;                        /* array consisting of constraint indices in which the corresponding variable exists */
5043 	   int* varnconss;                           /* array consisting of number of constraints the variable occurs */
5044 	   int* maxnvarconsidx;                      /* maximal number of occurrences of a variable */
5045 	   int* countofoverlapping = NULL;           /* the amount of variables which are in another constraint */
5046 	   SCIP_Bool* cliquevalues = NULL;           /* values of clique-variables, either one if the variable is active or zero if the variable is negated */
5047 	
5048 	   SCIP_HASHMAP* vartoindex;                 /* mapping of SCIP variables to indices */
5049 	   SCIP_CONSDATA* consdata;
5050 	
5051 	   SCIP_Bool chgcons0;
5052 	   int nvars;
5053 	   int c;
5054 	   int v;
5055 	   int nusefulconss;
5056 	   int nusefulvars;
5057 	   int susefulvars;
5058 	   int maxnvars;
5059 	   int varindex;
5060 	
5061 	   SCIP_VAR** undoneaggrvars;                /* storage for not yet performed aggregations */
5062 	   SCIP_Bool* undoneaggrtypes;               /* storage for not yet performed aggregation type (x = y or x + y = 1) */
5063 	   int saggregations;
5064 	   int naggregations;
5065 	
5066 	   assert(scip != NULL);
5067 	   assert(conshdlrdata != NULL);
5068 	   assert(conss != NULL || nconss == 0);
5069 	   assert(firstchange != NULL);
5070 	   assert(firstclique != NULL);
5071 	   assert(lastclique != NULL);
5072 	   assert(nfixedvars != NULL);
5073 	   assert(naggrvars != NULL);
5074 	   assert(ndelconss != NULL);
5075 	   assert(nchgcoefs != NULL);
5076 	   assert(cutoff != NULL);
5077 	
5078 	   *cutoff = FALSE;
5079 	
5080 	   if( nconss == 0 )
5081 	      return SCIP_OKAY;
5082 	
5083 	   nvars = SCIPgetNVars(scip);
5084 	
5085 	   if( nvars == 0 )
5086 	      return SCIP_OKAY;
5087 	
5088 	   susefulvars = 2 * nvars; /* two times because of negated vars, maybe due to deleted variables we need to increase this */
5089 	
5090 	   /* a hashmap from varindex to postion in varconsidxs array, because above is still too small */
5091 	   SCIP_CALL( SCIPhashmapCreate(&vartoindex, SCIPblkmem(scip), nvars) );
5092 	
5093 	   /* get temporary memory for the aggregation storage, to memorize aggregations which will be performed later, otherwise we would destroy our local data structures */
5094 	   saggregations = nvars;
5095 	   SCIP_CALL( SCIPallocBufferArray(scip, &undoneaggrvars, 2 * saggregations) );
5096 	   SCIP_CALL( SCIPallocBufferArray(scip, &undoneaggrtypes, saggregations) );
5097 	   BMSclearMemoryArray(undoneaggrtypes, saggregations);
5098 	   naggregations = 0;
5099 	
5100 	   /* get temporary memory for all clique constraints, all appearing variables and the mapping from variables to constraints */
5101 	   SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
5102 	   SCIP_CALL( SCIPallocBufferArray(scip, &usefulvars, susefulvars) );
5103 	   BMSclearMemoryArray(usefulvars, susefulvars);
5104 	   SCIP_CALL( SCIPallocBufferArray(scip, &varnconss, susefulvars + 1) );
5105 	   BMSclearMemoryArray(varnconss, susefulvars + 1);
5106 	   SCIP_CALL( SCIPallocBufferArray(scip, &maxnvarconsidx, susefulvars + 1) );
5107 	   SCIP_CALL( SCIPallocBufferArray(scip, &varconsidxs, susefulvars + 1) );
5108 	   BMSclearMemoryArray(varconsidxs, susefulvars + 1);
5109 	   nusefulvars = 0;
5110 	   nusefulconss = 0;
5111 	   maxnvars = 0;
5112 	
5113 	   /* @todo: check for round limit for adding extra clique constraints */
5114 	   /* adding clique constraints which arises from global clique information */
5115 	   if( conshdlrdata->nclqpresolve == 0 && conshdlrdata->addvariablesascliques )
5116 	   {
5117 	      SCIP_VAR** vars = SCIPgetVars(scip);
5118 	      SCIP_VAR** binvars;
5119 	      int* cliquepartition;
5120 	      int ncliques;
5121 	      int nbinvars;
5122 	      int naddconss;
5123 	
5124 	      nbinvars = SCIPgetNBinVars(scip);
5125 	      SCIP_CALL( SCIPduplicateBufferArray(scip, &binvars, vars, nbinvars) );
5126 	      SCIP_CALL( SCIPallocBufferArray(scip, &cliquepartition, nbinvars) );
5127 	
5128 	      /* @todo: check for better permutations/don't permute the first round
5129 	       * @todo: take binary variables which are not of vartype SCIP_VARTYPE_BINARY into account
5130 	       */
5131 	      SCIPrandomPermuteArray(conshdlrdata->randnumgen, (void**)binvars, 0, nbinvars);
5132 	
5133 	      /* try to create a clique-partition over all binary variables and create these cliques as new setppc constraints
5134 	       * and add them to the usefulconss array and adjust all necessary data this will hopefully lead to faster
5135 	       * detection of redundant constraints
5136 	       */
5137 	      SCIP_CALL( SCIPcalcCliquePartition(scip, binvars, nbinvars, cliquepartition, &ncliques) );
5138 	
5139 	      /* resize usefulconss array if necessary */
5140 	      SCIP_CALL( SCIPreallocBufferArray(scip, &usefulconss, nconss + ncliques) );
5141 	
5142 	      naddconss = 0;
5143 	
5144 	      /* add extra clique constraints resulting from the cliquepartition calculation to SCIP and to the local data structure */
5145 	      SCIP_CALL( addExtraCliques(scip, binvars, nbinvars, cliquepartition, ncliques, usefulconss, &nusefulconss,
5146 	            nrounds, nfixedvars, &naddconss, ndelconss, nchgcoefs, cutoff) );
5147 	
5148 	      /* bad hack, we don't want to count these artificial created constraints if they got deleted, so ndelconss
5149 	       * can become negative which will be change to zero at the end of this method if it's still negative
5150 	       */
5151 	      *ndelconss -= naddconss;
5152 	
5153 	      SCIPfreeBufferArray(scip, &cliquepartition);
5154 	      SCIPfreeBufferArray(scip, &binvars);
5155 	
5156 	      if( *cutoff )
5157 		 goto TERMINATE;
5158 	   }
5159 	
5160 	   /* start to collect setpartitioning and setpacking constraints, and try to remove fixed variables and merged these
5161 	    * constraints
5162 	    */
5163 	   SCIP_CALL( collectCliqueConss(scip, conss, nconss, usefulconss, &nusefulconss, nfixedvars, ndelconss, nchgcoefs, cutoff) );
5164 	   /* @Note: Even after the call above some constraints can have fixed variables, because it might happen that caused by
5165 	    * mergeMultiplies some variables were fixed which occurred already in previous constraints
5166 	    */
5167 	   if( *cutoff )
5168 	      goto TERMINATE;
5169 	
5170 	   /* no usefulconss found */
5171 	   if( nusefulconss <= 1 )
5172 	      goto TERMINATE;
5173 	
5174 	   /* @todo: maybe sort them after biggest indices too, or another variant would be to restore the order as they were
5175 	    *        read in
5176 	    */
5177 	   /* sort constraints first after type (partitioning before packing) and second after number of variables such that the
5178 	    * partitioning constraints have increasing number of variables and the packing constraints have decreasing number of
5179 	    * variables, because we loop from back to front we sort them downwards, so they are the other way around
5180 	    */
5181 	   SCIPsortDownPtr((void**)usefulconss, setppcConssSort, nusefulconss);
5182 	
5183 	   /* creating all necessary data in array structure, collect all clique constraint variables and occurrences */
5184 	   SCIP_CALL( collectCliqueData(scip, usefulconss, nusefulconss, usefulvars, &nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs, &maxnvars) );
5185 	   assert(maxnvars > 0);
5186 	
5187 	   /* allocate temporary memory for actual clique */
5188 	   SCIP_CALL( SCIPallocBufferArray(scip, &cliquevalues, maxnvars) );
5189 	   /* allocate temporary memory for counting an overlap of variables */
5190 	   SCIP_CALL( SCIPallocBufferArray(scip, &countofoverlapping, nusefulconss) );
5191 	
5192 	   /* sort usefulvars after indices of variables, negated and active counterparts will stand side by side */
5193 	   SCIPsortDownPtr((void**)usefulvars, SCIPvarCompActiveAndNegated, nusefulvars);
5194 	
5195 	   /* extend cliques/constraints by checking whether some variables of a second constraint are in the same clique */
5196 	   for( c = nusefulconss - 1; c >= 0 && !SCIPisStopped(scip); --c )
5197 	   {
5198 	      SCIP_VAR** cons0vars;                  /* these are the clique variables */
5199 	      SCIP_CONS* cons0;
5200 	      int ncons0vars;
5201 	      SCIP_VAR* var0;
5202 	      int v1;
5203 	      int nadded;     /* number of possible added variables to constraint */
5204 	      int cons0fixedzeros;
5205 	      int oldnchgcoefs;
5206 	#ifndef NDEBUG
5207 	      const int oldnaggrvars = *naggrvars;
5208 	#endif
5209 	      cons0 = usefulconss[c];
5210 	
5211 	      if( !SCIPconsIsActive(cons0) )
5212 	         continue;
5213 	
5214 	      /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
5215 	       * possible
5216 	       */
5217 	      SCIP_CALL( presolvePropagateCons(scip, cons0, FALSE, undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations, nfixedvars, naggrvars, ndelconss, cutoff) );
5218 	
5219 	      if( *cutoff )
5220 		 break;
5221 	
5222 	      /* we can't handle aggregated variables later on so we should have saved them for later */
5223 	      assert(*naggrvars == oldnaggrvars);
5224 	
5225 	      if( !SCIPconsIsActive(cons0) )
5226 	         continue;
5227 	
5228 	      /* we need to determine the cliquedata in each iteration because we eventual will change it later */
5229 	      consdata = SCIPconsGetData(cons0);
5230 	      assert(consdata != NULL);
5231 	
5232 	      cons0vars = consdata->vars;
5233 	      ncons0vars = consdata->nvars;
5234 	
5235 	      /* sorting array after indices of variables, negated and active counterparts will stand side by side */
5236 	      SCIPsortDownPtr((void**)cons0vars, SCIPvarCompActiveAndNegated, ncons0vars);
5237 	      /* standard setppc-sorting now lost */
5238 	      consdata->sorted = FALSE;
5239 	
5240 	      /* clique array should be long enough */
5241 	      assert(maxnvars >= ncons0vars);
5242 	
5243 	      /* clear old entries in overlapping constraint */
5244 	      BMSclearMemoryArray(countofoverlapping, nusefulconss);
5245 	
5246 	      /* calculate overlapping */
5247 	      for( v = ncons0vars - 1; v >= 0 ; --v )
5248 	      {
5249 		 var0 = cons0vars[v];
5250 	
5251 		 /* fixed variables later to the count */
5252 		 if( SCIPvarGetLbLocal(var0) > 0.5 || SCIPvarGetUbLocal(var0) < 0.5 )
5253 		    continue;
5254 	
5255 		 assert(SCIPhashmapExists(vartoindex, (void*) var0));
5256 	
5257 		 varindex = SCIPhashmapGetImageInt(vartoindex, (void*) var0);
5258 		 for( v1 = varnconss[varindex] - 1; v1 >= 0 ; --v1 )
5259 		    ++(countofoverlapping[varconsidxs[varindex][v1]]);
5260 	      }
5261 	
5262 	      oldnchgcoefs = *nchgcoefs;
5263 	      cons0fixedzeros = consdata->nfixedzeros;
5264 	
5265 	      chgcons0 = FALSE;
5266 	
5267 	      /* check for overlapping constraint before starting lifting */
5268 	      SCIP_CALL( checkForOverlapping(scip, cons0, c, c, usefulconss, nusefulconss, usefulvars, &nusefulvars, vartoindex,
5269 		    varnconss, maxnvarconsidx, varconsidxs, countofoverlapping, conshdlrdata->cliqueshrinking, &chgcons0,
5270 		    undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations,
5271 		    nfixedvars, naggrvars, nchgcoefs, ndelconss, cutoff) );
5272 	
5273 	      if( *cutoff )
5274 		 break;
5275 	
5276 	      /* we can't handle aggregated variables later on so we should have saved them for later */
5277 	      assert(*naggrvars == oldnaggrvars);
5278 	
5279 	      /* if cons0 changed, we need to reorder the variables  */
5280 	      if( chgcons0 && *nchgcoefs > oldnchgcoefs )
5281 	      {
5282 		 consdata = SCIPconsGetData(cons0);
5283 		 assert(consdata != NULL);
5284 	
5285 		 cons0vars = consdata->vars;
5286 		 ncons0vars = consdata->nvars;
5287 	
5288 		 /* sorting array after indices of variables, negated and active counterparts will stand side by side */
5289 		 SCIPsortDownPtr((void**)cons0vars, SCIPvarCompActiveAndNegated, ncons0vars);
5290 		 /* standard setppc-sorting now lost */
5291 		 consdata->sorted = FALSE;
5292 	      }
5293 	
5294 	      /* check cons0 again for redundancy/fixings, because due to fixings in all other constraints it might happen that cons0 is redundant now */
5295 	      if( consdata->nfixedones > 0 || consdata->nfixedzeros > cons0fixedzeros )
5296 	      {
5297 		 /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
5298 		  * possible
5299 		  */
5300 		 SCIP_CALL( presolvePropagateCons(scip, cons0, FALSE, undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations, nfixedvars, naggrvars, ndelconss, cutoff) );
5301 	
5302 		 if( *cutoff )
5303 		    break;
5304 	
5305 		 /* we can't handle aggregated variables later on so we should have saved them for later */
5306 		 assert(*naggrvars == oldnaggrvars);
5307 	
5308 		 if( !SCIPconsIsActive(cons0) )
5309 		    continue;
5310 	      }
5311 	
5312 	      nadded = 0;
5313 	
5314 	      /* iterate over the cliques variables and all possible new clique variables at the "same" time, determine starting
5315 	       * index
5316 	       *
5317 	       * @note: it might be better to start the first round with our computed v1, but maybe it's better to switch to
5318 	       *        trying to add all variables the second time for set packing constraints
5319 	       */
5320 	
5321 	      /* we try to add all variables to the partitioning constraints, to try to fix as much as possible */
5322 	      if( consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
5323 	         v1 = nusefulvars - 1;
5324 	      else
5325 	      {
5326 		 /* if we already ran a presolving round we want to try to add new variables */
5327 		 if( conshdlrdata->nclqpresolve > 0 )
5328 		    v1 = nusefulvars - 1;
5329 		 else
5330 		 {
5331 		    /* find start position of variable which we will try to add to our constraint, so we will get better clique constraints */
5332 		    (void) SCIPsortedvecFindDownPtr((void**)usefulvars, SCIPvarCompActiveAndNegated, (void*)cons0vars[ncons0vars - 1], nusefulvars, &v1);
5333 		    assert(v1 >= 0 && v1 < nusefulvars);
5334 		    /* if constraint is not merged and we found a variable which is negated the same as it's neighbour we have to
5335 		     * increase v1 to make sure that we don't loose this important variable */
5336 		    if( v1 + 1 < nusefulvars && ((SCIPvarIsNegated(usefulvars[v1 + 1]) && SCIPvarGetNegatedVar(usefulvars[v1 + 1]) == usefulvars[v1]) || (SCIPvarIsNegated(usefulvars[v1]) && SCIPvarGetNegatedVar(usefulvars[v1]) == usefulvars[v1 + 1])) )
5337 		       ++v1;
5338 		 }
5339 	      }
5340 	
5341 	      assert(maxnvars >= ncons0vars);
5342 	      /* initialize the cliquevalues array */
5343 	      for( v = ncons0vars - 1; v >= 0; --v )
5344 	      {
5345 	         if( SCIPvarGetLbLocal(cons0vars[v]) < 0.5 && SCIPvarGetUbLocal(cons0vars[v]) > 0.5 )
5346 	         {
5347 	            /* variable has to be either active or a negated variable of an active one */
5348 	            assert(SCIPvarIsActive(cons0vars[v]) || (SCIPvarGetStatus(cons0vars[v]) == SCIP_VARSTATUS_NEGATED &&
5349 	                  SCIPvarIsActive(SCIPvarGetNegationVar(cons0vars[v]))));
5350 	            cliquevalues[v] = SCIPvarIsActive(cons0vars[v]) ? TRUE : FALSE;
5351 	         }
5352 	      }
5353 	
5354 	      chgcons0 = FALSE;
5355 	
5356 	      /* try to lift variables to cons0 */
5357 	      SCIP_CALL( liftCliqueVariables(scip, cons0, c, usefulvars, &nusefulvars, v1, &cliquevalues, vartoindex, varnconss,
5358 	            maxnvarconsidx, varconsidxs, &maxnvars, &nadded, &chgcons0, nfixedvars, ndelconss, cutoff) );
5359 	
5360 	      if( *cutoff )
5361 		 break;
5362 	
5363 	      if( !SCIPconsIsActive(cons0) )
5364 		 continue;
5365 	
5366 	      /* check for redundant constraints due to changing cons0 */
5367 	      if( chgcons0 )
5368 	      {
5369 	         int i;
5370 	
5371 	         *firstchange = MIN(*firstchange, c);
5372 	         *firstclique = MIN(*firstclique, c);
5373 	         *lastclique = MAX(*lastclique, c);
5374 	
5375 		 /* variables array has changed due to lifting variables, so get new values */
5376 		 assert(consdata == SCIPconsGetData(cons0));
5377 		 cons0vars = consdata->vars;
5378 		 ncons0vars = consdata->nvars;
5379 	
5380 		 /* resorting array, because we added new variables, in order of indices of variables, negated
5381 		  * and active counterparts would stand side by side
5382 		  */
5383 		 SCIPsortDownPtr((void**)cons0vars, SCIPvarCompActiveAndNegated, ncons0vars);
5384 		 /* standard setppc-sorting now lost */
5385 		 consdata->sorted = FALSE;
5386 	
5387 		 /* clear old entries in overlapping constraint */
5388 	         BMSclearMemoryArray(countofoverlapping, nusefulconss);
5389 	
5390 	         for( v = ncons0vars - 1; v >= 0 ; --v )
5391 	         {
5392 	            var0 = cons0vars[v];
5393 	
5394 	            /* fixed variables later to the count */
5395 	            if( SCIPvarGetLbLocal(var0) > 0.5 || SCIPvarGetUbLocal(var0) < 0.5 )
5396 	               continue;
5397 	
5398 	            assert(SCIPhashmapExists(vartoindex, (void*) var0));
5399 	
5400 	            varindex = SCIPhashmapGetImageInt(vartoindex, (void*) var0);
5401 	            for( i = varnconss[varindex] - 1; i >= 0 ; --i )
5402 	               ++(countofoverlapping[varconsidxs[varindex][i]]);
5403 	         }
5404 	
5405 		 chgcons0 = FALSE;
5406 	
5407 		 /* check for overlapping constraint after lifting, in the first round we will only check up front */
5408 		 SCIP_CALL( checkForOverlapping(scip, cons0, c, (conshdlrdata->nclqpresolve > 0) ? nusefulconss : c,
5409 		       usefulconss, nusefulconss, usefulvars, &nusefulvars, vartoindex, varnconss, maxnvarconsidx, varconsidxs,
5410 		       countofoverlapping, conshdlrdata->cliqueshrinking, &chgcons0,
5411 		       undoneaggrvars, undoneaggrtypes, &naggregations, &saggregations,
5412 		       nfixedvars, naggrvars, nchgcoefs, ndelconss, cutoff) );
5413 	
5414 		 if( *cutoff )
5415 		    break;
5416 	
5417 		 /* we can't handle aggregated variables later on so we should have saved them for later */
5418 		 assert(*naggrvars == oldnaggrvars);
5419 	      }
5420 	   }
5421 	
5422 	 TERMINATE:
5423 	   SCIPfreeBufferArrayNull(scip, &countofoverlapping);
5424 	   SCIPfreeBufferArrayNull(scip, &cliquevalues);
5425 	
5426 	   /* free temporary memory for constraints, variables and the mapping between them in reverse order as they were
5427 	    * allocated
5428 	    */
5429 	   for( c = nusefulvars; c > 0; --c )
5430 	   {
5431 	      if( varconsidxs[c] != NULL )
5432 	      {
5433 	         SCIPfreeBufferArrayNull(scip, &(varconsidxs[c]));
5434 	      }
5435 	   }
5436 	
5437 	   SCIPfreeBufferArray(scip, &varconsidxs);
5438 	   SCIPfreeBufferArray(scip, &maxnvarconsidx);
5439 	   SCIPfreeBufferArray(scip, &varnconss);
5440 	   SCIPfreeBufferArray(scip, &usefulvars);
5441 	   SCIPfreeBufferArray(scip, &usefulconss);
5442 	
5443 	   /* perform all collected aggregations */
5444 	   if( !*cutoff && naggregations > 0 && !SCIPdoNotAggr(scip) )
5445 	   {
5446 	      SCIP_CALL( performAggregations(scip, conshdlrdata, undoneaggrvars, undoneaggrtypes, naggregations, naggrvars, cutoff) );
5447 	   }
5448 	
5449 	   /* free temporary memory for the aggregation storage */
5450 	   SCIPfreeBufferArray(scip, &undoneaggrtypes);
5451 	   SCIPfreeBufferArray(scip, &undoneaggrvars);
5452 	
5453 	   /* free hashmap */
5454 	   SCIPhashmapFree(&vartoindex);
5455 	
5456 	   if( *ndelconss < 0 )
5457 	      *ndelconss = 0;
5458 	
5459 	   return SCIP_OKAY;
5460 	}
5461 	
5462 	
5463 	/** add cliques to SCIP */
5464 	static
5465 	SCIP_RETCODE addCliques(
5466 	   SCIP*                 scip,               /**< SCIP data structure */
5467 	   SCIP_CONS**           conss,              /**< constraint set */
5468 	   int                   nconss,             /**< number of constraints in constraint set */
5469 	   int                   firstclique,        /**< first constraint to start to add cliques */
5470 	   int                   lastclique,         /**< last constraint to start to add cliques */
5471 	   int*                  naddconss,          /**< pointer to count number of added constraints */
5472 	   int*                  ndelconss,          /**< pointer to count number of deleted constraints */
5473 	   int*                  nchgbds,            /**< pointer to count number of changed bounds */
5474 	   SCIP_Bool*            cutoff              /**< pointer to store if the problem is infeasible due to a fixing */
5475 	   )
5476 	{
5477 	   SCIP_CONS* cons;
5478 	   SCIP_CONSDATA* consdata;
5479 	   SCIP_Bool infeasible;
5480 	   int nlocalbdchgs;
5481 	   int c;
5482 	
5483 	   assert(scip != NULL);
5484 	   assert(firstclique >= 0);
5485 	   assert(lastclique <= nconss);
5486 	   assert(conss != NULL || ((nconss == 0) && (lastclique == 0)));
5487 	
5488 	   /* add clique and implication information */
5489 	   for( c = firstclique; c < lastclique; ++c )
5490 	   {
5491 	      cons = conss[c]; /*lint !e613*/
5492 	      assert(cons != NULL);
5493 	
5494 	      /* ignore deleted constraints */
5495 	      if( !SCIPconsIsActive(cons) )
5496 	         continue;
5497 	
5498 	      nlocalbdchgs = 0;
5499 	      SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, &nlocalbdchgs, cutoff) );
5500 	      *nchgbds += nlocalbdchgs;
5501 	
5502 	      if( *cutoff )
5503 	         return SCIP_OKAY;
5504 	
5505 	      consdata = SCIPconsGetData(cons);
5506 	      assert(consdata != NULL);
5507 	
5508 	      if( SCIPconsIsDeleted(cons) )
5509 	         continue;
5510 	
5511 	      if( !consdata->cliqueadded && consdata->nvars >= 2 )
5512 	      {
5513 	         /* add a set partitioning / packing constraint as clique */
5514 	         if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING || (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
5515 	         {
5516 	            SCIP_CALL( SCIPaddClique(scip, consdata->vars, NULL, consdata->nvars,
5517 	                  ((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING), &infeasible, &nlocalbdchgs) );
5518 	            *nchgbds += nlocalbdchgs;
5519 	
5520 	            if( infeasible )
5521 	            {
5522 	               *cutoff = TRUE;
5523 	               return SCIP_OKAY;
5524 	            }
5525 	         }
5526 	         else if( consdata->nvars == 2 && !SCIPconsIsModifiable(cons) )
5527 	         {
5528 	            /* a two-variable set covering constraint x + y >= 1 yields the implication x == 0 -> y == 1 */
5529 	            SCIP_CALL( SCIPaddVarImplication(scip, consdata->vars[0], FALSE, consdata->vars[1],
5530 	                  SCIP_BOUNDTYPE_LOWER, 1.0, &infeasible, &nlocalbdchgs) );
5531 	            *nchgbds += nlocalbdchgs;
5532 	
5533 	            if( infeasible )
5534 	            {
5535 	               *cutoff = TRUE;
5536 	               return SCIP_OKAY;
5537 	            }
5538 	         }
5539 	         consdata->cliqueadded = TRUE;
5540 	      }
5541 	   }
5542 	
5543 	   return SCIP_OKAY;
5544 	}
5545 	
5546 	/** perform multi-aggregation on variables resulting from a set-partitioning/-packing constraint */
5547 	static
5548 	SCIP_RETCODE multiAggregateBinvar(
5549 	   SCIP*                 scip,               /**< SCIP data structure */
5550 	   SCIP_Bool             linearconshdlrexist,/**< does the linear constraint handler exist, necessary for multi-aggregations */
5551 	   SCIP_VAR**            vars,               /**< all variables including the variable to which will be multi-aggregated */
5552 	   int                   nvars,              /**< number of all variables */
5553 	   int                   pos,                /**< position of variable for multi-aggregation */
5554 	   SCIP_Bool*            infeasible,         /**< pointer to store infeasibility status of aggregation */
5555 	   SCIP_Bool*            aggregated          /**< pointer to store aggregation status */
5556 	   )
5557 	{
5558 	   SCIP_VAR** tmpvars;
5559 	   SCIP_Real* scalars;
5560 	   int v;
5561 	
5562 	   assert(scip != NULL);
5563 	   assert(vars != NULL);
5564 	   assert(nvars > 1);
5565 	   assert(0 <= pos && pos < nvars);
5566 	   assert(infeasible != NULL);
5567 	   assert(aggregated != NULL);
5568 	
5569 	   if( nvars == 2 )
5570 	   {
5571 	      SCIP_Bool redundant;
5572 	
5573 	      /* perform aggregation on variables resulting from a set-packing constraint */
5574 	      SCIP_CALL( SCIPaggregateVars(scip, vars[pos], vars[nvars - pos - 1], 1.0, 1.0, 1.0, infeasible, &redundant, aggregated) );
5575 	
5576 	      if( *aggregated )
5577 	         SCIPdebugMsg(scip, "aggregated %s = 1 - %s\n", SCIPvarGetName(vars[pos]), SCIPvarGetName(vars[nvars - pos - 1]));
5578 	
5579 	      return SCIP_OKAY;
5580 	   }
5581 	
5582 	   if( !linearconshdlrexist )
5583 	   {
5584 	      *infeasible = FALSE;
5585 	      return SCIP_OKAY;
5586 	   }
5587 	
5588 	   /* if the last variable will be multi-aggregated, we do not need to copy the variables */
5589 	   if( pos == nvars - 1 )
5590 	      tmpvars = vars;
5591 	   else
5592 	   {
5593 	      /* copy variables for aggregation */
5594 	      SCIP_CALL( SCIPduplicateBufferArray(scip, &tmpvars, vars, nvars) );
5595 	      tmpvars[pos] = tmpvars[nvars - 1];
5596 	   }
5597 	
5598 	   SCIP_CALL( SCIPallocBufferArray(scip, &scalars, nvars - 1) );
5599 	   /* initialize scalars */
5600 	   for( v = nvars - 2; v >= 0; --v )
5601 	      scalars[v] = -1.0;
5602 	
5603 	   SCIPdebugMsg(scip, "multi-aggregating binary variable <%s> (locks: [%d,%d]; to %d variables)\n",
5604 	      SCIPvarGetName(vars[pos]), SCIPvarGetNLocksDownType(vars[pos], SCIP_LOCKTYPE_MODEL),
5605 	      SCIPvarGetNLocksUpType(vars[pos], SCIP_LOCKTYPE_MODEL), nvars - 1);
5606 	
5607 	   /* perform multi-aggregation */
5608 	   SCIP_CALL( SCIPmultiaggregateVar(scip, vars[pos], nvars - 1, tmpvars, scalars, 1.0, infeasible, aggregated) );
5609 	   assert(!(*infeasible));
5610 	
5611 	   SCIPfreeBufferArray(scip, &scalars);
5612 	
5613 	   if( pos < nvars - 1 )
5614 	   {
5615 	      assert(tmpvars != vars);
5616 	      SCIPfreeBufferArray(scip, &tmpvars);
5617 	   }
5618 	
5619 	   return SCIP_OKAY;
5620 	}
5621 	
5622 	/** determine singleton variables in set-partitioning/-packing constraints, or doubleton variables (active and negated)
5623 	 *  in any combination of set-partitioning and set-packing constraints
5624 	 *
5625 	 *  we can multi-aggregate the variable and either change the set-partitioning constraint to a set-packing constraint or
5626 	 *  even delete it
5627 	 *
5628 	 *  1. c1: x + y + z = 1,  uplocks(x) = 1, downlocks(x) = 1               =>  x = 1 - y - z and change c1 to y + z <= 1
5629 	 *
5630 	 *  2. c2: x + y + z <= 1,  uplocks(x) = 1, downlocks(x) = 0, obj(x) < 0  =>  x = 1 - y - z and change c2 to y + z <= 1
5631 	 *
5632 	 *  3. d1: x + y + z <= 1 and d2: ~x + u + v <= 1, uplocks(x) = 1, downlocks(x) = 1
5633 	 *    a)  obj(x) <= 0                                                     =>  x = 1 - y - z and delete d1
5634 	 *    b)  obj(x) > 0                                                      => ~x = 1 - u - v and delete d2
5635 	 *
5636 	 *  4. e1: x + y + z == 1 and e2: ~x + u + v (<= or ==) 1, uplocks(x) = (1 or 2), downlocks(x) = 2
5637 	 *                                                                        =>  x = 1 - y - z and delete e1
5638 	 *
5639 	 *  we can also aggregate a variable in a set-packing constraint with only two variables when the uplocks are equal to
5640 	 *  one and then delete this constraint
5641 	 *
5642 	 *  5. f1: x + y <= 1,  uplocks(x) = 1, obj(x) <= 0                       =>  x = 1 - y and delete f1
5643 	 *
5644 	 *  @todo might want to multi-aggregate variables even with more locks, when the fill in is still smaller or equal to
5645 	 *        the old number of non-zeros, e.g.
5646 	 *
5647 	 *        x + y + z = 1
5648 	 *        ~x + u + v <=/= 1
5649 	 *        ~x + w <= 1
5650 	 */
5651 	static
5652 	SCIP_RETCODE removeDoubleAndSingletonsAndPerformDualpresolve(
5653 	   SCIP*                 scip,               /**< SCIP data structure */
5654 	   SCIP_CONS**           conss,              /**< constraint set */
5655 	   int                   nconss,             /**< number of constraints in constraint set */
5656 	   SCIP_Bool             dualpresolvingenabled,/**< is dual presolving enabled */
5657 	   SCIP_Bool             linearconshdlrexist,/**< does the linear constraint handler exist, necessary for
5658 	                                              *   multi-aggregations
5659 	                                              */
5660 	   int*                  nfixedvars,         /**< pointer to count number of deleted variables */
5661 	   int*                  naggrvars,          /**< pointer to count number of aggregated variables */
5662 	   int*                  ndelconss,          /**< pointer to count number of deleted constraints */
5663 	   int*                  nchgcoefs,          /**< pointer to count number of changed coefficients */
5664 	   int*                  nchgsides,          /**< pointer to count number of changed left hand sides */
5665 	   SCIP_Bool*            cutoff              /**< pointer to store if a cut off was detected */
5666 	   )
5667 	{
5668 	   SCIP_CONS** usefulconss;
5669 	   SCIP_VAR** binvars;
5670 	   SCIP_HASHMAP* vartoindex;
5671 	   SCIP_Bool* chgtype;
5672 	   int* considxs;
5673 	   int* posincons;
5674 	   SCIP_Bool infeasible;
5675 	   SCIP_Bool aggregated;
5676 	   SCIP_Bool donotaggr;
5677 	   SCIP_Bool donotmultaggr;
5678 	   SCIP_Bool mustcheck;
5679 	   SCIP_Bool addcut;
5680 	   int nposvars;
5681 	   int ndecs;
5682 	   int nbinvars;
5683 	   int nposbinvars;
5684 	   int nuplocks;
5685 	   int ndownlocks;
5686 	#ifndef NDEBUG
5687 	   int posreplacements = 0;
5688 	#endif
5689 	   int nhashmapentries;
5690 	   int nlocaladdconss;
5691 	   int v;
5692 	   int c;
5693 	
5694 	   assert(scip != NULL);
5695 	   assert(conss != NULL);
5696 	   assert(nconss > 0);
5697 	   assert(nfixedvars != NULL);
5698 	   assert(naggrvars != NULL);
5699 	   assert(ndelconss != NULL);
5700 	   assert(nchgcoefs != NULL);
5701 	   assert(nchgsides != NULL);
5702 	
5703 	   nbinvars = SCIPgetNBinVars(scip);
5704 	   nposbinvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
5705 	   assert(nbinvars + SCIPgetNIntVars(scip) + SCIPgetNImplVars(scip) == nposbinvars);
5706 	
5707 	   binvars = SCIPgetVars(scip);
5708 	
5709 	   /* determine number for possible multi-aggregations */
5710 	   nposvars = 0;
5711 	   for( v = nposbinvars - 1; v >= 0; --v )
5712 	   {
5713 	      assert(SCIPvarGetType(binvars[v]) != SCIP_VARTYPE_CONTINUOUS);
5714 	
5715 	      if( v < nbinvars || SCIPvarIsBinary(binvars[v]) )
5716 	      {
5717 	         nuplocks = SCIPvarGetNLocksUpType(binvars[v], SCIP_LOCKTYPE_MODEL);
5718 	         ndownlocks = SCIPvarGetNLocksDownType(binvars[v], SCIP_LOCKTYPE_MODEL);
5719 	
5720 	         if( (nuplocks == 1 && ndownlocks <= 1) || (nuplocks <= 1 && ndownlocks == 1) || (nuplocks <= 2 && ndownlocks <= 2 && SCIPvarGetNegatedVar(binvars[v]) != NULL) )
5721 	            ++nposvars;
5722 	      }
5723 	   }
5724 	
5725 	   SCIPdebugMsg(scip, "found %d binary variables for possible multi-aggregation\n", nposvars);
5726 	
5727 	   if( nposvars == 0 )
5728 	      return SCIP_OKAY;
5729 	
5730 	   /* a hashmap from var to index when found in a set-partitioning constraint */
5731 	   SCIP_CALL( SCIPhashmapCreate(&vartoindex, SCIPblkmem(scip), nposvars) );
5732 	
5733 	   /* get temporary memory */
5734 	   SCIP_CALL( SCIPallocBufferArray(scip, &chgtype, nconss) );
5735 	   BMSclearMemoryArray(chgtype, nconss);
5736 	
5737 	   SCIP_CALL( SCIPallocBufferArray(scip, &considxs, nposbinvars) );
5738 	   SCIP_CALL( SCIPallocBufferArray(scip, &posincons, nposbinvars) );
5739 	
5740 	   SCIP_CALL( SCIPduplicateBufferArray(scip, &usefulconss, conss, nconss) );
5741 	   /* sort constraints */
5742 	   SCIPsortPtr((void**)usefulconss, setppcConssSort2, nconss);
5743 	
5744 	   nhashmapentries = 0;
5745 	   ndecs = 0;
5746 	   donotaggr = SCIPdoNotAggr(scip);
5747 	   donotmultaggr = SCIPdoNotMultaggr(scip);
5748 	   assert(!donotaggr || !donotmultaggr);
5749 	
5750 	   /* determine singleton variables in set-partitioning/-packing constraints, or doubleton variables (active and
5751 	    * negated) in any combination of set-partitioning and set-packing constraints
5752 	    *
5753 	    * we can multi-aggregate the variable and either change the set-partitioning constraint to a set-packing constraint
5754 	    * or even delete it
5755 	    */
5756 	   for( c = 0; c < nconss; ++c )
5757 	   {
5758 	      SCIP_CONS* cons;
5759 	      SCIP_CONSDATA* consdata;
5760 	      int oldnfixedvars;
5761 	      nlocaladdconss = 0;
5762 	
5763 	      cons = usefulconss[c];
5764 	      assert(cons != NULL);
5765 	
5766 	      if( SCIPconsIsDeleted(cons) )
5767 	         continue;
5768 	
5769 	      consdata = SCIPconsGetData(cons);
5770 	      assert(consdata != NULL);
5771 	
5772 	      /* if we cannot find any constraint to perform a useful multi-aggregation, stop */
5773 	      if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING )
5774 	         break;
5775 	
5776 	      if( !SCIPconsIsChecked(cons) )
5777 	         continue;
5778 	
5779 	      if( SCIPconsIsModifiable(cons) )
5780 	         continue;
5781 	
5782 	      /* update the variables */
5783 	      SCIP_CALL( applyFixings(scip, cons, &nlocaladdconss, ndelconss, nfixedvars, cutoff) );
5784 	
5785 	      if( *cutoff )
5786 	         break;
5787 	
5788 	      /* due to resolving multi-aggregations a constraint can become deleted */
5789 	      if( SCIPconsIsDeleted(cons) )
5790 	         continue;
5791 	
5792 	      SCIP_CALL( processFixings(scip, cons, cutoff, nfixedvars, &addcut, &mustcheck) );
5793 	      assert(!addcut);
5794 	
5795 	      if( *cutoff )
5796 	         break;
5797 	
5798 	      if( SCIPconsIsDeleted(cons) )
5799 	         continue;
5800 	
5801 	      oldnfixedvars = *nfixedvars;
5802 	
5803 	      /* merging unmerged constraints */
5804 	      SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, cutoff) );
5805 	
5806 	      if( *cutoff )
5807 	         break;
5808 	
5809 	      if( SCIPconsIsDeleted(cons) )
5810 	         continue;
5811 	
5812 	      if( oldnfixedvars < *nfixedvars )
5813 	      {
5814 	         /* update the variables */
5815 	         SCIP_CALL( applyFixings(scip, cons, &nlocaladdconss, ndelconss, nfixedvars, cutoff) );
5816 	         assert(!SCIPconsIsDeleted(cons));
5817 	         assert(nlocaladdconss == 0);
5818 	         assert(!*cutoff);
5819 	
5820 	         if( SCIPconsIsDeleted(cons) )
5821 	            continue;
5822 	      }
5823 	
5824 	      /* if the constraint was not merged and consists of a variable with its negation, the constraint is redundant */
5825 	      if( consdata->nvars < 2 )
5826 	      {
5827 	         /* deleting redundant set-packing constraint */
5828 	         if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
5829 	         {
5830 		    SCIPdebugMsg(scip, "deleting redundant set-packing constraint <%s>\n", SCIPconsGetName(cons));
5831 	
5832 	            SCIP_CALL( SCIPdelCons(scip, cons) );
5833 	            ++(*ndelconss);
5834 	
5835 	            continue;
5836 	         }
5837 	         else
5838 	         {
5839 	            SCIP_Bool fixed;
5840 	
5841 	            assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
5842 	
5843 	            if( consdata->nvars == 0 )
5844 	            {
5845 	               SCIPdebugMsg(scip, "empty set partition constraint <%s> led to infeasibility\n", SCIPconsGetName(cons));
5846 	
5847 	               *cutoff = TRUE;
5848 	               break;
5849 	            }
5850 	
5851 		    SCIPdebugMsg(scip, "fixing <%s> to 1 because this variable is the last variable in a set partition constraint <%s>\n", SCIPvarGetName(consdata->vars[0]), SCIPconsGetName(cons));
5852 	
5853 	            SCIP_CALL( SCIPfixVar(scip, consdata->vars[0], 1.0, &infeasible, &fixed) );
5854 	            assert(!infeasible);
5855 	
5856 	            if( fixed )
5857 	               ++(*nfixedvars);
5858 	
5859 	            assert(SCIPvarGetLbGlobal(consdata->vars[0]) > 0.5);
5860 	
5861 		    SCIPdebugMsg(scip, "deleting redundant set-partition constraint <%s>\n", SCIPconsGetName(cons));
5862 	
5863 	            SCIP_CALL( SCIPdelCons(scip, cons) );
5864 	            ++(*ndelconss);
5865 	
5866 	            continue;
5867 	         }
5868 	      }
5869 	
5870 	      /* perform dualpresolve on set-packing constraints with exactly two variables */
5871 	      if( !donotaggr && consdata->nvars == 2 && dualpresolvingenabled && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
5872 	      {
5873 	         SCIP_VAR* var;
5874 	         SCIP_Real objval;
5875 	         SCIP_Bool redundant;
5876 	
5877 	         var = consdata->vars[0];
5878 	         assert(var != NULL);
5879 	         assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
5880 	
5881 	         SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
5882 	
5883 	         nuplocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
5884 	
5885 	         if( nuplocks == 1 && objval <= 0 )
5886 	         {
5887 	            /* perform aggregation on variables resulting from a set-packing constraint */
5888 	            SCIP_CALL( SCIPaggregateVars(scip, var, consdata->vars[1], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
5889 	
5890 	            if( infeasible )
5891 	            {
5892 	               *cutoff = TRUE;
5893 	               break;
5894 	            }
5895 	
5896 	            if( aggregated )
5897 	            {
5898 	               SCIPdebugMsg(scip, "dualpresolve, aggregated %s + %s = 1, in set-packing constraint %s\n", SCIPvarGetName(var), SCIPvarGetName(consdata->vars[1]), SCIPconsGetName(cons));
5899 	               ++(*naggrvars);
5900 	
5901 	               SCIP_CALL( SCIPdelCons(scip, cons) );
5902 	               ++(*ndelconss);
5903 	            }
5904 	
5905 	            continue;
5906 	         }
5907 	         else
5908 	         {
5909 	            var = consdata->vars[1];
5910 	            assert(var != NULL);
5911 	            assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
5912 	
5913 	            SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
5914 	
5915 	            nuplocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
5916 	
5917 	            if( nuplocks == 1 && objval <= 0 )
5918 	            {
5919 	               /* perform aggregation on variables resulting from a set-packing constraint */
5920 	               SCIP_CALL( SCIPaggregateVars(scip, var, consdata->vars[0], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
5921 	
5922 	               if( infeasible )
5923 	               {
5924 	                  *cutoff = TRUE;
5925 	                  break;
5926 	               }
5927 	
5928 	               if( aggregated )
5929 	               {
5930 	                  SCIPdebugMsg(scip, "dualpresolve, aggregated %s + %s = 1, in set-packing constraint %s\n", SCIPvarGetName(var), SCIPvarGetName(consdata->vars[0]), SCIPconsGetName(cons));
5931 	                  ++(*naggrvars);
5932 	
5933 	                  SCIP_CALL( SCIPdelCons(scip, cons) );
5934 	                  ++(*ndelconss);
5935 	               }
5936 	
5937 	               continue;
5938 	            }
5939 	         }
5940 	      }
5941 	      else if( !donotaggr && consdata->nvars == 2 && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
5942 	      {
5943 	         SCIP_Bool redundant;
5944 	
5945 	         /* perform aggregation on variables resulting from a set-partitioning constraint */
5946 	         SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
5947 	
5948 	         if( infeasible )
5949 	         {
5950 	            *cutoff = TRUE;
5951 	            break;
5952 	         }
5953 	
5954 	         if( aggregated )
5955 	         {
5956 	            SCIPdebugMsg(scip, "aggregated %s + %s = 1, in set-partition constraint %s\n", SCIPvarGetName(consdata->vars[0]), SCIPvarGetName(consdata->vars[1]), SCIPconsGetName(cons));
5957 	            ++(*naggrvars);
5958 	
5959 	            SCIP_CALL( SCIPdelCons(scip, cons) );
5960 	            ++(*ndelconss);
5961 	         }
5962 	
5963 	         continue;
5964 	      }
5965 	
5966 	      /* we already found all possible variables for multi-aggregation */
5967 	      if( ndecs >= nposvars )
5968 	         continue;
5969 	
5970 	      /* no multi aggregation is allowed, so we can continue */
5971 	      if( donotmultaggr )
5972 	         continue;
5973 	
5974 	      /* if the following condition does not hold, we have an unmerged constraint, and we might need to merge it first */
5975 	      assert(nposbinvars >= consdata->nvars);
5976 	
5977 	      /* search for possible variables for multi-aggregation */
5978 	      for( v = consdata->nvars - 1; v >= 0; --v )
5979 	      {
5980 	         SCIP_VAR* var;
5981 	         SCIP_CONS* constoupdate;
5982 	         int deleteconsindex = -1;
5983 	
5984 	         constoupdate = cons;
5985 	         var = consdata->vars[v];
5986 	         assert(var != NULL);
5987 	         assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
5988 	         assert(!SCIPconsIsDeleted(cons));
5989 	
5990 	         aggregated = FALSE;
5991 	         nuplocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
5992 	         ndownlocks = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL);
5993 	         assert(nuplocks >= 1 && ndownlocks >= 0); /* we are only treating set partitioning and set packing constraints, so every variable in there should have an uplock */
5994 	
5995 	         if( dualpresolvingenabled && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING && nuplocks <= 1 && nuplocks + ndownlocks <= 2 )
5996 	         {
5997 	            assert(nuplocks == 1 && ndownlocks <= 1);
5998 	
5999 	            /* we found a redundant variable in a set-partitioning constraint */
6000 	            if( ndownlocks == 0 )
6001 	            {
6002 	               SCIP_Real objval;
6003 	
6004 	               SCIP_CALL( SCIPvarGetAggregatedObj(var, &objval) );
6005 	
6006 	               /* if the objective value is >= 0 the fixing is normally done by the dualfix presolver */
6007 	               if( !SCIPisNegative(scip, objval) )
6008 	               {
6009 	                  SCIP_Bool fixed;
6010 	
6011 	                  SCIPdebugMsg(scip, "dual-fixing of variable <%s> to 0.0\n", SCIPvarGetName(var));
6012 	
6013 	                  SCIP_CALL( SCIPfixVar(scip, var, 0.0, &infeasible, &fixed) );
6014 	                  assert(!infeasible);
6015 	                  assert(fixed);
6016 	
6017 	                  ++(*nfixedvars);
6018 	               }
6019 	               else
6020 	               {
6021 	                  SCIPdebugMsg(scip, "multi-aggregating in set-packing constraint\n");
6022 	
6023 	                  /* perform aggregation on variables resulting from a set-packing constraint */
6024 	                  SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
6025 	
6026 	                  if( infeasible )
6027 	                  {
6028 	                     *cutoff = TRUE;
6029 	                     break;
6030 	                  }
6031 	               }
6032 	
6033 	               ++ndecs;
6034 	            }
6035 	            else if( ndownlocks == 1 && SCIPvarGetNegatedVar(var) != NULL )
6036 	            {
6037 	               SCIP_CONSDATA* aggrconsdata;
6038 	               SCIP_VAR* negvar;
6039 	               SCIP_VAR* activevar;
6040 	               SCIP_Real objval;
6041 	               int multaggridx;
6042 	               int notmultaggridx;
6043 	               int image;
6044 	               int consindex;
6045 	               int varindex;
6046 	
6047 	               assert(!SCIPhashmapExists(vartoindex, (void*) var));
6048 	
6049 	               negvar = SCIPvarGetNegatedVar(var);
6050 	
6051 	               /* if we found a new variable add it to the data */
6052 	               if( !SCIPhashmapExists(vartoindex, (void*) negvar) )
6053 	               {
6054 	                  ++nhashmapentries;
6055 	                  SCIP_CALL( SCIPhashmapInsertInt(vartoindex, (void*) var, nhashmapentries) );
6056 	
6057 	                  considxs[nhashmapentries - 1] = c;
6058 	                  posincons[nhashmapentries - 1] = v;
6059 	
6060 	#ifndef NDEBUG
6061 	                  ++posreplacements;
6062 	#endif
6063 	                  continue;
6064 	               }
6065 	
6066 	               assert(SCIPhashmapExists(vartoindex, (void*) negvar));
6067 	               image = SCIPhashmapGetImageInt(vartoindex, (void*) negvar);
6068 	               assert(image > 0 && image <= nhashmapentries);
6069 	
6070 	               consindex = considxs[image - 1];
6071 	               assert(0 <= consindex && consindex < nconss);
6072 	
6073 	               /* if the following assert fails, the constraint was not merged, or something really strange happened */
6074 	               assert(consindex < c);
6075 	
6076 	               ++ndecs;
6077 	#ifndef NDEBUG
6078 	               --posreplacements;
6079 	#endif
6080 	               assert(posreplacements >= 0);
6081 	
6082 	               varindex = posincons[image - 1];
6083 	               considxs[image - 1] = -1;
6084 	               posincons[image - 1] = -1;
6085 	               SCIP_CALL( SCIPhashmapRemove(vartoindex, (void*) negvar) );
6086 	
6087 	               /* if two variables in one constraint might be multi-aggregated, it might happen that this constraint was already removed */
6088 	               if( SCIPconsIsDeleted(usefulconss[consindex]) )
6089 	                  continue;
6090 	
6091 	               aggrconsdata = SCIPconsGetData(usefulconss[consindex]);
6092 	               assert(aggrconsdata != NULL);
6093 	               assert((SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PACKING);
6094 	               assert(0 <= varindex);
6095 	
6096 	               /* it might be that due to other multi-aggregations the constraint has fewer variables than when we
6097 	                * remembered the position, therefore we need to find the variable again
6098 	                */
6099 	               if( varindex >= aggrconsdata->nvars || aggrconsdata->vars[varindex] != negvar )
6100 	               {
6101 	                  int v2;
6102 	
6103 	                  /* if the following assert is raised, then the constraint is redundant and we do not need to aggregate
6104 	                   * anymore and can delete this constraint
6105 	                   */
6106 	                  assert(aggrconsdata->nvars >= 2);
6107 	
6108 	                  for( v2 = aggrconsdata->nvars - 1; v2 >= 0; --v2 )
6109 	                  {
6110 	                     if( aggrconsdata->vars[v2] == negvar )
6111 	                        break;
6112 	                  }
6113 	                  assert(v2 >= 0);
6114 	
6115 	                  varindex = v2;
6116 	               }
6117 	               assert(0 <= varindex && varindex < aggrconsdata->nvars);
6118 	               assert(aggrconsdata->vars[varindex] == negvar);
6119 	               assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(negvar) == SCIP_VARSTATUS_NEGATED);
6120 	
6121 	               /* determine active variable and constraint that corresponds to */
6122 	               if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6123 	               {
6124 	                  activevar = negvar;
6125 	                  multaggridx = consindex;
6126 	                  notmultaggridx = c;
6127 	               }
6128 	               else
6129 	               {
6130 	                  activevar = var;
6131 	                  multaggridx = c;
6132 	                  notmultaggridx = consindex;
6133 	               }
6134 	               objval = SCIPvarGetObj(activevar);
6135 	
6136 	               SCIPdebugMsg(scip, "multi-aggregating in two set-packing constraint\n");
6137 	
6138 	               if( objval <= 0.0 )
6139 	               {
6140 	                  /* perform aggregation on variables resulting from a set-packing constraint */
6141 	                  if( multaggridx == c )
6142 	                  {
6143 	                     SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
6144 	                  }
6145 	                  else
6146 	                  {
6147 	                     SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, aggrconsdata->vars, aggrconsdata->nvars, varindex, &infeasible, &aggregated) );
6148 	                  }
6149 	                  deleteconsindex = multaggridx;
6150 	               }
6151 	               else
6152 	               {
6153 	                  /* perform aggregation on variables resulting from a set-packing constraint */
6154 	                  /* coverity[copy_paste_error] */
6155 	                  if( multaggridx == c )
6156 	                  {
6157 	                     SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, aggrconsdata->vars, aggrconsdata->nvars, varindex, &infeasible, &aggregated) );
6158 	                  }
6159 	                  else
6160 	                  {
6161 	                     SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
6162 	                  }
6163 	                  deleteconsindex = notmultaggridx;
6164 	               }
6165 	
6166 	               if( infeasible )
6167 	               {
6168 	                  *cutoff = TRUE;
6169 	                  break;
6170 	               }
6171 	
6172 	               assert(deleteconsindex >= 0 && deleteconsindex <= c);
6173 	            }
6174 	         }
6175 	         /* we found a redundant variable in a set-partitioning constraint */
6176 	         else if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING && nuplocks == 1 && ndownlocks == 1 )
6177 	         {
6178 	            SCIPdebugMsg(scip, "multi-aggregating in set-partitioning constraint\n");
6179 	
6180 	            /* perform aggregation on variables resulting from a set-partitioning constraint */
6181 	            SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
6182 	
6183 	            if( infeasible )
6184 	            {
6185 	               *cutoff = TRUE;
6186 	               break;
6187 	            }
6188 	
6189 	            ++ndecs;
6190 	         }
6191 	         /* we might have found a redundant variable */
6192 	         else if( ndownlocks <= 2 && nuplocks <= 2 && SCIPvarGetNegatedVar(var) != NULL )
6193 	         {
6194 	            SCIP_CONSDATA* aggrconsdata;
6195 	            int image;
6196 	            int consindex;
6197 	            int varindex;
6198 	
6199 	            /* if we have two times the same variable in a set-partitioning constraint, we cannot aggregate this */
6200 	            if( SCIPhashmapExists(vartoindex, (void*) var) )
6201 	            {
6202 	               image = SCIPhashmapGetImageInt(vartoindex, (void*) var);
6203 	               assert(image > 0 && image <= nhashmapentries);
6204 	
6205 	               assert(0 <= considxs[image - 1] && considxs[image - 1] < nconss);
6206 	               assert(SCIPconsIsDeleted(usefulconss[considxs[image - 1]]) || chgtype[considxs[image - 1]] || (0 <= posincons[image - 1] && posincons[image - 1] < SCIPconsGetData(usefulconss[considxs[image - 1]])->nvars));
6207 	
6208 	               considxs[image - 1] = -1;
6209 	               posincons[image - 1] = -1;
6210 	
6211 	               SCIP_CALL( SCIPhashmapRemove(vartoindex, (void*) var) );
6212 	
6213 	#ifndef NDEBUG
6214 	               --posreplacements;
6215 	#endif
6216 	               assert(posreplacements >= 0);
6217 	
6218 	               continue;
6219 	            }
6220 	            else if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
6221 	            {
6222 	               /* if we found a new variable add it to the data */
6223 	               if( !SCIPhashmapExists(vartoindex, (void*) SCIPvarGetNegatedVar(var)) )
6224 	               {
6225 	                  assert(!SCIPhashmapExists(vartoindex, (void*) var));
6226 	
6227 	                  ++nhashmapentries;
6228 	                  SCIP_CALL( SCIPhashmapInsertInt(vartoindex, (void*) var, nhashmapentries) );
6229 	
6230 	                  considxs[nhashmapentries - 1] = c;
6231 	                  posincons[nhashmapentries - 1] = v;
6232 	
6233 	#ifndef NDEBUG
6234 	                  ++posreplacements;
6235 	#endif
6236 	                  continue;
6237 	               }
6238 	            }
6239 	            else
6240 	            {
6241 	               assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING);
6242 	
6243 	               /* the negated variable did not occur in a set partitioning constraint (those will be iterated over
6244 	                * first), so we cannot aggregate this variable
6245 	                */
6246 	               if( !SCIPhashmapExists(vartoindex, (void*) SCIPvarGetNegatedVar(var)) )
6247 	                  continue;
6248 	            }
6249 	
6250 	            assert(!chgtype[c]);
6251 	            assert(SCIPhashmapExists(vartoindex, (void*) SCIPvarGetNegatedVar(var)));
6252 	            image = SCIPhashmapGetImageInt(vartoindex, (void*) SCIPvarGetNegatedVar(var));
6253 	            assert(image > 0 && image <= nhashmapentries);
6254 	
6255 	            consindex = considxs[image - 1];
6256 	            assert(0 <= consindex && consindex < nconss);
6257 	
6258 	            /* if the following assert fails, the constraint was not merged, or something really strange happened */
6259 	            assert(consindex < c);
6260 	
6261 	            ++ndecs;
6262 	#ifndef NDEBUG
6263 	            --posreplacements;
6264 	#endif
6265 	            assert(posreplacements >= 0);
6266 	
6267 	            varindex = posincons[image - 1];
6268 	            considxs[image - 1] = -1;
6269 	            posincons[image - 1] = -1;
6270 	            SCIP_CALL( SCIPhashmapRemove(vartoindex, (void*) SCIPvarGetNegatedVar(var)) );
6271 	
6272 	            /* if two variables in one constraint might be multi-aggregated, it might happen that this constraint was
6273 	             * already removed
6274 	             */
6275 	            if( SCIPconsIsDeleted(usefulconss[consindex]) )
6276 	               continue;
6277 	
6278 	            aggrconsdata = SCIPconsGetData(usefulconss[consindex]);
6279 	            assert(aggrconsdata != NULL);
6280 	
6281 	            /* must not multi-aggregate variables that are locked more then twice by all setppc constraints */
6282 	            if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING &&
6283 	               (SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PACKING )
6284 	            {
6285 	               assert(!dualpresolvingenabled || nuplocks + ndownlocks > 2);
6286 	               continue;
6287 	            }
6288 	
6289 	            assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING ||
6290 	               (SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
6291 	
6292 	            /* we already removed a variable before, so our positioning information might be wrong, so we need to walk
6293 	             * over all variables again
6294 	             */
6295 	            if( chgtype[consindex] )
6296 	            {
6297 	#ifndef NDEBUG
6298 	               int v2;
6299 	
6300 	               assert((SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PACKING);
6301 	
6302 	               /* negated variables needs to be still in the upgraded set-packing constraint */
6303 	               for( v2 = aggrconsdata->nvars - 1; v2 >= 0; --v2 )
6304 	               {
6305 	                  if( aggrconsdata->vars[v2] == SCIPvarGetNegatedVar(var) )
6306 	                     break;
6307 	               }
6308 	               assert(v2 >= 0);
6309 	#endif
6310 	               assert((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
6311 	
6312 	               SCIPdebugMsg(scip, "multi-aggregating in one set-partitioning or one set-packing constraint\n");
6313 	
6314 	               /* perform aggregation on variables resulting from a set-partitioning constraint */
6315 	               SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, consdata->vars, consdata->nvars, v, &infeasible, &aggregated) );
6316 	
6317 	               if( infeasible )
6318 	               {
6319 	                  *cutoff = TRUE;
6320 	                  break;
6321 	               }
6322 	               assert(deleteconsindex == -1);
6323 	            }
6324 	            else
6325 	            {
6326 	               /* @note it might have happened that we have a variable at hand which exists actually in a set-packing
6327 	                *       constraint and due to some other aggregation we increased the number of locks and reached this
6328 	                *       part of the code, where we would expect only set-partitioning constraints in general, so in
6329 	                *       such a strange case we cannot aggregate anything
6330 	                */
6331 	               if( (SCIP_SETPPCTYPE)aggrconsdata->setppctype != SCIP_SETPPCTYPE_PARTITIONING )
6332 	                  continue;
6333 	
6334 	               assert(0 <= varindex && varindex < aggrconsdata->nvars);
6335 	               assert(aggrconsdata->vars[varindex] == SCIPvarGetNegatedVar(var));
6336 	               assert((SCIP_SETPPCTYPE)aggrconsdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING);
6337 	
6338 	               SCIPdebugMsg(scip, "multi-aggregating in two set-partitioning or one set-partitioning and -packing constraint\n");
6339 	
6340 	               /* perform aggregation on variables resulting from a set-partitioning constraint */
6341 	               SCIP_CALL( multiAggregateBinvar(scip, linearconshdlrexist, aggrconsdata->vars, aggrconsdata->nvars, varindex, &infeasible, &aggregated) );
6342 	
6343 	               if( infeasible )
6344 	               {
6345 	                  *cutoff = TRUE;
6346 	                  break;
6347 	               }
6348 	
6349 	               /* change pointer for deletion */
6350 	               constoupdate = usefulconss[consindex];
6351 	               assert(deleteconsindex == -1);
6352 	            }
6353 	         }
6354 	
6355 	         if( aggregated )
6356 	         {
6357 	            assert(nuplocks >= 1 && ndownlocks >= 0); /* repeated from above */
6358 	            ++(*naggrvars);
6359 	
6360 	            if( nuplocks == 1 && ndownlocks == 0 && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PACKING )
6361 	            {
6362 	               assert(deleteconsindex < 0);
6363 	
6364 	               SCIP_CALL( delCoefPos(scip, constoupdate, v) );
6365 	               ++(*nchgcoefs);
6366 	            }
6367 	            else if( nuplocks == 1 && ndownlocks == 1 && (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
6368 	            {
6369 	               assert(deleteconsindex < 0);
6370 	
6371 	               SCIP_CALL( delCoefPos(scip, constoupdate, v) );
6372 	               ++(*nchgcoefs);
6373 	
6374 	               SCIPdebugMsg(scip, "changing constraint <%s> from set-partitioning to set-packing, due to multi-aggregation\n", SCIPconsGetName(cons));
6375 	
6376 	               chgtype[c] = TRUE;
6377 	
6378 	               SCIP_CALL( setSetppcType(scip, constoupdate, SCIP_SETPPCTYPE_PACKING) );
6379 	               ++(*nchgsides);
6380 	            }
6381 	            else
6382 	            {
6383 	               if( deleteconsindex >= 0 )
6384 	               {
6385 	                  SCIPdebugMsg(scip, "1: deleting redundant constraint <%s>, due to multi-aggregation\n", SCIPconsGetName(usefulconss[deleteconsindex]));
6386 	                  SCIPdebugPrintCons(scip, usefulconss[deleteconsindex], NULL);
6387 	
6388 	                  assert(!SCIPconsIsDeleted(usefulconss[deleteconsindex]));
6389 	                  SCIP_CALL( SCIPdelCons(scip, usefulconss[deleteconsindex]) );
6390 	               }
6391 	               else
6392 	               {
6393 	                  SCIPdebugMsg(scip, "2: deleting redundant constraint <%s>, due to multi-aggregation\n", SCIPconsGetName(cons));
6394 	                  SCIPdebugPrintCons(scip, constoupdate, NULL);
6395 	
6396 	                  assert(!SCIPconsIsDeleted(cons));
6397 	                  SCIP_CALL( SCIPdelCons(scip, constoupdate) );
6398 	               }
6399 	               ++(*ndelconss);
6400 	            }
6401 	
6402 	            break;
6403 	         }
6404 	      }
6405 	   }
6406 	
6407 	   /* free temporary memory */
6408 	   SCIPfreeBufferArray(scip, &usefulconss);
6409 	   SCIPfreeBufferArray(scip, &posincons);
6410 	   SCIPfreeBufferArray(scip, &considxs);
6411 	   SCIPfreeBufferArray(scip, &chgtype);
6412 	
6413 	   /* free hashmap */
6414 	   SCIPhashmapFree(&vartoindex);
6415 	
6416 	   return SCIP_OKAY;
6417 	}
6418 	
6419 	
6420 	/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
6421 	 *  accordingly; in contrast to removeRedundantConstraints(), it uses a hash table
6422 	 */
6423 	static
6424 	SCIP_RETCODE detectRedundantConstraints(
6425 	   SCIP*                 scip,               /**< SCIP data structure */
6426 	   BMS_BLKMEM*           blkmem,             /**< block memory */
6427 	   SCIP_CONS**           conss,              /**< constraint set */
6428 	   int                   nconss,             /**< number of constraints in constraint set */
6429 	   int*                  firstchange,        /**< pointer to store first changed constraint */
6430 	   int*                  ndelconss,          /**< pointer to count number of deleted constraints */
6431 	   int*                  nchgsides           /**< pointer to count number of changed left/right hand sides */
6432 	   )
6433 	{
6434 	   SCIP_HASHTABLE* hashtable;
6435 	   int hashtablesize;
6436 	   int c;
6437 	
6438 	   assert(scip != NULL);
6439 	   assert(blkmem != NULL);
6440 	   assert(conss != NULL || nconss == 0);
6441 	   assert(firstchange != NULL);
6442 	   assert(ndelconss != NULL);
6443 	   assert(nchgsides != NULL);
6444 	
6445 	   if( nconss == 0 )
6446 	      return SCIP_OKAY;
6447 	
6448 	   assert(conss != NULL);
6449 	
6450 	   /* create a hash table for the constraint set */
6451 	   hashtablesize = nconss;
6452 	   hashtablesize = MAX(hashtablesize, HASHSIZE_SETPPCCONS);
6453 	   SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
6454 	         hashGetKeySetppccons, hashKeyEqSetppccons, hashKeyValSetppccons, (void*) scip) );
6455 	
6456 	   /* check all constraints in the given set for redundancy */
6457 	   for( c = 0; c < nconss; ++c )
6458 	   {
6459 	      SCIP_CONS* cons0;
6460 	      SCIP_CONS* cons1;
6461 	
6462 	      cons0 = conss[c];
6463 	
6464 	      if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
6465 	         continue;
6466 	
6467 	      /* get constraint from current hash table with same variables as cons0 and with coefficients either equal or negated
6468 	       * to the ones of cons0 */
6469 	      cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
6470 	
6471 	      if( cons1 != NULL )
6472 	      {
6473 	         SCIP_CONSDATA* consdata0;
6474 	         SCIP_CONSDATA* consdata1;
6475 	
6476 	         assert(SCIPconsIsActive(cons1));
6477 	         assert(!SCIPconsIsModifiable(cons1));
6478 	
6479 	         /* constraint found: create a new constraint with same coefficients and best left and right hand side;
6480 	          * delete old constraints afterwards
6481 	          */
6482 	         consdata0 = SCIPconsGetData(cons0);
6483 	         consdata1 = SCIPconsGetData(cons1);
6484 	
6485 	         assert(consdata0 != NULL && consdata1 != NULL);
6486 	         assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
6487 	
6488 	         assert(consdata0->sorted && consdata1->sorted);
6489 	         assert(consdata0->vars[0] == consdata1->vars[0]);
6490 	
6491 	         SCIPdebugMsg(scip, "setppc constraints <%s> and <%s> have identical variable sets\n",
6492 	            SCIPconsGetName(cons0), SCIPconsGetName(cons1));
6493 	         SCIPdebugPrintCons(scip, cons0, NULL);
6494 	         SCIPdebugPrintCons(scip, cons1, NULL);
6495 	
6496 	         /* if necessary change type of setppc constraint */
6497 	         if( consdata1->setppctype != SCIP_SETPPCTYPE_PARTITIONING && consdata0->setppctype != consdata1->setppctype ) /*lint !e641*/
6498 	         {
6499 	            /* change the type of cons0 */
6500 	            SCIP_CALL( setSetppcType(scip, cons1, SCIP_SETPPCTYPE_PARTITIONING) );
6501 	            (*nchgsides)++;
6502 	         }
6503 	
6504 	         /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
6505 	         /* coverity[swapped_arguments] */
6506 	         SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
6507 	
6508 	         /* delete cons0 */
6509 	         SCIP_CALL( SCIPdelCons(scip, cons0) );
6510 	         (*ndelconss)++;
6511 	
6512 	         /* update the first changed constraint to begin the next aggregation round with */
6513 	         if( consdata0->changed && SCIPconsGetPos(cons1) < *firstchange )
6514 	            *firstchange = SCIPconsGetPos(cons1);
6515 	
6516 	         assert(SCIPconsIsActive(cons1));
6517 	      }
6518 	      else
6519 	      {
6520 	         /* no such constraint in current hash table: insert cons0 into hash table */
6521 	         SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
6522 	      }
6523 	   }
6524 	
6525 	   /* free hash table */
6526 	   SCIPhashtableFree(&hashtable);
6527 	
6528 	   return SCIP_OKAY;
6529 	}
6530 	
6531 	/** removes the redundant second constraint and updates the flags of the first one */
6532 	static
6533 	SCIP_RETCODE removeRedundantCons(
6534 	   SCIP*                 scip,               /**< SCIP data structure */
6535 	   SCIP_CONS*            cons0,              /**< constraint that should stay */
6536 	   SCIP_CONS*            cons1,              /**< constraint that should be deleted */
6537 	   int*                  ndelconss           /**< pointer to count number of deleted constraints */
6538 	   )
6539 	{
6540 	   assert(ndelconss != NULL);
6541 	
6542 	   SCIPdebugMsg(scip, " -> removing setppc constraint <%s> which is redundant to <%s>\n",
6543 	      SCIPconsGetName(cons1), SCIPconsGetName(cons0));
6544 	   SCIPdebugPrintCons(scip, cons0, NULL);
6545 	   SCIPdebugPrintCons(scip, cons1, NULL);
6546 	
6547 	   /* update flags of cons0 */
6548 	   SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
6549 	
6550 	   /* delete cons1 */
6551 	   SCIP_CALL( SCIPdelCons(scip, cons1) );
6552 	   (*ndelconss)++;
6553 	
6554 	   return SCIP_OKAY;
6555 	}
6556 	
6557 	/** for cons0 contained in cons1, fixes variables of cons1 that are not in cons0 to zero */
6558 	static
6559 	SCIP_RETCODE fixAdditionalVars(
6560 	   SCIP*                 scip,               /**< SCIP data structure */
6561 	   SCIP_CONS*            cons0,              /**< constraint that is contained in the other */
6562 	   SCIP_CONS*            cons1,              /**< constraint that is a superset of the other */
6563 	   SCIP_Bool*            cutoff,             /**< pointer to store whether a cutoff was found */
6564 	   int*                  nfixedvars          /**< pointer to count number of fixed variables */
6565 	   )
6566 	{
6567 	   SCIP_CONSDATA* consdata0;
6568 	   SCIP_CONSDATA* consdata1;
6569 	   int v0;
6570 	   int v1;
6571 	
6572 	   assert(cutoff != NULL);
6573 	   assert(nfixedvars != NULL);
6574 	
6575 	   *cutoff = FALSE;
6576 	
6577 	   /* get constraint data */
6578 	   consdata0 = SCIPconsGetData(cons0);
6579 	   consdata1 = SCIPconsGetData(cons1);
6580 	   assert(consdata0 != NULL);
6581 	   assert(consdata1 != NULL);
6582 	   assert(consdata0->nvars < consdata1->nvars);
6583 	   assert(consdata0->sorted);
6584 	   assert(consdata1->sorted);
6585 	
6586 	   /* fix variables in the range of cons0 */
6587 	   for( v0 = 0, v1 = 0; v0 < consdata0->nvars && !(*cutoff); ++v0, ++v1 )
6588 	   {
6589 	      int index0;
6590 	
6591 	      assert(v1 < consdata1->nvars);
6592 	      index0 = SCIPvarGetIndex(consdata0->vars[v0]);
6593 	      for( ; SCIPvarGetIndex(consdata1->vars[v1]) < index0 && !(*cutoff); ++v1 ) /*lint !e445*/
6594 	      {
6595 	         SCIP_Bool fixed;
6596 	
6597 	         /* fix variable to zero */
6598 	         SCIP_CALL( SCIPfixVar(scip, consdata1->vars[v1], 0.0, cutoff, &fixed) );
6599 	         if( fixed )
6600 	         {
6601 	            SCIPdebugMsg(scip, " -> fixed <%s> == 0\n", SCIPvarGetName(consdata1->vars[v1]));
6602 	            (*nfixedvars)++;
6603 	         }
6604 	         assert(v1 < consdata1->nvars-1);
6605 	      }
6606 	      assert(SCIPvarGetIndex(consdata1->vars[v1]) == index0 || *cutoff);
6607 	   }
6608 	
6609 	   /* fix remaining variables of cons1 */
6610 	   for( ; v1 < consdata1->nvars && !(*cutoff); ++v1 )
6611 	   {
6612 	      SCIP_Bool fixed;
6613 	
6614 	      assert(consdata0->nvars == 0
6615 	         || SCIPvarGetIndex(consdata1->vars[v1]) > SCIPvarGetIndex(consdata0->vars[consdata0->nvars-1]));
6616 	
6617 	      /* fix variable to zero */
6618 	      SCIP_CALL( SCIPfixVar(scip, consdata1->vars[v1], 0.0, cutoff, &fixed) );
6619 	      if( fixed )
6620 	      {
6621 	         SCIPdebugMsg(scip, " -> fixed <%s> == 0\n", SCIPvarGetName(consdata1->vars[v1]));
6622 	         (*nfixedvars)++;
6623 	      }
6624 	   }
6625 	
6626 	   return SCIP_OKAY;
6627 	}
6628 	
6629 	/** applies reductions for cons0 being contained in cons1 */
6630 	static
6631 	SCIP_RETCODE processContainedCons(
6632 	   SCIP*                 scip,               /**< SCIP data structure */
6633 	   SCIP_CONS*            cons0,              /**< constraint that is contained in the other */
6634 	   SCIP_CONS*            cons1,              /**< constraint that is a superset of the other */
6635 	   SCIP_Bool*            cutoff,             /**< pointer to store whether a cutoff was found */
6636 	   int*                  nfixedvars,         /**< pointer to count number of fixed variables */
6637 	   int*                  ndelconss,          /**< pointer to count number of deleted constraints */
6638 	   int*                  nchgsides           /**< pointer to count number of changed left/right hand sides */
6639 	   )
6640 	{
6641 	   SCIP_CONSDATA* consdata0;
6642 	   SCIP_CONSDATA* consdata1;
6643 	
6644 	   assert(cutoff != NULL);
6645 	   assert(nfixedvars != NULL);
6646 	   assert(ndelconss != NULL);
6647 	   assert(nchgsides != NULL);
6648 	
6649 	   *cutoff = FALSE;
6650 	
6651 	   /* get constraint data */
6652 	   consdata0 = SCIPconsGetData(cons0);
6653 	   consdata1 = SCIPconsGetData(cons1);
6654 	   assert(consdata0 != NULL);
6655 	   assert(consdata1 != NULL);
6656 	   assert(consdata0->nvars < consdata1->nvars);
6657 	   assert(consdata0->sorted);
6658 	   assert(consdata1->sorted);
6659 	
6660 	   switch( consdata0->setppctype )
6661 	   {
6662 	   case SCIP_SETPPCTYPE_PARTITIONING:
6663 	      switch( consdata1->setppctype )
6664 	      {
6665 	      case SCIP_SETPPCTYPE_PARTITIONING:
6666 	      case SCIP_SETPPCTYPE_PACKING:
6667 	         /* cons0: partitioning, cons1: partitioning or packing
6668 	          * -> fix additional variables in cons1 to zero, remove cons1
6669 	          */
6670 	         SCIP_CALL( fixAdditionalVars(scip, cons0, cons1, cutoff, nfixedvars) );
6671 	         SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6672 	         break;
6673 	
6674 	      case SCIP_SETPPCTYPE_COVERING:
6675 	         /* cons0: partitioning, cons1: covering
6676 	          * -> remove cons1
6677 	          */
6678 	         SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6679 	         break;
6680 	
6681 	      default:
6682 	         SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata1->setppctype, SCIPconsGetName(cons1));
6683 	         return SCIP_INVALIDDATA;
6684 	      }
6685 	      break;
6686 	
6687 	   case SCIP_SETPPCTYPE_PACKING:
6688 	      switch( consdata1->setppctype )
6689 	      {
6690 	      case SCIP_SETPPCTYPE_PARTITIONING:
6691 	      case SCIP_SETPPCTYPE_PACKING:
6692 	         /* cons0: packing, cons1: partitioning or packing
6693 	          * -> remove cons0
6694 	          */
6695 	         SCIP_CALL( removeRedundantCons(scip, cons1, cons0, ndelconss) );
6696 	         break;
6697 	
6698 	      case SCIP_SETPPCTYPE_COVERING:
6699 	         /* cons0: packing, cons1: covering
6700 	          * -> nothing can be deduced
6701 	          */
6702 	         break;
6703 	
6704 	      default:
6705 	         SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata1->setppctype, SCIPconsGetName(cons1));
6706 	         return SCIP_INVALIDDATA;
6707 	      }
6708 	      break;
6709 	
6710 	   case SCIP_SETPPCTYPE_COVERING:
6711 	      switch( consdata1->setppctype )
6712 	      {
6713 	      case SCIP_SETPPCTYPE_PARTITIONING:
6714 	      case SCIP_SETPPCTYPE_PACKING:
6715 	         /* cons0: covering, cons1: partitioning or packing
6716 	          * -> fix additional variables in cons1 to zero, remove cons1, convert cons0 into partitioning
6717 	          */
6718 	         SCIP_CALL( fixAdditionalVars(scip, cons0, cons1, cutoff, nfixedvars) );
6719 	         SCIP_CALL( setSetppcType(scip, cons0, SCIP_SETPPCTYPE_PARTITIONING) );
6720 	         SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6721 	         (*nchgsides)++;
6722 	         break;
6723 	
6724 	      case SCIP_SETPPCTYPE_COVERING:
6725 	         /* cons0: covering, cons1: covering
6726 	          * -> remove cons1
6727 	          */
6728 	         SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6729 	         break;
6730 	
6731 	      default:
6732 	         SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata1->setppctype, SCIPconsGetName(cons1));
6733 	         return SCIP_INVALIDDATA;
6734 	      }
6735 	      break;
6736 	
6737 	   default:
6738 	      SCIPerrorMessage("invalid setppc type <%d> of constraint <%s>\n", consdata0->setppctype, SCIPconsGetName(cons0));
6739 	      return SCIP_INVALIDDATA;
6740 	   }
6741 	
6742 	   return SCIP_OKAY;
6743 	}
6744 	
6745 	/** deletes redundant constraints */
6746 	static
6747 	SCIP_RETCODE removeRedundantConstraints(
6748 	   SCIP*                 scip,               /**< SCIP data structure */
6749 	   SCIP_CONS**           conss,              /**< constraint set */
6750 	   int                   firstchange,        /**< first constraint that changed since last pair preprocessing round */
6751 	   int                   chkind,             /**< index of constraint to check against all prior indices up to startind */
6752 	   SCIP_Bool*            cutoff,             /**< pointer to store whether a cutoff was found */
6753 	   int*                  nfixedvars,         /**< pointer to count number of fixed variables */
6754 	   int*                  ndelconss,          /**< pointer to count number of deleted constraints */
6755 	   int*                  nchgsides           /**< pointer to count number of changed left/right hand sides */
6756 	   )
6757 	{
6758 	   SCIP_CONS* cons0;
6759 	   SCIP_CONSDATA* consdata0;
6760 	   uint64_t signature0;
6761 	   SCIP_Bool cons0changed;
6762 	   int c;
6763 	
6764 	   assert(scip != NULL);
6765 	   assert(conss != NULL);
6766 	   assert(cutoff != NULL);
6767 	   assert(nfixedvars != NULL);
6768 	   assert(ndelconss != NULL);
6769 	   assert(nchgsides != NULL);
6770 	
6771 	   *cutoff = FALSE;
6772 	
6773 	   /* get the constraint to be checked against all prior constraints */
6774 	   cons0 = conss[chkind];
6775 	   assert(SCIPconsIsActive(cons0));
6776 	   assert(!SCIPconsIsModifiable(cons0));
6777 	
6778 	   consdata0 = SCIPconsGetData(cons0);
6779 	   assert(consdata0 != NULL);
6780 	   assert(consdata0->nvars >= 1);
6781 	
6782 	   /* sort the constraint cons0 */
6783 	   consdataSort(consdata0);
6784 	
6785 	   /* get the bit signature of the constraint */
6786 	   signature0 = consdataGetSignature(consdata0);
6787 	
6788 	   /* check constraint against all prior constraints */
6789 	   cons0changed = consdata0->changed;
6790 	   consdata0->changed = FALSE;
6791 	   for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && SCIPconsIsActive(cons0); ++c )
6792 	   {
6793 	      SCIP_CONS* cons1;
6794 	      SCIP_CONSDATA* consdata1;
6795 	      uint64_t signature1;
6796 	      uint64_t jointsignature;
6797 	      SCIP_Bool cons0iscontained;
6798 	      SCIP_Bool cons1iscontained;
6799 	      int v0;
6800 	      int v1;
6801 	
6802 	      cons1 = conss[c];
6803 	
6804 	      /* ignore inactive and modifiable constraints */
6805 	      if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
6806 	         continue;
6807 	
6808 	      consdata1 = SCIPconsGetData(cons1);
6809 	      assert(consdata1 != NULL);
6810 	
6811 	      /* sort the constraint cons1 */
6812 	      consdataSort(consdata1);
6813 	
6814 	      /* get the bit signature of cons1 */
6815 	      signature1 = consdataGetSignature(consdata1);
6816 	
6817 	      /* check (based on signature) if the two constraints are not included in each other */
6818 	      jointsignature = (signature0 | signature1);
6819 	      if( jointsignature != signature0 && jointsignature != signature1 )
6820 	         continue;
6821 	
6822 	      /* check whether one constraint is really a subset of the other */
6823 	      cons0iscontained = (consdata0->nvars <= consdata1->nvars);
6824 	      cons1iscontained = (consdata1->nvars <= consdata0->nvars);
6825 	      v0 = 0;
6826 	      v1 = 0;
6827 	      while( v0 < consdata0->nvars && v1 < consdata1->nvars )
6828 	      {
6829 	         int index0;
6830 	         int index1;
6831 	
6832 	         index0 = SCIPvarGetIndex(consdata0->vars[v0]);
6833 	         index1 = SCIPvarGetIndex(consdata1->vars[v1]);
6834 	         if( index0 < index1 )
6835 	         {
6836 	            cons0iscontained = FALSE;
6837 	            if( !cons1iscontained )
6838 	               break;
6839 	            for( v0++; v0 < consdata0->nvars && SCIPvarGetIndex(consdata0->vars[v0]) < index1; v0++ )
6840 	            {}
6841 	         }
6842 	         else if( index1 < index0 )
6843 	         {
6844 	            cons1iscontained = FALSE;
6845 	            if( !cons0iscontained )
6846 	               break;
6847 	            for( v1++; v1 < consdata1->nvars && SCIPvarGetIndex(consdata1->vars[v1]) < index0; v1++ )
6848 	            {}
6849 	         }
6850 	         else
6851 	         {
6852 	            v0++;
6853 	            v1++;
6854 	         }
6855 	      }
6856 	      cons0iscontained = cons0iscontained && (v0 == consdata0->nvars);
6857 	      cons1iscontained = cons1iscontained && (v1 == consdata1->nvars);
6858 	
6859 	      if( cons0iscontained && cons1iscontained )
6860 	      {
6861 	         SCIPdebugMsg(scip, "setppc constraints <%s> and <%s> have identical variable sets\n",
6862 	            SCIPconsGetName(cons0), SCIPconsGetName(cons1));
6863 	         SCIPdebugPrintCons(scip, cons0, NULL);
6864 	         SCIPdebugPrintCons(scip, cons1, NULL);
6865 	
6866 	         /* both constraints consists of the same variables */
6867 	         if( consdata0->setppctype == consdata1->setppctype )
6868 	         {
6869 	            /* both constraints are equal: update flags in cons0 and delete cons1 */
6870 	            SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6871 	         }
6872 	         else if( consdata0->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
6873 	         {
6874 	            /* the set partitioning constraint is stronger: remove the other one */
6875 	            SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6876 	         }
6877 	         else if( consdata1->setppctype == SCIP_SETPPCTYPE_PARTITIONING ) /*lint !e641*/
6878 	         {
6879 	            /* the set partitioning constraint is stronger: remove the other one */
6880 	            SCIP_CALL( removeRedundantCons(scip, cons1, cons0, ndelconss) );
6881 	         }
6882 	         else
6883 	         {
6884 	            /* one is a covering, the other one a packing constraint: replace them by a single partitioning constraint */
6885 	            assert((consdata0->setppctype == SCIP_SETPPCTYPE_COVERING && consdata1->setppctype == SCIP_SETPPCTYPE_PACKING)
6886 	               || (consdata1->setppctype == SCIP_SETPPCTYPE_COVERING && consdata0->setppctype == SCIP_SETPPCTYPE_PACKING)); /*lint !e641*/
6887 	
6888 	            /* change the type of cons0 */
6889 	            SCIP_CALL( setSetppcType(scip, cons0, SCIP_SETPPCTYPE_PARTITIONING) );
6890 	            (*nchgsides)++;
6891 	
6892 	            /* delete cons1 */
6893 	            SCIP_CALL( removeRedundantCons(scip, cons0, cons1, ndelconss) );
6894 	         }
6895 	      }
6896 	      else if( cons0iscontained )
6897 	      {
6898 	         /* cons0 is contained in cons1 */
6899 	         SCIPdebugMsg(scip, "setppc constraint <%s> is contained in <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
6900 	         SCIPdebugPrintCons(scip, cons0, NULL);
6901 	         SCIPdebugPrintCons(scip, cons1, NULL);
6902 	         SCIP_CALL( processContainedCons(scip, cons0, cons1, cutoff, nfixedvars, ndelconss, nchgsides) );
6903 	      }
6904 	      else if( cons1iscontained )
6905 	      {
6906 	         /* cons1 is contained in cons1 */
6907 	         SCIPdebugMsg(scip, "setppc constraint <%s> is contained in <%s>\n", SCIPconsGetName(cons1), SCIPconsGetName(cons0));
6908 	         SCIPdebugPrintCons(scip, cons0, NULL);
6909 	         SCIPdebugPrintCons(scip, cons1, NULL);
6910 	         SCIP_CALL( processContainedCons(scip, cons1, cons0, cutoff, nfixedvars, ndelconss, nchgsides) );
6911 	      }
6912 	   }
6913 	
6914 	   return SCIP_OKAY;
6915 	}
6916 	
6917 	/* perform deletion of variables in all constraints of the constraint handler */
6918 	static
6919 	SCIP_RETCODE performVarDeletions(
6920 	   SCIP*                 scip,               /**< SCIP data structure */
6921 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
6922 	   SCIP_CONS**           conss,              /**< array of constraints */
6923 	   int                   nconss              /**< number of constraints */
6924 	   )
6925 	{
6926 	   SCIP_CONSDATA* consdata;
6927 	   int i;
6928 	   int v;
6929 	
6930 	   assert(scip != NULL);
6931 	   assert(conshdlr != NULL);
6932 	   assert(conss != NULL);
6933 	   assert(nconss >= 0);
6934 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
6935 	
6936 	   /* iterate over all constraints */
6937 	   for( i = 0; i < nconss; i++ )
6938 	   {
6939 	      consdata = SCIPconsGetData(conss[i]);
6940 	
6941 	      /* constraint is marked, that some of its variables were deleted */
6942 	      if( consdata->varsdeleted )
6943 	      {
6944 	         /* iterate over all variables of the constraint and delete marked variables */
6945 	         for( v = consdata->nvars - 1; v >= 0; v-- )
6946 	         {
6947 	            if( SCIPvarIsDeleted(consdata->vars[v]) )
6948 	            {
6949 	               SCIP_CALL( delCoefPos(scip, conss[i], v) );
6950 	            }
6951 	         }
6952 	         consdata->varsdeleted = FALSE;
6953 	      }
6954 	   }
6955 	
6956 	   return SCIP_OKAY;
6957 	}
6958 	
6959 	/** helper function to enforce constraints */
6960 	static
6961 	SCIP_RETCODE enforceConstraint(
6962 	   SCIP*                 scip,               /**< SCIP data structure */
6963 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
6964 	   SCIP_CONS**           conss,              /**< constraints to process */
6965 	   int                   nconss,             /**< number of constraints */
6966 	   int                   nusefulconss,       /**< number of useful (non-obsolete) constraints to process */
6967 	   SCIP_SOL*             sol,                /**< solution to enforce (NULL for the LP solution) */
6968 	   SCIP_RESULT*          result              /**< pointer to store the result of the enforcing call */
6969 	   )
6970 	{
6971 	   SCIP_Bool cutoff;
6972 	   SCIP_Bool separated;
6973 	   SCIP_Bool reduceddom;
6974 	   int c;
6975 	
6976 	   assert(conshdlr != NULL);
6977 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
6978 	   assert(nconss == 0 || conss != NULL);
6979 	   assert(result != NULL);
6980 	
6981 	   SCIPdebugMsg(scip, "Enforcing %d set partitioning / packing / covering constraints for %s solution\n", nconss,
6982 	         sol == NULL ? "LP" : "relaxation");
6983 	
6984 	   *result = SCIP_FEASIBLE;
6985 	
6986 	   cutoff = FALSE;
6987 	   separated = FALSE;
6988 	   reduceddom = FALSE;
6989 	
6990 	   /* check all useful set partitioning / packing / covering constraints for feasibility */
6991 	   for( c = 0; c < nusefulconss && !cutoff && !reduceddom; ++c )
6992 	   {
6993 	      SCIP_CALL( separateCons(scip, conss[c], sol, TRUE, &cutoff, &separated, &reduceddom) );
6994 	   }
6995 	
6996 	   /* check all obsolete set partitioning / packing / covering constraints for feasibility */
6997 	   for( c = nusefulconss; c < nconss && !cutoff && !separated && !reduceddom; ++c )
6998 	   {
6999 	      SCIP_CALL( separateCons(scip, conss[c], sol, TRUE, &cutoff, &separated, &reduceddom) );
7000 	   }
7001 	
7002 	#ifdef VARUSES
7003 	#ifdef BRANCHLP
7004 	   /* @todo also branch on relaxation solution */
7005 	   if( (sol == NULL) && !cutoff && !separated && !reduceddom )
7006 	   {
7007 	      /* if solution is not integral, choose a variable set to branch on */
7008 	      SCIP_CALL( branchLP(scip, conshdlr, result) );
7009 	      if( *result != SCIP_FEASIBLE )
7010 	         return SCIP_OKAY;
7011 	   }
7012 	#endif
7013 	#endif
7014 	
7015 	   /* return the correct result */
7016 	   if( cutoff )
7017 	      *result = SCIP_CUTOFF;
7018 	   else if( separated )
7019 	      *result = SCIP_SEPARATED;
7020 	   else if( reduceddom )
7021 	      *result = SCIP_REDUCEDDOM;
7022 	
7023 	   return SCIP_OKAY;
7024 	}
7025 	
7026 	/*
7027 	 * upgrading of linear constraints
7028 	 */
7029 	
7030 	
7031 	/** creates and captures a set partitioning / packing / covering constraint */
7032 	static
7033 	SCIP_RETCODE createConsSetppc(
7034 	   SCIP*                 scip,               /**< SCIP data structure */
7035 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
7036 	   const char*           name,               /**< name of constraint */
7037 	   int                   nvars,              /**< number of variables in the constraint */
7038 	   SCIP_VAR**            vars,               /**< array with variables of constraint entries */
7039 	   SCIP_SETPPCTYPE       setppctype,         /**< type of constraint: set partitioning, packing, or covering constraint */
7040 	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
7041 	                                              *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
7042 	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
7043 	                                              *   Usually set to TRUE. */
7044 	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
7045 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7046 	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
7047 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7048 	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
7049 	                                              *   Usually set to TRUE. */
7050 	   SCIP_Bool             local,              /**< is constraint only valid locally?
7051 	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
7052 	   SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)?
7053 	                                              *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
7054 	                                              *   adds coefficients to this constraint. */
7055 	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
7056 	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
7057 	                                              *   are separated as constraints. */
7058 	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
7059 	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
7060 	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
7061 	                                              *   if it may be moved to a more global node?
7062 	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
7063 	   )
7064 	{
7065 	   SCIP_CONSHDLR* conshdlr;
7066 	   SCIP_CONSDATA* consdata;
7067 	   SCIP_CONSHDLRDATA* conshdlrdata;
7068 	
7069 	   assert(scip != NULL);
7070 	
7071 	   /* find the set partitioning constraint handler */
7072 	   conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
7073 	   if( conshdlr == NULL )
7074 	   {
7075 	      SCIPerrorMessage("set partitioning / packing / covering constraint handler not found\n");
7076 	      return SCIP_INVALIDCALL;
7077 	   }
7078 	
7079 	   /* create the constraint specific data */
7080 	   if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
7081 	   {
7082 	      /* create constraint in original problem */
7083 	      SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, setppctype) );
7084 	   }
7085 	   else
7086 	   {
7087 	      /* create constraint in transformed problem */
7088 	      SCIP_CALL( consdataCreateTransformed(scip, &consdata, nvars, vars, setppctype) );
7089 	   }
7090 	
7091 	   /* create constraint */
7092 	   SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
7093 	         local, modifiable, dynamic, removable, stickingatnode) );
7094 	
7095 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
7096 	   assert(conshdlrdata != NULL);
7097 	
7098 	   if( SCIPisTransformed(scip) && setppctype == SCIP_SETPPCTYPE_PARTITIONING )
7099 	   {
7100 	      ++(conshdlrdata->nsetpart);
7101 	      assert(conshdlrdata->nsetpart >= 0);
7102 	   }
7103 	
7104 	   if( SCIPgetStage(scip) != SCIP_STAGE_PROBLEM )
7105 	   {
7106 	      /* get event handler */
7107 	      assert(conshdlrdata->eventhdlr != NULL);
7108 	
7109 	      /* catch bound change events of variables */
7110 	      SCIP_CALL( catchAllEvents(scip, *cons, conshdlrdata->eventhdlr) );
7111 	   }
7112 	
7113 	   return SCIP_OKAY;
7114 	}
7115 	
7116 	/** creates and captures a normalized (with all coefficients +1) setppc constraint */
7117 	static
7118 	SCIP_RETCODE createNormalizedSetppc(
7119 	   SCIP*                 scip,               /**< SCIP data structure */
7120 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
7121 	   const char*           name,               /**< name of constraint */
7122 	   int                   nvars,              /**< number of variables in the constraint */
7123 	   SCIP_VAR**            vars,               /**< array with variables of constraint entries */
7124 	   SCIP_Real*            vals,               /**< array with coefficients (+1.0 or -1.0) */
7125 	   int                   mult,               /**< multiplier on the coefficients(+1 or -1) */
7126 	   SCIP_SETPPCTYPE       setppctype,         /**< type of constraint: set partitioning, packing, or covering constraint */
7127 	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
7128 	                                              *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
7129 	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
7130 	                                              *   Usually set to TRUE. */
7131 	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
7132 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7133 	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
7134 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7135 	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
7136 	                                              *   Usually set to TRUE. */
7137 	   SCIP_Bool             local,              /**< is constraint only valid locally?
7138 	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
7139 	   SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)?
7140 	                                              *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
7141 	                                              *   adds coefficients to this constraint. */
7142 	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
7143 	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
7144 	                                              *   are separated as constraints. */
7145 	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
7146 	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
7147 	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
7148 	                                              *   if it may be moved to a more global node?
7149 	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
7150 	   )
7151 	{
7152 	   SCIP_VAR** transvars;
7153 	   int v;
7154 	
7155 	   assert(nvars == 0 || vars != NULL);
7156 	   assert(nvars == 0 || vals != NULL);
7157 	   assert(mult == +1 || mult == -1);
7158 	
7159 	   /* get temporary memory */
7160 	   SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
7161 	
7162 	   /* negate positive or negative variables */
7163 	   for( v = 0; v < nvars; ++v )
7164 	   {
7165 	      if( mult * vals[v] > 0.0 )
7166 	         transvars[v] = vars[v];
7167 	      else
7168 	      {
7169 	         SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &transvars[v]) );
7170 	      }
7171 	      assert(transvars[v] != NULL);
7172 	   }
7173 	
7174 	   /* create the constraint */
7175 	   SCIP_CALL( createConsSetppc(scip, cons, name, nvars, transvars, setppctype,
7176 	         initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
7177 	
7178 	   /* release temporary memory */
7179 	   SCIPfreeBufferArray(scip, &transvars);
7180 	
7181 	   return SCIP_OKAY;
7182 	}
7183 	
7184 	/** check, if linear constraint can be upgraded to set partitioning, packing, or covering constraint */
7185 	static
7186 	SCIP_DECL_LINCONSUPGD(linconsUpgdSetppc)
7187 	{  /*lint --e{715}*/
7188 	   assert(upgdcons != NULL);
7189 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "linear") == 0 );
7190 	
7191 	   /* check, if linear constraint can be upgraded to set partitioning, packing, or covering constraint
7192 	    * - all set partitioning / packing / covering constraints consist only of binary variables with a
7193 	    *   coefficient of +1.0 or -1.0 (variables with -1.0 coefficients can be negated):
7194 	    *        lhs     <= x1 + ... + xp - y1 - ... - yn <= rhs
7195 	    * - negating all variables y = (1-Y) with negative coefficients gives:
7196 	    *        lhs + n <= x1 + ... + xp + Y1 + ... + Yn <= rhs + n
7197 	    * - negating all variables x = (1-X) with positive coefficients and multiplying with -1 gives:
7198 	    *        p - rhs <= X1 + ... + Xp + y1 + ... + yn <= p - lhs
7199 	    * - a set partitioning constraint has left hand side of +1.0, and right hand side of +1.0 : x(S) == 1.0
7200 	    *    -> without negations:  lhs == rhs == 1 - n  or  lhs == rhs == p - 1
7201 	    * - a set packing constraint has left hand side of -infinity, and right hand side of +1.0 : x(S) <= 1.0
7202 	    *    -> without negations:  (lhs == -inf  and  rhs == 1 - n)  or  (lhs == p - 1  and  rhs = +inf)
7203 	    * - a set covering constraint has left hand side of +1.0, and right hand side of +infinity: x(S) >= 1.0
7204 	    *    -> without negations:  (lhs == 1 - n  and  rhs == +inf)  or  (lhs == -inf  and  rhs = p - 1)
7205 	    */
7206 	   if( nposbin + nnegbin + nposimplbin + nnegimplbin == nvars && ncoeffspone + ncoeffsnone == nvars )
7207 	   {
7208 	      int mult;
7209 	
7210 	      if( SCIPisEQ(scip, lhs, rhs) && (SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) || SCIPisEQ(scip, lhs, ncoeffspone - 1.0)) )
7211 	      {
7212 	         SCIPdebugMsg(scip, "upgrading constraint <%s> to set partitioning constraint\n", SCIPconsGetName(cons));
7213 	
7214 	         /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
7215 	         mult = SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) ? +1 : -1;
7216 	
7217 	         /* create the set partitioning constraint (an automatically upgraded constraint is always unmodifiable) */
7218 	         assert(!SCIPconsIsModifiable(cons));
7219 	         SCIP_CALL( createNormalizedSetppc(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
7220 	               SCIP_SETPPCTYPE_PARTITIONING,
7221 	               SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
7222 	               SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),
7223 	               SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons),
7224 	               SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
7225 	      }
7226 	      else if( (SCIPisInfinity(scip, -lhs) && SCIPisEQ(scip, rhs, 1.0 - ncoeffsnone))
7227 	         || (SCIPisEQ(scip, lhs, ncoeffspone - 1.0) && SCIPisInfinity(scip, rhs)) )
7228 	      {
7229 	         SCIPdebugMsg(scip, "upgrading constraint <%s> to set packing constraint\n", SCIPconsGetName(cons));
7230 	
7231 	         /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
7232 	         mult = SCIPisInfinity(scip, -lhs) ? +1 : -1;
7233 	
7234 	         /* create the set packing constraint (an automatically upgraded constraint is always unmodifiable) */
7235 	         assert(!SCIPconsIsModifiable(cons));
7236 	         SCIP_CALL( createNormalizedSetppc(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
7237 	               SCIP_SETPPCTYPE_PACKING,
7238 	               SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
7239 	               SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),
7240 	               SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons),
7241 	               SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
7242 	      }
7243 	      else if( (SCIPisEQ(scip, lhs, 1.0 - ncoeffsnone) && SCIPisInfinity(scip, rhs))
7244 	         || (SCIPisInfinity(scip, -lhs) && SCIPisEQ(scip, rhs, ncoeffspone - 1.0)) )
7245 	      {
7246 	         SCIPdebugMsg(scip, "upgrading constraint <%s> to set covering constraint\n", SCIPconsGetName(cons));
7247 	
7248 	         /* check, if we have to multiply with -1 (negate the positive vars) or with +1 (negate the negative vars) */
7249 	         mult = SCIPisInfinity(scip, rhs) ? +1 : -1;
7250 	
7251 	         /* create the set covering constraint (an automatically upgraded constraint is always unmodifiable) */
7252 	         assert(!SCIPconsIsModifiable(cons));
7253 	         SCIP_CALL( createNormalizedSetppc(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, mult,
7254 	               SCIP_SETPPCTYPE_COVERING,
7255 	               SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
7256 	               SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),
7257 	               SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons),
7258 	               SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
7259 	      }
7260 	   }
7261 	
7262 	   return SCIP_OKAY;
7263 	}
7264 	
7265 	/** tries to upgrade a nonlinear constraint to a setpacking constraint */
7266 	static
7267 	SCIP_DECL_NONLINCONSUPGD(nonlinUpgdSetppc)
7268 	{
7269 	   SCIP_Bool isquadratic;
7270 	   SCIP_EXPR* expr;
7271 	   SCIP_EXPR* expr1;
7272 	   SCIP_EXPR* expr2;
7273 	   SCIP_VAR* bilinvars[2];
7274 	   SCIP_VAR* vars[2];
7275 	   SCIP_Real bilincoef;
7276 	   SCIP_Real constant;
7277 	   SCIP_Real lincoef;
7278 	   SCIP_Real sqrcoef;
7279 	   SCIP_Real coefx;
7280 	   SCIP_Real coefy;
7281 	   SCIP_Real rhs;
7282 	   int nbilinexprterms;
7283 	   int nquadexprs;
7284 	   int nlinexprs;
7285 	
7286 	   assert(scip != NULL);
7287 	   assert(cons != NULL);
7288 	   assert(nupgdconss != NULL);
7289 	   assert(upgdconss != NULL);
7290 	   assert(! SCIPconsIsModifiable(cons));
7291 	   assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "nonlinear") == 0);
7292 	
7293 	   *nupgdconss = 0;
7294 	
7295 	   SCIPdebugMsg(scip, "try to upgrade nonlinear constraint <%s> to setpacking constraint ...\n", SCIPconsGetName(cons));
7296 	   SCIPdebugPrintCons(scip, cons, NULL);
7297 	
7298 	   /* need exactly two variables */
7299 	   if( nvarexprs != 2 )
7300 	      return SCIP_OKAY;
7301 	
7302 	   /* left and right hand side need to be equal
7303 	    * @todo we could also handle inequalities
7304 	    */
7305 	   rhs = SCIPgetRhsNonlinear(cons);
7306 	   if( SCIPisInfinity(scip, rhs) || !SCIPisEQ(scip, SCIPgetLhsNonlinear(cons), rhs) )
7307 	      return SCIP_OKAY;
7308 	
7309 	   /* check whether constraint is quadratic */
7310 	   SCIP_CALL( SCIPcheckQuadraticNonlinear(scip, cons, &isquadratic) );
7311 	   if( !isquadratic )
7312 	      return SCIP_OKAY;
7313 	
7314 	   expr = SCIPgetExprNonlinear(cons);
7315 	   SCIPexprGetQuadraticData(expr, &constant, &nlinexprs, NULL, NULL, &nquadexprs, &nbilinexprterms, NULL, NULL);
7316 	
7317 	   /* adjust rhs */
7318 	   rhs -= constant;
7319 	
7320 	   /* cannot currently handle linear part */
7321 	   if( nlinexprs > 0 )
7322 	      return SCIP_OKAY;
7323 	
7324 	   /* need only one bilinear term */
7325 	   if( nbilinexprterms != 1 )
7326 	      return SCIP_OKAY;
7327 	
7328 	   /* need exactly two quadratic variables */
7329 	   if( nquadexprs != 2 )
7330 	      return SCIP_OKAY;
7331 	
7332 	   /* get bilinear term */
7333 	   SCIPexprGetQuadraticBilinTerm(expr, 0, &expr1, &expr2, &bilincoef, NULL, NULL);
7334 	   bilinvars[0] = SCIPgetVarExprVar(expr1);
7335 	   bilinvars[1] = SCIPgetVarExprVar(expr2);
7336 	
7337 	   if( SCIPisZero(scip, bilincoef) )
7338 	      return SCIP_OKAY;
7339 	
7340 	   /* check variable types */
7341 	   if( SCIPvarGetType(bilinvars[0]) != SCIP_VARTYPE_BINARY || SCIPvarGetType(bilinvars[1]) != SCIP_VARTYPE_BINARY )
7342 	      return SCIP_OKAY;
7343 	
7344 	   /* get data of quadratic terms */
7345 	   SCIPexprGetQuadraticQuadTerm(expr, 0, &expr1, &lincoef, &sqrcoef, NULL, NULL, NULL);
7346 	   coefx = lincoef + sqrcoef;  /* for binary variables, we can treat sqr coef as lin coef */
7347 	
7348 	   SCIPexprGetQuadraticQuadTerm(expr, 1, &expr2, &lincoef, &sqrcoef, NULL, NULL, NULL);
7349 	   coefy = lincoef + sqrcoef;  /* for binary variables, we can treat sqr coef as lin coef */
7350 	
7351 	   /* divide constraint by coefficient of x*y */
7352 	   coefx /= bilincoef;
7353 	   coefy /= bilincoef;
7354 	   rhs   /= bilincoef;
7355 	
7356 	   /* constraint is now of the form coefx * x + coefy * y + x * y == rhs
7357 	    * we can rewrite as (x + coefy) * (y + coefx) == rhs + coefx * coefy
7358 	    */
7359 	
7360 	   /* we can only upgrade if coefx and coefy are 0 or -1 and rhs == -coefx * coefy */
7361 	   if( !SCIPisZero(scip, coefx) && !SCIPisEQ(scip, coefx, -1.0) )
7362 	      return SCIP_OKAY;
7363 	   if( !SCIPisZero(scip, coefy) && !SCIPisEQ(scip, coefy, -1.0) )
7364 	      return SCIP_OKAY;
7365 	   if( !SCIPisEQ(scip, rhs, -coefx * coefy) )
7366 	      return SCIP_OKAY;
7367 	
7368 	   if( SCIPisZero(scip, coefy) )
7369 	   {
7370 	      vars[0] = SCIPgetVarExprVar(expr1);
7371 	   }
7372 	   else
7373 	   {
7374 	      assert(SCIPisEQ(scip, coefy, -1.0));
7375 	      /* x - 1 = -(1-x) = -(~x) */
7376 	      SCIP_CALL( SCIPgetNegatedVar(scip, SCIPgetVarExprVar(expr1), &vars[0]) );
7377 	   }
7378 	   if( SCIPisZero(scip, coefx) )
7379 	   {
7380 	      vars[1] = SCIPgetVarExprVar(expr2);
7381 	   }
7382 	   else
7383 	   {
7384 	      assert(SCIPisEQ(scip, coefx, -1.0));
7385 	      /* y - 1 = -(1 - y) = -(~y) */
7386 	      SCIP_CALL( SCIPgetNegatedVar(scip, SCIPgetVarExprVar(expr2), &vars[1]) );
7387 	   }
7388 	
7389 	   /* constraint is now of the form  vars[0] * vars[1] == 0 */
7390 	
7391 	   SCIPdebugMsg(scip, "constraint <%s> can be upgraded ...\n", SCIPconsGetName(cons));
7392 	
7393 	   /* vars[0] + vars[1] <= 1 */
7394 	   SCIP_CALL( SCIPcreateConsSetpack(scip, &upgdconss[0], SCIPconsGetName(cons), 2, vars,
7395 	         SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
7396 	         SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),  SCIPconsIsLocal(cons),
7397 	         SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
7398 	   SCIPdebugPrintCons(scip, upgdconss[0], NULL);
7399 	
7400 	   ++(*nupgdconss);
7401 	
7402 	   return SCIP_OKAY;
7403 	} /*lint !e715*/
7404 	
7405 	/** adds symmetry information of constraint to a symmetry detection graph */
7406 	static
7407 	SCIP_RETCODE addSymmetryInformation(
7408 	   SCIP*                 scip,               /**< SCIP pointer */
7409 	   SYM_SYMTYPE           symtype,            /**< type of symmetries that need to be added */
7410 	   SCIP_CONS*            cons,               /**< constraint */
7411 	   SYM_GRAPH*            graph,              /**< symmetry detection graph */
7412 	   SCIP_Bool*            success             /**< pointer to store whether symmetry information could be added */
7413 	   )
7414 	{
7415 	   SCIP_CONSDATA* consdata;
7416 	   SCIP_VAR** vars;
7417 	   SCIP_Real* vals;
7418 	   SCIP_Real constant = 0.0;
7419 	   SCIP_Real lhs;
7420 	   SCIP_Real rhs;
7421 	   int nlocvars;
7422 	   int nvars;
7423 	   int i;
7424 	
7425 	   assert(scip != NULL);
7426 	   assert(cons != NULL);
7427 	   assert(graph != NULL);
7428 	   assert(success != NULL);
7429 	
7430 	   consdata = SCIPconsGetData(cons);
7431 	   assert(consdata != NULL);
7432 	
7433 	   /* get active variables of the constraint */
7434 	   nvars = SCIPgetNVars(scip);
7435 	   nlocvars = consdata->nvars;
7436 	
7437 	   SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
7438 	   SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
7439 	
7440 	   for( i = 0; i < consdata->nvars; ++i )
7441 	   {
7442 	      vars[i] = consdata->vars[i];
7443 	      vals[i] = 1.0;
7444 	   }
7445 	
7446 	   SCIP_CALL( SCIPgetActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
7447 	
7448 	   lhs = -SCIPinfinity(scip);
7449 	   rhs = SCIPinfinity(scip);
7450 	   if ( consdata->setppctype == (unsigned) SCIP_SETPPCTYPE_PACKING ) /*lint !e641*/
7451 	      rhs = 1.0 - constant;
7452 	   else if ( consdata->setppctype == (unsigned) SCIP_SETPPCTYPE_COVERING ) /*lint !e641*/
7453 	      lhs = 1.0 - constant;
7454 	   else
7455 	   {
7456 	      assert(consdata->setppctype == (unsigned) SCIP_SETPPCTYPE_PARTITIONING); /*lint !e641*/
7457 	
7458 	      rhs = 1.0 - constant;
7459 	      lhs = 1.0 - constant;
7460 	   }
7461 	
7462 	   SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
7463 	         cons, lhs, rhs, success) );
7464 	
7465 	   SCIPfreeBufferArray(scip, &vals);
7466 	   SCIPfreeBufferArray(scip, &vars);
7467 	
7468 	   return SCIP_OKAY;
7469 	}
7470 	
7471 	/*
7472 	 * Callback methods of constraint handler
7473 	 */
7474 	
7475 	/** copy method for constraint handler plugins (called when SCIP copies plugins) */
7476 	static
7477 	SCIP_DECL_CONSHDLRCOPY(conshdlrCopySetppc)
7478 	{  /*lint --e{715}*/
7479 	   assert(scip != NULL);
7480 	   assert(conshdlr != NULL);
7481 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7482 	
7483 	   /* call inclusion method of constraint handler */
7484 	   SCIP_CALL( SCIPincludeConshdlrSetppc(scip) );
7485 	
7486 	   *valid = TRUE;
7487 	
7488 	   return SCIP_OKAY;
7489 	}
7490 	
7491 	/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
7492 	static
7493 	SCIP_DECL_CONSFREE(consFreeSetppc)
7494 	{  /*lint --e{715}*/
7495 	   SCIP_CONSHDLRDATA* conshdlrdata;
7496 	
7497 	   assert(conshdlr != NULL);
7498 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7499 	   assert(scip != NULL);
7500 	
7501 	   /* free constraint handler data */
7502 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
7503 	   assert(conshdlrdata != NULL);
7504 	   SCIP_CALL( conshdlrdataFree(scip, &conshdlrdata) );
7505 	
7506 	   SCIPconshdlrSetData(conshdlr, NULL);
7507 	
7508 	   return SCIP_OKAY;
7509 	}
7510 	
7511 	
7512 	/** initialization method of constraint handler (called after problem was transformed) */
7513 	static
7514 	SCIP_DECL_CONSINIT(consInitSetppc)
7515 	{  /*lint --e{715}*/
7516 	   SCIP_CONSHDLRDATA* conshdlrdata;
7517 	
7518 	   assert(conshdlr != NULL);
7519 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7520 	   assert(scip != NULL);
7521 	
7522 	   /* free constraint handler data */
7523 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
7524 	   assert(conshdlrdata != NULL);
7525 	
7526 	   conshdlrdata->noldfixedvars = 0;
7527 	   conshdlrdata->noldimpls = 0;
7528 	   conshdlrdata->noldcliques = 0;
7529 	   conshdlrdata->noldupgrs = 0;
7530 	   conshdlrdata->nclqpresolve = 0;
7531 	   conshdlrdata->updatedsetppctype = FALSE;
7532 	   conshdlrdata->enablecliquelifting = TRUE;
7533 	
7534 	   return SCIP_OKAY;
7535 	}
7536 	
7537 	
7538 	/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
7539 	static
7540 	SCIP_DECL_CONSEXITPRE(consExitpreSetppc)
7541 	{  /*lint --e{715}*/
7542 	   int c;
7543 	
7544 	   assert(scip != NULL);
7545 	   assert(conshdlr != NULL);
7546 	
7547 	   for( c = 0; c < nconss; ++c )
7548 	   {
7549 	      if( !SCIPconsIsDeleted(conss[c]) )
7550 	      {
7551 	         /* we are not allowed to detect infeasibility in the exitpre stage */
7552 	         SCIP_CALL( applyFixings(scip, conss[c], NULL, NULL, NULL, NULL) );
7553 	      }
7554 	   }
7555 	
7556 	   return SCIP_OKAY;
7557 	}
7558 	
7559 	/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
7560 	static
7561 	SCIP_DECL_CONSINITSOL(consInitsolSetppc)
7562 	{  /*lint --e{715}*/
7563 	   /* add nlrow representation to NLP, if NLP had been constructed */
7564 	   if( SCIPisNLPConstructed(scip) )
7565 	   {
7566 	      int c;
7567 	      for( c = 0; c < nconss; ++c )
7568 	      {
7569 	         SCIP_CALL( addNlrow(scip, conss[c]) );
7570 	      }
7571 	   }
7572 	
7573 	   return SCIP_OKAY;
7574 	}
7575 	
7576 	/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
7577 	static
7578 	SCIP_DECL_CONSEXITSOL(consExitsolSetppc)
7579 	{  /*lint --e{715}*/
7580 	   SCIP_CONSDATA* consdata;
7581 	   int c;
7582 	
7583 	   /* release the rows and nlrows of all constraints */
7584 	   for( c = 0; c < nconss; ++c )
7585 	   {
7586 	      consdata = SCIPconsGetData(conss[c]);
7587 	      assert(consdata != NULL);
7588 	
7589 	      if( consdata->row != NULL )
7590 	      {
7591 	         SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
7592 	      }
7593 	
7594 	      if( consdata->nlrow != NULL )
7595 	      {
7596 	         SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
7597 	      }
7598 	   }
7599 	
7600 	   return SCIP_OKAY;
7601 	}
7602 	
7603 	
7604 	/** frees specific constraint data */
7605 	static
7606 	SCIP_DECL_CONSDELETE(consDeleteSetppc)
7607 	{  /*lint --e{715}*/
7608 	   SCIP_CONSHDLRDATA* conshdlrdata;
7609 	
7610 	   assert(conshdlr != NULL);
7611 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7612 	
7613 	   /* get event handler */
7614 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
7615 	   assert(conshdlrdata != NULL);
7616 	   assert(conshdlrdata->eventhdlr != NULL);
7617 	
7618 	   if( SCIPisTransformed(scip) )
7619 	   {
7620 	      if( (SCIP_SETPPCTYPE)((*consdata)->setppctype) == SCIP_SETPPCTYPE_PARTITIONING )
7621 	      {
7622 	         --(conshdlrdata->nsetpart);
7623 	         assert(conshdlrdata->nsetpart >= 0);
7624 	      }
7625 	   }
7626 	
7627 	   /* if constraint belongs to transformed problem space, drop bound change events on variables */
7628 	   if( (*consdata)->nvars > 0 && SCIPvarIsTransformed((*consdata)->vars[0]) )
7629 	   {
7630 	      SCIP_CALL( dropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7631 	   }
7632 	
7633 	   /* free setppc constraint data */
7634 	   SCIP_CALL( consdataFree(scip, consdata) );
7635 	
7636 	   return SCIP_OKAY;
7637 	}
7638 	
7639 	
7640 	/** transforms constraint data into data belonging to the transformed problem */
7641 	static
7642 	SCIP_DECL_CONSTRANS(consTransSetppc)
7643 	{  /*lint --e{715}*/
7644 	   SCIP_CONSHDLRDATA* conshdlrdata;
7645 	   SCIP_CONSDATA* sourcedata;
7646 	   SCIP_CONSDATA* targetdata;
7647 	
7648 	   /*debugMsg(scip, "Trans method of setppc constraints\n");*/
7649 	
7650 	   assert(conshdlr != NULL);
7651 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7652 	   assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
7653 	   assert(sourcecons != NULL);
7654 	   assert(targetcons != NULL);
7655 	
7656 	   /* get event handler */
7657 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
7658 	   assert(conshdlrdata != NULL);
7659 	   assert(conshdlrdata->eventhdlr != NULL);
7660 	
7661 	   sourcedata = SCIPconsGetData(sourcecons);
7662 	   assert(sourcedata != NULL);
7663 	   assert(sourcedata->row == NULL);  /* in original problem, there cannot be LP rows */
7664 	
7665 	   /* create constraint data for target constraint */
7666 	   SCIP_CALL( consdataCreateTransformed(scip, &targetdata, sourcedata->nvars, sourcedata->vars,
7667 	         (SCIP_SETPPCTYPE)sourcedata->setppctype) );
7668 	
7669 	   /* create target constraint */
7670 	   SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
7671 	         SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
7672 	         SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
7673 	         SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
7674 	         SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
7675 	
7676 	   if( (SCIP_SETPPCTYPE)sourcedata->setppctype == SCIP_SETPPCTYPE_PARTITIONING )
7677 	   {
7678 	      ++(conshdlrdata->nsetpart);
7679 	      assert(conshdlrdata->nsetpart >= 0);
7680 	   }
7681 	
7682 	   /* catch bound change events of variables */
7683 	   SCIP_CALL( catchAllEvents(scip, *targetcons, conshdlrdata->eventhdlr) );
7684 	
7685 	   return SCIP_OKAY;
7686 	}
7687 	
7688 	
7689 	/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
7690 	static
7691 	SCIP_DECL_CONSINITLP(consInitlpSetppc)
7692 	{  /*lint --e{715}*/
7693 	   int c;
7694 	
7695 	   *infeasible = FALSE;
7696 	
7697 	   for( c = 0; c < nconss && !(*infeasible); ++c )
7698 	   {
7699 	      assert(SCIPconsIsInitial(conss[c]));
7700 	      SCIP_CALL( addCut(scip, conss[c], infeasible) );
7701 	   }
7702 	
7703 	   return SCIP_OKAY;
7704 	}
7705 	
7706 	
7707 	/** separation method of constraint handler for LP solutions */
7708 	static
7709 	SCIP_DECL_CONSSEPALP(consSepalpSetppc)
7710 	{  /*lint --e{715}*/
7711 	   SCIP_Bool cutoff;
7712 	   SCIP_Bool separated;
7713 	   SCIP_Bool reduceddom;
7714 	   int c;
7715 	
7716 	   assert(conshdlr != NULL);
7717 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7718 	   assert(nconss == 0 || conss != NULL);
7719 	   assert(result != NULL);
7720 	
7721 	   SCIPdebugMsg(scip, "separating %d/%d set partitioning / packing / covering constraints\n", nusefulconss, nconss);
7722 	
7723 	   *result = SCIP_DIDNOTFIND;
7724 	
7725 	   cutoff = FALSE;
7726 	   separated = FALSE;
7727 	   reduceddom = FALSE;
7728 	
7729 	   /* check all useful set partitioning / packing / covering constraints for feasibility */
7730 	   for( c = 0; c < nusefulconss && !cutoff; ++c )
7731 	   {
7732 	      SCIP_CALL( separateCons(scip, conss[c], NULL, TRUE, &cutoff, &separated, &reduceddom) );
7733 	   }
7734 	
7735 	   /* combine set partitioning / packing / covering constraints to get more cuts */
7736 	   /**@todo further cuts of set partitioning / packing / covering constraints */
7737 	
7738 	   /* return the correct result */
7739 	   if( cutoff )
7740 	      *result = SCIP_CUTOFF;
7741 	   else if( reduceddom )
7742 	      *result = SCIP_REDUCEDDOM;
7743 	   else if( separated )
7744 	      *result = SCIP_SEPARATED;
7745 	
7746 	   return SCIP_OKAY;
7747 	}
7748 	
7749 	
7750 	/** separation method of constraint handler for arbitrary primal solutions */
7751 	static
7752 	SCIP_DECL_CONSSEPASOL(consSepasolSetppc)
7753 	{  /*lint --e{715}*/
7754 	   SCIP_Bool cutoff;
7755 	   SCIP_Bool separated;
7756 	   SCIP_Bool reduceddom;
7757 	   int c;
7758 	
7759 	   assert(conshdlr != NULL);
7760 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7761 	   assert(nconss == 0 || conss != NULL);
7762 	   assert(result != NULL);
7763 	
7764 	   SCIPdebugMsg(scip, "separating %d/%d set partitioning / packing / covering constraints\n", nusefulconss, nconss);
7765 	
7766 	   *result = SCIP_DIDNOTFIND;
7767 	
7768 	   cutoff = FALSE;
7769 	   separated = FALSE;
7770 	   reduceddom = FALSE;
7771 	
7772 	   /* check all useful set partitioning / packing / covering constraints for feasibility */
7773 	   for( c = 0; c < nusefulconss && !cutoff; ++c )
7774 	   {
7775 	      SCIP_CALL( separateCons(scip, conss[c], sol, FALSE, &cutoff, &separated, &reduceddom) );
7776 	   }
7777 	
7778 	   /* combine set partitioning / packing / covering constraints to get more cuts */
7779 	   /**@todo further cuts of set partitioning / packing / covering constraints */
7780 	
7781 	   /* return the correct result */
7782 	   if( cutoff )
7783 	      *result = SCIP_CUTOFF;
7784 	   else if( reduceddom )
7785 	      *result = SCIP_REDUCEDDOM;
7786 	   else if( separated )
7787 	      *result = SCIP_SEPARATED;
7788 	
7789 	   return SCIP_OKAY;
7790 	}
7791 	
7792 	
7793 	#ifdef VARUSES
7794 	#ifdef BRANCHLP
7795 	/** if fractional variables exist, chooses a set S of them and branches on (i) x(S) == 0, and (ii) x(S) >= 1 */
7796 	static
7797 	SCIP_RETCODE branchLP(
7798 	   SCIP*                 scip,               /**< SCIP data structure */
7799 	   SCIP_CONSHDLR*        conshdlr,           /**< set partitioning / packing / covering constraint handler */
7800 	   SCIP_RESULT*          result              /**< pointer to store the result SCIP_BRANCHED, if branching was applied */
7801 	   )
7802 	{
7803 	   SCIP_CONSHDLRDATA* conshdlrdata;
7804 	   SCIP_INTARRAY* varuses;
7805 	   SCIP_VAR** lpcands;
7806 	   SCIP_VAR** sortcands;
7807 	   SCIP_VAR* var;
7808 	   SCIP_Real branchweight;
7809 	   SCIP_Real solval;
7810 	   int* uses;
7811 	   int nlpcands;
7812 	   int nsortcands;
7813 	   int nselcands;
7814 	   int numuses;
7815 	   int i;
7816 	   int j;
7817 	
7818 	   /**@todo use a better set partitioning / packing / covering branching on LP solution (use SOS branching) */
7819 	
7820 	   assert(conshdlr != NULL);
7821 	   assert(result != NULL);
7822 	
7823 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
7824 	   assert(conshdlrdata != NULL);
7825 	
7826 	   varuses = conshdlrdata->varuses;
7827 	   assert(varuses != NULL);
7828 	
7829 	   /* get fractional variables */
7830 	   SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, NULL, NULL, &nlpcands, NULL, NULL) );
7831 	   if( nlpcands == 0 )
7832 	      return SCIP_OKAY;
7833 	
7834 	   assert(MINBRANCHWEIGHT <= MAXBRANCHWEIGHT);
7835 	
7836 	   /* get temporary memory */
7837 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortcands, nlpcands) );
7838 	   SCIP_CALL( SCIPallocBufferArray(scip, &uses, nlpcands) );
7839 	
7840 	   /* sort fractional variables by number of uses in enabled set partitioning / packing / covering constraints */
7841 	   nsortcands = 0;
7842 	   for( i = 0; i < nlpcands; ++i )
7843 	   {
7844 	      var = lpcands[i];
7845 	      numuses = SCIPgetIntarrayVal(scip, varuses, SCIPvarGetIndex(var));
7846 	      if( numuses > 0 )
7847 	      {
7848 	         for( j = nsortcands; j > 0 && numuses > uses[j-1]; --j )
7849 	         {
7850 	            sortcands[j] = sortcands[j-1];
7851 	            uses[j] = uses[j-1];
7852 	         }
7853 	         assert(0 <= j && j <= nsortcands);
7854 	         sortcands[j] = var;
7855 	         uses[j] = numuses;
7856 	         nsortcands++;
7857 	      }
7858 	   }
7859 	   assert(nsortcands <= nlpcands);
7860 	
7861 	   /* if none of the fractional variables is member of a set partitioning / packing / covering constraint,
7862 	    * we are not responsible for doing the branching
7863 	    */
7864 	   if( nsortcands > 0 )
7865 	   {
7866 	      SCIP_Real cumprio = 0.0;
7867 	      SCIP_Real minprio = SCIP_INVALID;
7868 	      SCIP_Real minestzero = SCIP_INVALID;
7869 	      SCIP_Real minestone = SCIP_INVALID;
7870 	      SCIP_Real tmp;
7871 	
7872 	      /* select the first variables from the sorted candidate list, until MAXBRANCHWEIGHT is reached;
7873 	       * then choose one less
7874 	       */
7875 	      branchweight = 0.0;
7876 	      solval = 0.0;
7877 	      for( nselcands = 0; nselcands < nsortcands; ++nselcands )
7878 	      {
7879 	         solval = SCIPgetVarSol(scip, sortcands[nselcands]);
7880 	         assert(SCIPisFeasGE(scip, solval, 0.0) && SCIPisFeasLE(scip, solval, 1.0));
7881 	         branchweight += solval;
7882 	
7883 		 /* did we exceed the maximal weight */
7884 		 if( branchweight > MAXBRANCHWEIGHT )
7885 		    break;
7886 	
7887 		 /* @todo instead of taking the minimum into account try other variants like the maximum and the average */
7888 		 /* calculate priorities and estimates by adding up/taking the minimum of all single priorities/estimates */
7889 		 cumprio += SCIPcalcNodeselPriority(scip, sortcands[nselcands], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
7890 		 tmp = SCIPcalcNodeselPriority(scip, sortcands[nselcands], SCIP_BRANCHDIR_UPWARDS, 1.0);
7891 		 minprio = MIN(minprio, tmp);
7892 		 tmp = SCIPcalcChildEstimate(scip, sortcands[nselcands], 0.0);;
7893 		 minestzero = MIN(minestzero, tmp);
7894 		 tmp = SCIPcalcChildEstimate(scip, sortcands[nselcands], 1.0);;
7895 		 minestone = MIN(minestone, tmp);
7896 	      }
7897 	      assert(minestzero != SCIP_INVALID); /*lint !e777*/
7898 	      assert(minestone != SCIP_INVALID); /*lint !e777*/
7899 	      assert(minprio != SCIP_INVALID); /*lint !e777*/
7900 	      assert(nselcands > 0);
7901 	      branchweight -= solval;
7902 	
7903 	      /* check, if we accumulated at least MIN and at most MAXBRANCHWEIGHT weight */
7904 	      if( MINBRANCHWEIGHT <= branchweight && branchweight <= MAXBRANCHWEIGHT )
7905 	      {
7906 	         SCIP_NODE* node;
7907 	
7908 	         /* perform the binary set branching on the selected variables */
7909 	         assert(1 <= nselcands && nselcands <= nlpcands);
7910 	
7911 	         /* create left child, fix x_i = 0 for all i \in S */
7912 	         SCIP_CALL( SCIPcreateChild(scip, &node, cumprio, minestzero) );
7913 	         for( i = 0; i < nselcands; ++i )
7914 	         {
7915 	            SCIP_CALL( SCIPchgVarUbNode(scip, node, sortcands[i], 0.0) );
7916 	         }
7917 	
7918 	         /* create right child: add constraint x(S) >= 1 */
7919 	         SCIP_CALL( SCIPcreateChild(scip, &node, minprio, minestone) );
7920 	         if( nselcands == 1 )
7921 	         {
7922 	            /* only one candidate selected: fix it to 1.0 */
7923 	            SCIPdebugMsg(scip, "fixing variable <%s> to 1.0 in right child node\n", SCIPvarGetName(sortcands[0]));
7924 	            SCIP_CALL( SCIPchgVarLbNode(scip, node, sortcands[0], 1.0) );
7925 	         }
7926 	         else
7927 	         {
7928 	            SCIP_CONS* newcons;
7929 	            char name[SCIP_MAXSTRLEN];
7930 	
7931 	            /* add set covering constraint x(S) >= 1 */
7932 	            (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "BSB%" SCIP_LONGINT_FORMAT, SCIPgetNTotalNodes(scip));
7933 	
7934 	            SCIP_CALL( SCIPcreateConsSetcover(scip, &newcons, name, nselcands, sortcands,
7935 	                  FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
7936 	            SCIP_CALL( SCIPaddConsNode(scip, node, newcons, NULL) );
7937 	            SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
7938 	         }
7939 	
7940 	         *result = SCIP_BRANCHED;
7941 	
7942 	#ifdef SCIP_DEBUG
7943 	         SCIPdebugMsg(scip, "binary set branching: nselcands=%d/%d, weight(S)=%g, A={", nselcands, nlpcands, branchweight);
7944 	         for( i = 0; i < nselcands; ++i )
7945 	            SCIPdebugMsgPrint(scip, " %s[%g]", SCIPvarGetName(sortcands[i]), SCIPgetSolVal(scip, NULL, sortcands[i]));
7946 	         SCIPdebugMsgPrint(scip, " }\n");
7947 	#endif
7948 	      }
7949 	   }
7950 	
7951 	   /* free temporary memory */
7952 	   SCIPfreeBufferArray(scip, &uses);
7953 	   SCIPfreeBufferArray(scip, &sortcands);
7954 	
7955 	   return SCIP_OKAY;
7956 	}
7957 	#endif
7958 	
7959 	/** if unfixed variables exist, chooses a set S of them and creates |S|+1 child nodes:
7960 	 *   - for each variable i from S, create child node with x_0 = ... = x_i-1 = 0, x_i = 1
7961 	 *   - create an additional child node x_0 = ... = x_n-1 = 0
7962 	 */
7963 	static
7964 	SCIP_RETCODE branchPseudo(
7965 	   SCIP*                 scip,               /**< SCIP data structure */
7966 	   SCIP_CONSHDLR*        conshdlr,           /**< set partitioning / packing / covering constraint handler */
7967 	   SCIP_RESULT*          result              /**< pointer to store the result SCIP_BRANCHED, if branching was applied */
7968 	   )
7969 	{
7970 	   SCIP_CONSHDLRDATA* conshdlrdata;
7971 	   SCIP_INTARRAY* varuses;
7972 	   SCIP_VAR** pseudocands;
7973 	   SCIP_VAR** branchcands;
7974 	   SCIP_VAR* var;
7975 	   SCIP_NODE* node;
7976 	   int* canduses;
7977 	   int npseudocands;
7978 	   int maxnbranchcands;
7979 	   int nbranchcands;
7980 	   int uses;
7981 	   int i;
7982 	   int j;
7983 	
7984 	   /**@todo use a better set partitioning / packing / covering branching on pseudo solution (use SOS branching) */
7985 	
7986 	   assert(conshdlr != NULL);
7987 	   assert(result != NULL);
7988 	
7989 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
7990 	   assert(conshdlrdata != NULL);
7991 	
7992 	   /* check, if pseudo branching is disabled */
7993 	   if( conshdlrdata->npseudobranches <= 1 )
7994 	      return SCIP_OKAY;
7995 	
7996 	   /* get fractional variables */
7997 	   SCIP_CALL( SCIPgetPseudoBranchCands(scip, &pseudocands, NULL, &npseudocands) );
7998 	   if( npseudocands == 0 )
7999 	      return SCIP_OKAY;
8000 	
8001 	   varuses = conshdlrdata->varuses;
8002 	   assert(varuses != NULL);
8003 	
8004 	   /* choose the maximal number of branching variables */
8005 	   maxnbranchcands = conshdlrdata->npseudobranches-1;
8006 	   assert(maxnbranchcands >= 1);
8007 	
8008 	   /* get temporary memory */
8009 	   SCIP_CALL( SCIPallocBufferArray(scip, &branchcands, maxnbranchcands) );
8010 	   SCIP_CALL( SCIPallocBufferArray(scip, &canduses, maxnbranchcands) );
8011 	
8012 	   /* sort unfixed variables by number of uses in enabled set partitioning / packing / covering constraints */
8013 	   nbranchcands = 0;
8014 	   for( i = 0; i < npseudocands; ++i )
8015 	   {
8016 	      var = pseudocands[i];
8017 	      uses = SCIPgetIntarrayVal(scip, varuses, SCIPvarGetIndex(var));
8018 	      if( uses > 0 )
8019 	      {
8020 	         if( nbranchcands < maxnbranchcands || uses > canduses[nbranchcands-1] )
8021 	         {
8022 	            for( j = MIN(nbranchcands, maxnbranchcands-1); j > 0 && uses > canduses[j-1]; --j )
8023 	            {
8024 	               branchcands[j] = branchcands[j-1];
8025 	               canduses[j] = canduses[j-1];
8026 	            }
8027 	            assert(0 <= j && j <= nbranchcands && j < maxnbranchcands);
8028 	            branchcands[j] = var;
8029 	            canduses[j] = uses;
8030 	            if( nbranchcands < maxnbranchcands )
8031 	               nbranchcands++;
8032 	         }
8033 	      }
8034 	   }
8035 	   assert(nbranchcands <= maxnbranchcands);
8036 	
8037 	   /* if none of the unfixed variables is member of a set partitioning / packing / covering constraint,
8038 	    * we are not responsible for doing the branching
8039 	    */
8040 	   if( nbranchcands > 0 )
8041 	   {
8042 	      SCIP_Real* estone;
8043 	      SCIP_Real minestzero = SCIP_INVALID;
8044 	      SCIP_Real tmp;
8045 	
8046 	      SCIP_CALL( SCIPallocBufferArray(scip, &estone, nbranchcands) );
8047 	
8048 	      /* @todo instead of taking the minimum into account try other variants like the maximum and the average */
8049 	      /* @todo calculate priorities instead of setting it to the number of branching candidates */
8050 	      /* calculate estimates by taking the minimum over all single estimates */
8051 	      for( i = 0; i < nbranchcands; ++i )
8052 	      {
8053 		 tmp = SCIPcalcChildEstimate(scip, branchcands[i], 0.0);;
8054 		 minestzero = MIN(minestzero, tmp);
8055 		 estone[i] = SCIPcalcChildEstimate(scip, branchcands[i], 1.0);
8056 	      }
8057 	      assert(minestzero != SCIP_INVALID); /*lint !e777*/
8058 	
8059 	      /* branch on the first part of the sorted candidates:
8060 	       * - for each of these variables i, create a child node x_0 = ... = x_i-1 = 0, x_i = 1
8061 	       * - create an additional child node x_0 = ... = x_n-1 = 0
8062 	       */
8063 	      for( i = 0; i < nbranchcands; ++i )
8064 	      {
8065 	         /* create child with x_0 = ... = x_i-1 = 0, x_i = 1 */
8066 	         SCIP_CALL( SCIPcreateChild(scip, &node, (SCIP_Real)nbranchcands, MIN(minestzero, estone[i])) );
8067 	         for( j = 0; j < i; ++j )
8068 	         {
8069 	            SCIP_CALL( SCIPchgVarUbNode(scip, node, branchcands[j], 0.0) );
8070 	         }
8071 	         SCIP_CALL( SCIPchgVarLbNode(scip, node, branchcands[i], 1.0) );
8072 	      }
8073 	      /* create child with x_0 = ... = x_n = 0 */
8074 	      SCIP_CALL( SCIPcreateChild(scip, &node, (SCIP_Real)nbranchcands, minestzero) );
8075 	      for( i = 0; i < nbranchcands; ++i )
8076 	      {
8077 	         SCIP_CALL( SCIPchgVarUbNode(scip, node, branchcands[i], 0.0) );
8078 	      }
8079 	
8080 	      *result = SCIP_BRANCHED;
8081 	
8082 	      SCIPfreeBufferArray(scip, &estone);
8083 	
8084 	#ifdef SCIP_DEBUG
8085 	      {
8086 	         int nchildren;
8087 	         SCIP_CALL( SCIPgetChildren(scip, NULL, &nchildren) );
8088 	         SCIPdebugMsg(scip, "branched on pseudo solution: %d children\n", nchildren);
8089 	      }
8090 	#endif
8091 	   }
8092 	
8093 	   /* free temporary memory */
8094 	   SCIPfreeBufferArray(scip, &canduses);
8095 	   SCIPfreeBufferArray(scip, &branchcands);
8096 	
8097 	   return SCIP_OKAY;
8098 	}
8099 	#endif
8100 	
8101 	
8102 	/** constraint enforcing method of constraint handler for LP solutions */
8103 	static
8104 	SCIP_DECL_CONSENFOLP(consEnfolpSetppc)
8105 	{  /*lint --e{715}*/
8106 	   SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
8107 	
8108 	   return SCIP_OKAY;
8109 	}
8110 	
8111 	
8112 	/** constraint enforcing method of constraint handler for relaxation solutions */
8113 	static
8114 	SCIP_DECL_CONSENFORELAX(consEnforelaxSetppc)
8115 	{  /*lint --e{715}*/
8116 	   SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
8117 	
8118 	   return SCIP_OKAY;
8119 	}
8120 	
8121 	
8122 	/** constraint enforcing method of constraint handler for pseudo solutions */
8123 	static
8124 	SCIP_DECL_CONSENFOPS(consEnfopsSetppc)
8125 	{  /*lint --e{715}*/
8126 	   SCIP_Bool cutoff;
8127 	   SCIP_Bool infeasible;
8128 	   SCIP_Bool reduceddom;
8129 	   SCIP_Bool solvelp;
8130 	   int c;
8131 	
8132 	   assert(conshdlr != NULL);
8133 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8134 	   assert(nconss == 0 || conss != NULL);
8135 	   assert(result != NULL);
8136 	
8137 	   /* if the solution is infeasible anyway due to objective value, skip the constraint processing and branch directly */
8138 	#ifdef VARUSES
8139 	   if( objinfeasible )
8140 	   {
8141 	      *result = SCIP_DIDNOTRUN;
8142 	      SCIP_CALL( branchPseudo(scip, conshdlr, result) );
8143 	      return SCIP_OKAY;
8144 	   }
8145 	#endif
8146 	
8147 	   SCIPdebugMsg(scip, "pseudo enforcing %d set partitioning / packing / covering constraints\n", nconss);
8148 	
8149 	   *result = SCIP_FEASIBLE;
8150 	
8151 	   cutoff = FALSE;
8152 	   infeasible = FALSE;
8153 	   reduceddom = FALSE;
8154 	   solvelp = FALSE;
8155 	
8156 	   /* check all set partitioning / packing / covering constraints for feasibility */
8157 	   for( c = 0; c < nconss && !cutoff && !reduceddom && !solvelp; ++c )
8158 	   {
8159 	      SCIP_CALL( enforcePseudo(scip, conss[c], &cutoff, &infeasible, &reduceddom, &solvelp) );
8160 	   }
8161 	
8162 	   if( cutoff )
8163 	      *result = SCIP_CUTOFF;
8164 	   else if( reduceddom )
8165 	      *result = SCIP_REDUCEDDOM;
8166 	   else if( solvelp )
8167 	      *result = SCIP_SOLVELP;
8168 	   else if( infeasible )
8169 	   {
8170 	      *result = SCIP_INFEASIBLE;
8171 	
8172 	#ifdef VARUSES
8173 	      /* at least one constraint is violated by pseudo solution and we didn't find a better way to resolve this:
8174 	       * -> branch on pseudo solution
8175 	       */
8176 	      SCIP_CALL( branchPseudo(scip, conshdlr, result) );
8177 	#endif
8178 	   }
8179 	
8180 	   return SCIP_OKAY;
8181 	}
8182 	
8183 	
8184 	/** feasibility check method of constraint handler for integral solutions */
8185 	static
8186 	SCIP_DECL_CONSCHECK(consCheckSetppc)
8187 	{  /*lint --e{715}*/
8188 	   SCIP_CONS* cons;
8189 	   SCIP_CONSDATA* consdata;
8190 	   int c;
8191 	
8192 	   assert(conshdlr != NULL);
8193 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8194 	   assert(nconss == 0 || conss != NULL);
8195 	   assert(result != NULL);
8196 	
8197 	   *result = SCIP_FEASIBLE;
8198 	
8199 	   /* check all set partitioning / packing / covering constraints for feasibility */
8200 	   for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
8201 	   {
8202 	      cons = conss[c];
8203 	      consdata = SCIPconsGetData(cons);
8204 	      assert(consdata != NULL);
8205 	      if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
8206 	      {
8207 	         if( !checkCons(scip, consdata, sol) )
8208 	         {
8209 	            /* constraint is violated */
8210 	            *result = SCIP_INFEASIBLE;
8211 	
8212 	            if( printreason )
8213 	            {
8214 	               SCIP_Real sum = 0.0;
8215 	               int v;
8216 	
8217 	               SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
8218 	
8219 	               for( v = 0; v < consdata->nvars; ++v )
8220 	               {
8221 	                  assert(SCIPvarIsBinary(consdata->vars[v]));
8222 	
8223 	                  sum += SCIPgetSolVal(scip, sol, consdata->vars[v]);
8224 	               }
8225 	               SCIPinfoMessage(scip, NULL, ";\n");
8226 	               SCIPinfoMessage(scip, NULL, "violation: the right hand side is violated by by %.15g\n", ABS(sum - 1));
8227 	            }
8228 	         }
8229 	      }
8230 	   }
8231 	
8232 	   return SCIP_OKAY;
8233 	}
8234 	
8235 	/** domain propagation method of constraint handler */
8236 	static
8237 	SCIP_DECL_CONSPROP(consPropSetppc)
8238 	{  /*lint --e{715}*/
8239 	   SCIP_Bool cutoff;
8240 	   SCIP_Bool addcut;
8241 	   SCIP_Bool mustcheck;
8242 	   SCIP_Bool inpresolve;
8243 	   int nfixedvars = 0;
8244 	   int c;
8245 	
8246 	   assert(conshdlr != NULL);
8247 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8248 	   assert(nconss == 0 || conss != NULL);
8249 	   assert(result != NULL);
8250 	
8251 	   *result = SCIP_DIDNOTFIND;
8252 	
8253 	   SCIPdebugMsg(scip, "propagating %d/%d set partitioning / packing / covering constraints\n", nmarkedconss, nconss);
8254 	
8255 	   cutoff = FALSE;
8256 	   inpresolve = (SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE);
8257 	
8258 	   /* propagate all marked set partitioning / packing / covering constraints */
8259 	   for( c = nmarkedconss - 1; c >= 0 && !cutoff; --c )
8260 	   {
8261 	      assert(SCIPconsGetData(conss[c]) != NULL);
8262 	
8263 	      /* during presolving, we do not want to propagate constraints with multiaggregated variables. After presolving,
8264 	       * we want to resolve the multiaggregation to have a clean data structure; All initial constraints should not
8265 	       * have multiaggregated variables, but this is not true for constraints that were introduced during solving
8266 	       */
8267 	      if( SCIPconsGetData(conss[c])->existmultaggr )
8268 	      {
8269 	         int naddconss, ndelconss;
8270 	
8271 	         if( inpresolve )
8272 	            continue;
8273 	
8274 	         naddconss = ndelconss = 0;
8275 	         SCIP_CALL( applyFixings(scip, conss[c], &naddconss, &ndelconss, &nfixedvars, &cutoff) );
8276 	
8277 	         if( cutoff )
8278 	            break;
8279 	      }
8280 	
8281 	      /* all multiaggregations should be resolved at here */
8282 	      assert(inpresolve || ! SCIPconsGetData(conss[c])->existmultaggr);
8283 	
8284 	      SCIP_CALL( processFixings(scip, conss[c], &cutoff, &nfixedvars, &addcut, &mustcheck) );
8285 	
8286 	      SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[c]) );
8287 	   }
8288 	
8289 	   /* return the correct result */
8290 	   if( cutoff )
8291 	      *result = SCIP_CUTOFF;
8292 	   else if( nfixedvars > 0 )
8293 	      *result = SCIP_REDUCEDDOM;
8294 	
8295 	   return SCIP_OKAY; /*lint !e438*/
8296 	}
8297 	
8298 	
8299 	/** presolving method of constraint handler */
8300 	static
8301 	SCIP_DECL_CONSPRESOL(consPresolSetppc)
8302 	{  /*lint --e{715}*/
8303 	   SCIP_CONSHDLRDATA* conshdlrdata;
8304 	   int oldnfixedvars;
8305 	   int oldnaggrvars;
8306 	   int oldndelconss;
8307 	   int oldnchgcoefs;
8308 	   int firstchange;
8309 	   int firstclique;
8310 	   int lastclique;
8311 	   int startdelconss;
8312 	   int c;
8313 	   SCIP_Bool cutoff;
8314 	
8315 	   assert(conshdlr != NULL);
8316 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8317 	   assert(scip != NULL);
8318 	   assert(result != NULL);
8319 	
8320 	   *result = SCIP_DIDNOTFIND;
8321 	   oldnfixedvars = *nfixedvars;
8322 	   oldndelconss = *ndelconss;
8323 	   oldnaggrvars = *naggrvars;
8324 	   oldnchgcoefs = *nchgcoefs;
8325 	   cutoff = FALSE;
8326 	
8327 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
8328 	   assert(conshdlrdata != NULL);
8329 	
8330 	   /* determine whether we want to run the clique lifting procedure */
8331 	   conshdlrdata->enablecliquelifting = conshdlrdata->enablecliquelifting || conshdlrdata->updatedsetppctype
8332 	      || conshdlrdata->noldfixedvars != SCIPgetNFixedVars(scip) || conshdlrdata->noldimpls != SCIPgetNImplications(scip)
8333 	      || conshdlrdata->noldcliques != SCIPgetNCliques(scip) || conshdlrdata->noldupgrs != nconss;
8334 	
8335 	   /* remember old values */
8336 	   startdelconss = *ndelconss;
8337 	   conshdlrdata->noldimpls = SCIPgetNImplications(scip);
8338 	   conshdlrdata->noldcliques = SCIPgetNCliques(scip);
8339 	   conshdlrdata->updatedsetppctype = FALSE;
8340 	
8341 	   /* process constraints */
8342 	   firstchange = INT_MAX;
8343 	   firstclique = INT_MAX;
8344 	   lastclique = -1;
8345 	   for( c = 0; c < nconss && !SCIPisStopped(scip); ++c )
8346 	   {
8347 	      SCIP_CONS* cons;
8348 	      SCIP_CONSDATA* consdata;
8349 	
8350 	      assert(*result != SCIP_CUTOFF);
8351 	
8352 	      cons = conss[c];
8353 	      assert(cons != NULL);
8354 	      consdata = SCIPconsGetData(cons);
8355 	      assert(consdata != NULL);
8356 	
8357 	      /*SCIPdebugMsg(scip, "presolving set partitioning / packing / covering constraint <%s>\n", SCIPconsGetName(cons));*/
8358 	
8359 	      /* remove all variables that are fixed to zero and replace all aggregated variables */
8360 	      if( consdata->nfixedzeros > 0 || nnewaggrvars > 0 || nnewaddconss > 0 || nnewupgdconss > 0
8361 	            || *naggrvars > oldnaggrvars || (nrounds == 0 && SCIPgetNRuns(scip) > 1) )
8362 	      {
8363 	         SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, &cutoff) );
8364 	
8365 	         if( cutoff )
8366 	         {
8367 	            *result = SCIP_CUTOFF;
8368 	            return SCIP_OKAY;
8369 	         }
8370 	
8371 	         if( SCIPconsIsDeleted(cons) )
8372 	            continue;
8373 	      }
8374 	
8375 	      /* find pairs of negated variables in constraint:
8376 	       * partitioning/packing: all other variables must be zero, constraint is redundant
8377 	       * covering: constraint is redundant
8378 	       *
8379 	       * find sets of equal variables in constraint:
8380 	       * partitioning/packing: variable must be zero
8381 	       * covering: multiple entries of variable can be replaced by single entry
8382 	       */
8383 	      SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, &cutoff) );
8384 	
8385 	      if( cutoff )
8386 	      {
8387 	         *result = SCIP_CUTOFF;
8388 	         return SCIP_OKAY;
8389 	      }
8390 	
8391 	      /* if constraint was deleted while merging, go to the next constraint */
8392 	      if( !SCIPconsIsActive(cons) )
8393 	         continue;
8394 	
8395 	      /* remove fixings found by merging */
8396 	      if( consdata->nfixedzeros > 0 )
8397 	      {
8398 	         SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, &cutoff) );
8399 	
8400 	         if( cutoff )
8401 	         {
8402 	            *result = SCIP_CUTOFF;
8403 	            return SCIP_OKAY;
8404 	         }
8405 	
8406 	         if( SCIPconsIsDeleted(cons) )
8407 	            continue;
8408 	      }
8409 	
8410 	      /* check if constraint is already redundant or infeasible due to fixings, fix or aggregate left over variables if
8411 	       * possible
8412 	       */
8413 	      SCIP_CALL( presolvePropagateCons(scip, cons, TRUE, NULL, NULL, NULL, NULL, nfixedvars, naggrvars, ndelconss, &cutoff) );
8414 	
8415 	      if( cutoff )
8416 	      {
8417 	         *result = SCIP_CUTOFF;
8418 	         return SCIP_OKAY;
8419 	      }
8420 	
8421 	      /* if constraint was deleted while propagation, go to the next constraint */
8422 	      if( !SCIPconsIsActive(cons) )
8423 	         continue;
8424 	
8425 	      /* remove fixings found by presolvePropagateCons() */
8426 	      if( consdata->nfixedzeros > 0 )
8427 	      {
8428 	         SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, &cutoff) );
8429 	
8430 	         if( cutoff )
8431 	         {
8432 	            *result = SCIP_CUTOFF;
8433 	            return SCIP_OKAY;
8434 	         }
8435 	
8436 	         if( SCIPconsIsDeleted(cons) )
8437 	            continue;
8438 	      }
8439 	
8440 	      /* perform dual reductions */
8441 	      if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
8442 	      {
8443 	         SCIP_CALL( dualPresolving(scip, cons, nfixedvars, ndelconss, naggrvars, result) );
8444 	
8445 	         /* if dual reduction deleted the constraint we take the next */
8446 	         if( !SCIPconsIsActive(cons) )
8447 	            continue;
8448 	      }
8449 	
8450 	      /* remember the first changed constraint to begin the next redundancy round with */
8451 	      if( firstchange == INT_MAX && consdata->changed )
8452 	         firstchange = c;
8453 	
8454 	      /* remember the first and last constraints for which we have to add the clique information */
8455 	      if( !consdata->cliqueadded && consdata->nvars >= 2 )
8456 	      {
8457 	         if( firstclique == INT_MAX )
8458 	            firstclique = c;
8459 	         lastclique = c;
8460 	      }
8461 	   }
8462 	
8463 	   /* update result pointer */
8464 	   if( oldnfixedvars < *nfixedvars || oldnaggrvars < *naggrvars || oldndelconss < *ndelconss || oldnchgcoefs < *nchgcoefs )
8465 	      *result = SCIP_SUCCESS;
8466 	
8467 	   if( firstchange < nconss && conshdlrdata->presolusehashing )
8468 	   {
8469 	      /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
8470 	      SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, ndelconss, nchgsides) );
8471 	      if( oldndelconss < *ndelconss )
8472 	         *result = SCIP_SUCCESS;
8473 	   }
8474 	
8475 	   /* determine singleton variables in set-partitioning/-packing constraints, or doubleton variables (active and
8476 	    * negated) in any combination of set-partitioning and set-packing constraints
8477 	    */
8478 	   if( nconss > 1 && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0
8479 	      && ((conshdlrdata->nsetpart > 0 && !SCIPdoNotMultaggr(scip) && conshdlrdata->conshdlrlinear != NULL)
8480 	         || (conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip)
8481 	               && conshdlrdata->nsetpart < nconss && !SCIPdoNotAggr(scip))) )
8482 	   {
8483 	      SCIP_CALL( removeDoubleAndSingletonsAndPerformDualpresolve(scip, conss, nconss, conshdlrdata->dualpresolving
8484 	            && SCIPallowStrongDualReds(scip), conshdlrdata->conshdlrlinear != NULL, nfixedvars,
8485 	            naggrvars, ndelconss, nchgcoefs, nchgsides, &cutoff) );
8486 	
8487 	      if( cutoff )
8488 	      {
8489 	         *result = SCIP_CUTOFF;
8490 	         return SCIP_OKAY;
8491 	      }
8492 	      else if( oldnfixedvars < *nfixedvars || oldnaggrvars < *naggrvars || oldndelconss < *ndelconss )
8493 	         *result = SCIP_SUCCESS;
8494 	   }
8495 	
8496 	   /* clique lifting */
8497 	   if( conshdlrdata->cliquelifting && conshdlrdata->enablecliquelifting && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
8498 	   {
8499 	      /* add cliques first before lifting variables */
8500 	      SCIP_CALL( addCliques(scip, conss, nconss, firstclique, lastclique, naddconss, ndelconss, nchgbds, &cutoff) );
8501 	
8502 	      if( cutoff )
8503 	      {
8504 	         *result = SCIP_CUTOFF;
8505 	         return SCIP_OKAY;
8506 	      }
8507 	
8508 	      firstclique = nconss;
8509 	      lastclique = -1;
8510 	
8511 	      /* lift variables and check for fixings due to clique information */
8512 	      SCIP_CALL( preprocessCliques(scip, conshdlrdata, conss, nconss, nrounds, &firstchange, &firstclique,
8513 	            &lastclique, nfixedvars, naggrvars, ndelconss, nchgcoefs, &cutoff) );
8514 	      ++(conshdlrdata->nclqpresolve);
8515 	
8516 	      if( cutoff )
8517 	      {
8518 	         *result = SCIP_CUTOFF;
8519 	         return SCIP_OKAY;
8520 	      }
8521 	      else if( oldnfixedvars < *nfixedvars || oldnaggrvars < *naggrvars || oldndelconss < *ndelconss || oldnchgcoefs < *nchgcoefs )
8522 	         *result = SCIP_SUCCESS;
8523 	
8524 	      /* remember the number of fixings */
8525 	      conshdlrdata->noldfixedvars = *nfixedvars + *naggrvars;
8526 	      conshdlrdata->enablecliquelifting = FALSE;
8527 	   }
8528 	
8529 	   if( oldndelconss == *ndelconss && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
8530 	   {
8531 	      /* check constraints for redundancy */
8532 	      if( conshdlrdata->presolpairwise )
8533 	      {
8534 	         SCIP_Longint npaircomparisons = 0;
8535 	
8536 	         oldndelconss = *ndelconss;
8537 	         oldnfixedvars = *nfixedvars;
8538 	
8539 	         for( c = firstchange; c < nconss && !SCIPisStopped(scip); ++c )
8540 	         {
8541 	            assert(*result != SCIP_CUTOFF);
8542 	
8543 	            if( SCIPconsIsActive(conss[c]) && !SCIPconsIsModifiable(conss[c]) )
8544 	            {
8545 	               npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? (SCIP_Longint) c : ((SCIP_Longint) c - (SCIP_Longint) firstchange);
8546 	
8547 	               SCIP_CALL( removeRedundantConstraints(scip, conss, firstchange, c, &cutoff, nfixedvars, ndelconss, nchgsides) );
8548 	               if( cutoff )
8549 	               {
8550 	                  *result = SCIP_CUTOFF;
8551 	                  return SCIP_OKAY;
8552 	               }
8553 	
8554 	               if( npaircomparisons > NMINCOMPARISONS )
8555 	               {
8556 	                  if( (*ndelconss - oldndelconss + *nfixedvars - oldnfixedvars) / ((SCIP_Real)npaircomparisons) < MINGAINPERNMINCOMPARISONS )
8557 	                     break;
8558 	                  oldndelconss = *ndelconss;
8559 	                  oldnfixedvars = *nfixedvars;
8560 	                  npaircomparisons = 0;
8561 	                  *result = SCIP_SUCCESS;
8562 	               }
8563 	            }
8564 	         }
8565 	      }
8566 	   }
8567 	
8568 	   /* add cliques after lifting variables */
8569 	   SCIP_CALL( addCliques(scip, conss, nconss, MIN(firstclique, nconss), MIN(lastclique, nconss), naddconss, ndelconss,
8570 	         nchgbds, &cutoff) );
8571 	
8572 	   if( cutoff )
8573 	      *result = SCIP_CUTOFF;
8574 	
8575 	   conshdlrdata->noldupgrs = nconss - (*ndelconss - startdelconss);
8576 	
8577 	   return SCIP_OKAY;
8578 	}
8579 	
8580 	
8581 	/** propagation conflict resolving method of constraint handler */
8582 	static
8583 	SCIP_DECL_CONSRESPROP(consRespropSetppc)
8584 	{  /*lint --e{715}*/
8585 	   SCIP_CONSDATA* consdata;
8586 	   int v;
8587 	
8588 	   assert(conshdlr != NULL);
8589 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8590 	   assert(cons != NULL);
8591 	   assert(infervar != NULL);
8592 	   assert(result != NULL);
8593 	
8594 	   consdata = SCIPconsGetData(cons);
8595 	   assert(consdata != NULL);
8596 	
8597 	   SCIPdebugMsg(scip, "conflict resolving method of set partitioning / packing / covering constraint handler\n");
8598 	
8599 	   if( (SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_COVERING
8600 	      || ((SCIP_SETPPCTYPE)consdata->setppctype == SCIP_SETPPCTYPE_PARTITIONING
8601 	         && SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5) )
8602 	   {
8603 	#ifndef NDEBUG
8604 	      SCIP_Bool confvarfound;
8605 	#endif
8606 	
8607 	      /* the inference constraint is a set partitioning or covering constraint with the inference variable inferred to 1.0:
8608 	       * the reason for the deduction is the assignment of 0.0 to all other variables
8609 	       */
8610 	#ifndef NDEBUG
8611 	      confvarfound = FALSE;
8612 	#endif
8613 	      for( v = 0; v < consdata->nvars; ++v )
8614 	      {
8615 	         if( consdata->vars[v] != infervar )
8616 	         {
8617 	            /* the reason variable must be assigned to zero */
8618 	            assert(SCIPgetVarUbAtIndex(scip, consdata->vars[v], bdchgidx, FALSE) < 0.5);
8619 	            SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
8620 	         }
8621 	#ifndef NDEBUG
8622 	         else
8623 	         {
8624 	            assert(!confvarfound);
8625 	            confvarfound = TRUE;
8626 	         }
8627 	#endif
8628 	      }
8629 	      assert(confvarfound);
8630 	   }
8631 	   else
8632 	   {
8633 	      /* the inference constraint is a set partitioning or packing constraint with the inference variable inferred to 0.0:
8634 	       * the reason for the deduction is the assignment of 1.0 to a single variable
8635 	       */
8636 	      assert(SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5);
8637 	
8638 	      if( inferinfo >= 0 )
8639 	      {
8640 	         assert(SCIPgetVarLbAtIndex(scip, consdata->vars[inferinfo], bdchgidx, FALSE) > 0.5);
8641 	         SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[inferinfo]) );
8642 	      }
8643 	      else
8644 	      {
8645 	         for( v = 0; v < consdata->nvars; ++v )
8646 	         {
8647 	            if( SCIPgetVarLbAtIndex(scip, consdata->vars[v], bdchgidx, FALSE) > 0.5 )
8648 	            {
8649 	               SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[v]) );
8650 	               break;
8651 	            }
8652 	         }
8653 	         assert(v < consdata->nvars);
8654 	      }
8655 	   }
8656 	
8657 	   *result = SCIP_SUCCESS;
8658 	
8659 	   return SCIP_OKAY;
8660 	}
8661 	
8662 	
8663 	/** variable rounding lock method of constraint handler */
8664 	static
8665 	SCIP_DECL_CONSLOCK(consLockSetppc)
8666 	{  /*lint --e{715}*/
8667 	   SCIP_CONSDATA* consdata;
8668 	   int nlocksdown;
8669 	   int nlocksup;
8670 	   int i;
8671 	
8672 	   consdata = SCIPconsGetData(cons);
8673 	   assert(consdata != NULL);
8674 	
8675 	   switch( consdata->setppctype )
8676 	   {
8677 	   case SCIP_SETPPCTYPE_PARTITIONING:
8678 	      nlocksdown = nlockspos + nlocksneg;
8679 	      nlocksup = nlockspos + nlocksneg;
8680 	      break;
8681 	   case SCIP_SETPPCTYPE_PACKING:
8682 	      nlocksdown = nlocksneg;
8683 	      nlocksup = nlockspos;
8684 	      break;
8685 	   case SCIP_SETPPCTYPE_COVERING:
8686 	      nlocksdown = nlockspos;
8687 	      nlocksup = nlocksneg;
8688 	      break;
8689 	   default:
8690 	      SCIPerrorMessage("unknown setppc type\n");
8691 	      return SCIP_INVALIDDATA;
8692 	   }
8693 	
8694 	   for( i = 0; i < consdata->nvars; ++i )
8695 	   {
8696 	      SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksdown, nlocksup) );
8697 	   }
8698 	
8699 	   return SCIP_OKAY;
8700 	}
8701 	
8702 	
8703 	/** constraint activation notification method of constraint handler */
8704 	static
8705 	SCIP_DECL_CONSACTIVE(consActiveSetppc)
8706 	{  /*lint --e{715}*/
8707 	   assert(cons != NULL);
8708 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8709 	   assert(SCIPconsIsTransformed(cons));
8710 	
8711 	   SCIPdebugMsg(scip, "activation information for set partitioning / packing / covering constraint <%s>\n",
8712 	      SCIPconsGetName(cons));
8713 	
8714 	   /* we only might add the constraint to the propagation list, when we are not activating it in probing mode */
8715 	   if( SCIPgetStage(scip) > SCIP_STAGE_TRANSFORMING )
8716 	   {
8717 	      SCIP_CONSDATA* consdata = SCIPconsGetData(cons);
8718 	      assert(consdata != NULL);
8719 	
8720 	      if( consdata->nfixedones >= 1 || consdata->nfixedzeros >= consdata->nvars - 1 )
8721 	      {
8722 	         SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
8723 	      }
8724 	   }
8725 	
8726 	#ifdef VARUSES
8727 	   /* increase the number of uses for each variable in the constraint */
8728 	   SCIP_CALL( consdataIncVaruses(scip, SCIPconshdlrGetData(conshdlr), SCIPconsGetData(cons)) );
8729 	#endif
8730 	
8731 	   if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisNLPConstructed(scip) )
8732 	   {
8733 	      SCIP_CALL( addNlrow(scip, cons) );
8734 	   }
8735 	
8736 	   return SCIP_OKAY;
8737 	}
8738 	
8739 	
8740 	/** constraint deactivation notification method of constraint handler */
8741 	static
8742 	SCIP_DECL_CONSDEACTIVE(consDeactiveSetppc)
8743 	{  /*lint --e{715}*/
8744 	   SCIP_CONSDATA* consdata;
8745 	
8746 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
8747 	   assert(SCIPconsIsTransformed(cons));
8748 	
8749 	   SCIPdebugMsg(scip, "deactivation information for set partitioning / packing / covering constraint <%s>\n",
8750 	      SCIPconsGetName(cons));
8751 	
8752 	   /* get constraint data */
8753 	   consdata = SCIPconsGetData(cons);
8754 	   assert(consdata != NULL);
8755 	
8756 	#ifdef VARUSES
8757 	   /* decrease the number of uses for each variable in the constraint */
8758 	   SCIP_CALL( consdataDecVaruses(scip, SCIPconshdlrGetData(conshdlr), condata) );
8759 	#endif
8760 	
8761 	   if( SCIPconsIsDeleted(cons) )
8762 	   {
8763 	      SCIP_CONSHDLRDATA* conshdlrdata;
8764 	
8765 	      /* get event handler */
8766 	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
8767 	      assert(conshdlrdata != NULL);
8768 	      assert(conshdlrdata->eventhdlr != NULL);
8769 	
8770 	      /* if constraint belongs to transformed problem space, drop bound change events on variables */
8771 	      if( consdata->nvars > 0 && SCIPvarIsTransformed(consdata->vars[0]) )
8772 	      {
8773 	         SCIP_CALL( dropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
8774 	      }
8775 	   }
8776 	
8777 	   /* remove row from NLP, if still in solving
8778 	    * if we are in exitsolve, the whole NLP will be freed anyway
8779 	    */
8780 	   if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
8781 	   {
8782 	      SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
8783 	   }
8784 	
8785 	   return SCIP_OKAY;
8786 	}
8787 	
8788 	/** variable deletion method of constraint handler */
8789 	static
8790 	SCIP_DECL_CONSDELVARS(consDelvarsSetppc)
8791 	{
8792 	   assert( scip != NULL );
8793 	   assert( conshdlr != NULL );
8794 	   assert( conss != NULL || nconss == 0 );
8795 	
8796 	   if( nconss > 0 )
8797 	   {
8798 	      SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
8799 	   }
8800 	
8801 	   return SCIP_OKAY;
8802 	}
8803 	
8804 	
8805 	
8806 	/** constraint display method of constraint handler */
8807 	static
8808 	SCIP_DECL_CONSPRINT(consPrintSetppc)
8809 	{  /*lint --e{715}*/
8810 	   assert( scip != NULL );
8811 	   assert( conshdlr != NULL );
8812 	   assert( cons != NULL );
8813 	
8814 	   SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
8815 	
8816 	   return SCIP_OKAY;
8817 	}
8818 	
8819 	/** constraint copying method of constraint handler */
8820 	static
8821 	SCIP_DECL_CONSCOPY(consCopySetppc)
8822 	{  /*lint --e{715}*/
8823 	   SCIP_VAR** sourcevars;
8824 	   const char* consname;
8825 	   SCIP_Real lhs;
8826 	   SCIP_Real rhs;
8827 	   int nvars;
8828 	   SCIP_SETPPCTYPE type;
8829 	
8830 	   /* get variables and coefficients of the source constraint */
8831 	   sourcevars = SCIPgetVarsSetppc(sourcescip, sourcecons);
8832 	   nvars = SCIPgetNVarsSetppc(sourcescip, sourcecons);
8833 	
8834 	   /* get setppc type */
8835 	   type = SCIPgetTypeSetppc(sourcescip, sourcecons);
8836 	   lhs = -SCIPinfinity(scip);
8837 	   rhs = SCIPinfinity(scip);
8838 	
8839 	   switch( type )
8840 	   {
8841 	   case SCIP_SETPPCTYPE_PARTITIONING:
8842 	      lhs = 1.0;
8843 	      rhs = 1.0;
8844 	      break;
8845 	   case SCIP_SETPPCTYPE_PACKING:
8846 	      rhs = 1.0;
8847 	      break;
8848 	   case SCIP_SETPPCTYPE_COVERING:
8849 	      lhs = 1.0;
8850 	      break;
8851 	   default:
8852 	      SCIPerrorMessage("unknown setppc type\n");
8853 	      return SCIP_INVALIDDATA;
8854 	   }
8855 	
8856 	   if( name != NULL )
8857 	      consname = name;
8858 	   else
8859 	      consname = SCIPconsGetName(sourcecons);
8860 	
8861 	   /* copy the logic using the linear constraint copy method */
8862 	   SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, NULL,
8863 	         lhs, rhs, varmap, consmap,
8864 	         initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
8865 	   assert(cons != NULL);
8866 	
8867 	   return SCIP_OKAY;
8868 	}
8869 	
8870 	/** constraint parsing method of constraint handler */
8871 	static
8872 	SCIP_DECL_CONSPARSE(consParseSetppc)
8873 	{  /*lint --e{715}*/
8874 	   SCIP_VAR** vars;
8875 	   int nvars;
8876 	
8877 	   assert(scip != NULL);
8878 	   assert(success != NULL);
8879 	   assert(str != NULL);
8880 	   assert(name != NULL);
8881 	   assert(cons != NULL);
8882 	
8883 	   *success = TRUE;
8884 	
8885 	   nvars = 0;
8886 	   vars = NULL;
8887 	
8888 	   /* check if lhs is just 0 */
8889 	   if( str[0] == '0' )
8890 	   {
8891 	      assert(str[1] == ' ');
8892 	      str += 2;
8893 	   }
8894 	   else
8895 	   {
8896 	      SCIP_Real* coefs;
8897 	      char* endptr;
8898 	      int coefssize;
8899 	      int requsize;
8900 	
8901 	      /* initialize buffers for storing the coefficients */
8902 	      coefssize = 100;
8903 	      SCIP_CALL( SCIPallocBufferArray(scip, &vars,  coefssize) );
8904 	      SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
8905 	
8906 	      /* parse linear sum to get variables and coefficients */
8907 	      SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
8908 	
8909 	      if( *success && requsize > coefssize )
8910 	      {
8911 	         /* realloc buffers and try again */
8912 	         coefssize = requsize;
8913 	         SCIP_CALL( SCIPreallocBufferArray(scip, &vars,  coefssize) );
8914 	         SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
8915 	
8916 	         SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
8917 	         assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
8918 	      }
8919 	
8920 	      if( !*success )
8921 	      {
8922 	         SCIPerrorMessage("no luck in parsing linear sum '%s'\n", str);
8923 	      }
8924 	      else
8925 	         str = endptr;
8926 	
8927 	      /* free coefficient array */
8928 	      SCIPfreeBufferArray(scip, &coefs);
8929 	   }
8930 	
8931 	   /* remove white spaces */
8932 	   SCIP_CALL( SCIPskipSpace((char**)&str) );
8933 	
8934 	   if( *success )
8935 	   {
8936 	      switch( *str )
8937 	      {
8938 	         case '=' :
8939 	            SCIP_CALL( SCIPcreateConsSetpart(scip, cons, name, nvars, vars,
8940 	                  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
8941 	            break;
8942 	         case '<' :
8943 	            SCIP_CALL( SCIPcreateConsSetpack(scip, cons, name, nvars, vars,
8944 	                  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
8945 	            break;
8946 	         case '>' :
8947 	            SCIP_CALL( SCIPcreateConsSetcover(scip, cons, name, nvars, vars,
8948 	                  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
8949 	            break;
8950 	         default:
8951 	            SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "error parsing setppc type\n");
8952 	            *success = FALSE;
8953 	            break;
8954 	      }
8955 	   }
8956 	
8957 	   /* free variable array */
8958 	   SCIPfreeBufferArrayNull(scip, &vars);
8959 	
8960 	   return SCIP_OKAY;
8961 	}
8962 	
8963 	/** constraint method of constraint handler which returns the variables (if possible) */
8964 	static
8965 	SCIP_DECL_CONSGETVARS(consGetVarsSetppc)
8966 	{  /*lint --e{715}*/
8967 	   SCIP_CONSDATA* consdata;
8968 	
8969 	   consdata = SCIPconsGetData(cons);
8970 	   assert(consdata != NULL);
8971 	
8972 	   if( varssize < consdata->nvars )
8973 	      (*success) = FALSE;
8974 	   else
8975 	   {
8976 	      assert(vars != NULL);
8977 	
8978 	      BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
8979 	      (*success) = TRUE;
8980 	   }
8981 	
8982 	   return SCIP_OKAY;
8983 	}
8984 	
8985 	/** constraint method of constraint handler which returns the number of variables (if possible) */
8986 	static
8987 	SCIP_DECL_CONSGETNVARS(consGetNVarsSetppc)
8988 	{  /*lint --e{715}*/
8989 	   SCIP_CONSDATA* consdata;
8990 	
8991 	   consdata = SCIPconsGetData(cons);
8992 	   assert(consdata != NULL);
8993 	
8994 	   (*nvars) = consdata->nvars;
8995 	   (*success) = TRUE;
8996 	
8997 	   return SCIP_OKAY;
8998 	}
8999 	
9000 	/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
9001 	static
9002 	SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphSetppc)
9003 	{  /*lint --e{715}*/
9004 	   SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
9005 	
9006 	   return SCIP_OKAY;
9007 	}
9008 	
9009 	/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
9010 	static
9011 	SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphSetppc)
9012 	{  /*lint --e{715}*/
9013 	   SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
9014 	
9015 	   return SCIP_OKAY;
9016 	}
9017 	
9018 	/*
9019 	 * Callback methods of event handler
9020 	 */
9021 	
9022 	static
9023 	SCIP_DECL_EVENTEXEC(eventExecSetppc)
9024 	{  /*lint --e{715}*/
9025 	   SCIP_CONS* cons;
9026 	   SCIP_CONSDATA* consdata;
9027 	   SCIP_EVENTTYPE eventtype;
9028 	
9029 	   assert(eventhdlr != NULL);
9030 	   assert(eventdata != NULL);
9031 	   assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
9032 	   assert(event != NULL);
9033 	
9034 	   /*debugMsg(scip, "Exec method of bound change event handler for set partitioning / packing / covering constraints\n");*/
9035 	
9036 	   cons = (SCIP_CONS*)eventdata;
9037 	   assert(cons != NULL);
9038 	
9039 	   consdata = SCIPconsGetData(cons);
9040 	   assert(consdata != NULL);
9041 	
9042 	   eventtype = SCIPeventGetType(event);
9043 	
9044 	   switch( eventtype )
9045 	   {
9046 	   case SCIP_EVENTTYPE_LBTIGHTENED:
9047 	      consdata->nfixedones++;
9048 	      break;
9049 	   case SCIP_EVENTTYPE_LBRELAXED:
9050 	      consdata->nfixedones--;
9051 	      break;
9052 	   case SCIP_EVENTTYPE_UBTIGHTENED:
9053 	      consdata->nfixedzeros++;
9054 	      break;
9055 	   case SCIP_EVENTTYPE_UBRELAXED:
9056 	      consdata->nfixedzeros--;
9057 	      break;
9058 	   case SCIP_EVENTTYPE_VARDELETED:
9059 	      consdata->varsdeleted = TRUE;
9060 	      break;
9061 	   case SCIP_EVENTTYPE_VARFIXED:
9062 	      if( consdata->merged )
9063 	      {
9064 		 SCIP_VAR* var = SCIPeventGetVar(event);
9065 	
9066 		 /* this event should only arise during the presolving stage */
9067 		 assert(SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING);
9068 		 assert(var != NULL);
9069 	
9070 		 /* one variable was changed to a negated or aggregated variable, so maybe we can merge again */
9071 		 if( SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED && SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5 )
9072 		    consdata->merged = FALSE;
9073 	      }
9074 	
9075 	      if( !consdata->existmultaggr )
9076 	      {
9077 		 SCIP_VAR* var = SCIPeventGetVar(event);
9078 		 assert(var != NULL);
9079 	
9080 	         if( SCIPvarGetStatus(SCIPvarGetProbvar(var)) == SCIP_VARSTATUS_MULTAGGR )
9081 	            consdata->existmultaggr = TRUE;
9082 	      }
9083 	      break;
9084 	   default:
9085 	      SCIPerrorMessage("invalid event type\n");
9086 	      return SCIP_INVALIDDATA;
9087 	   }
9088 	   assert(0 <= consdata->nfixedzeros && consdata->nfixedzeros <= consdata->nvars);
9089 	   assert(0 <= consdata->nfixedones && consdata->nfixedones <= consdata->nvars);
9090 	
9091 	   if( eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED )
9092 	   {
9093 	      if( consdata->nfixedones >= 1 || consdata->nfixedzeros >= consdata->nvars - 1 )
9094 	      {
9095 	         consdata->presolpropagated = FALSE;
9096 	         SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
9097 	      }
9098 	      else if( (SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE) && (consdata->nfixedzeros >= consdata->nvars - 2) )
9099 	      {
9100 	         consdata->presolpropagated = FALSE;
9101 	      }
9102 	   }
9103 	
9104 	   /*debugMsg(scip, " -> constraint has %d zero-fixed and %d one-fixed of %d variables\n",
9105 	     consdata->nfixedzeros, consdata->nfixedones, consdata->nvars);*/
9106 	
9107 	   return SCIP_OKAY;
9108 	}
9109 	
9110 	
9111 	
9112 	
9113 	/*
9114 	 * Callback methods of conflict handler
9115 	 */
9116 	
9117 	/** conflict processing method of conflict handler (called when conflict was found) */
9118 	static
9119 	SCIP_DECL_CONFLICTEXEC(conflictExecSetppc)
9120 	{  /*lint --e{715}*/
9121 	   SCIP_VAR** vars;
9122 	   int i;
9123 	
9124 	   assert(conflicthdlr != NULL);
9125 	   assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
9126 	   assert(bdchginfos != NULL || nbdchginfos == 0);
9127 	   assert(result != NULL);
9128 	
9129 	   /* don't process already resolved conflicts */
9130 	   if( resolved )
9131 	   {
9132 	      *result = SCIP_DIDNOTRUN;
9133 	      return SCIP_OKAY;
9134 	   }
9135 	
9136 	   *result = SCIP_DIDNOTFIND;
9137 	
9138 	   /* for two (binary) variables we will create a set packing constraint and add the clique information of the conflict is global */
9139 	   if( nbdchginfos == 2 )
9140 	   {
9141 	      SCIP_CONS* cons;
9142 	      char consname[SCIP_MAXSTRLEN];
9143 	      SCIP_VAR* twovars[2];
9144 	
9145 	      assert(bdchginfos != NULL);
9146 	
9147 	      twovars[0] = SCIPbdchginfoGetVar(bdchginfos[0]);
9148 	
9149 	      /* we can only treat binary variables */
9150 	      if( !SCIPvarIsBinary(twovars[0]) )
9151 	         return SCIP_OKAY;
9152 	
9153 	      /* if the variable is fixed to zero in the conflict set, we have to use its negation */
9154 	      if( SCIPbdchginfoGetNewbound(bdchginfos[0]) < 0.5 )
9155 	      {
9156 	         SCIP_CALL( SCIPgetNegatedVar(scip, twovars[0], &twovars[0]) );
9157 	      }
9158 	
9159 	      twovars[1] = SCIPbdchginfoGetVar(bdchginfos[1]);
9160 	
9161 	      /* we can only treat binary variables */
9162 	      if( !SCIPvarIsBinary(twovars[1]) )
9163 	         return SCIP_OKAY;
9164 	
9165 	      /* if the variable is fixed to zero in the conflict set, we have to use its negation */
9166 	      if( SCIPbdchginfoGetNewbound(bdchginfos[1]) < 0.5 )
9167 	      {
9168 	         SCIP_CALL( SCIPgetNegatedVar(scip, twovars[1], &twovars[1]) );
9169 	      }
9170 	
9171 	      /* create a constraint out of the conflict set */
9172 	      (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%d_%" SCIP_LONGINT_FORMAT, SCIPgetNRuns(scip), SCIPgetNConflictConssApplied(scip));
9173 	      SCIP_CALL( SCIPcreateConsSetpack(scip, &cons, consname, 2, twovars,
9174 	            FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
9175 	
9176 	      /* if the constraint gets globally added, we also add the clique information */
9177 	      if( !SCIPconsIsLocal(cons) )
9178 	      {
9179 	         SCIP_Bool infeasible;
9180 	         int ncliquebdchgs;
9181 	
9182 	         SCIP_CALL( SCIPaddClique(scip, twovars, NULL, 2, FALSE, &infeasible, &ncliquebdchgs) );
9183 	
9184 	         SCIPdebugMsg(scip, "new clique of conflict constraint %s led to %d fixings\n", consname, ncliquebdchgs);
9185 	
9186 	         if( infeasible )
9187 	         {
9188 	            SCIPdebugMsg(scip, "new clique of conflict constraint %s led to infeasibility\n", consname);
9189 	         }
9190 	      }
9191 	
9192 	      /* add conflict to SCIP */
9193 	      SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
9194 	
9195 	      *result = SCIP_CONSADDED;
9196 	
9197 	      return SCIP_OKAY;
9198 	   }
9199 	
9200 	   /* create array of variables in conflict constraint */
9201 	   SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
9202 	   for( i = 0; i < nbdchginfos; ++i )
9203 	   {
9204 	      assert(bdchginfos != NULL);
9205 	
9206 	      vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
9207 	
9208 	      /* we can only treat binary variables */
9209 	      if( !SCIPvarIsBinary(vars[i]) )
9210 	         break;
9211 	
9212 	      /* if the variable is fixed to one in the conflict set, we have to use its negation */
9213 	      if( SCIPbdchginfoGetNewbound(bdchginfos[i]) > 0.5 )
9214 	      {
9215 	         SCIP_CALL( SCIPgetNegatedVar(scip, vars[i], &vars[i]) );
9216 	      }
9217 	   }
9218 	
9219 	   if( i == nbdchginfos )
9220 	   {
9221 	      SCIP_CONS* cons;
9222 	      char consname[SCIP_MAXSTRLEN];
9223 	
9224 	      /* create a constraint out of the conflict set */
9225 	      (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%d_%" SCIP_LONGINT_FORMAT, SCIPgetNRuns(scip), SCIPgetNConflictConssApplied(scip));
9226 	      SCIP_CALL( SCIPcreateConsSetcover(scip, &cons, consname, nbdchginfos, vars,
9227 	            FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
9228 	      SCIP_CALL( SCIPaddConsNode(scip, node, cons, validnode) );
9229 	      SCIP_CALL( SCIPreleaseCons(scip, &cons) );
9230 	
9231 	      *result = SCIP_CONSADDED;
9232 	   }
9233 	
9234 	   /* free temporary memory */
9235 	   SCIPfreeBufferArray(scip, &vars);
9236 	
9237 	   return SCIP_OKAY;
9238 	}
9239 	
9240 	
9241 	
9242 	
9243 	/*
9244 	 * constraint specific interface methods
9245 	 */
9246 	
9247 	/** creates the handler for set partitioning / packing / covering constraints and includes it in SCIP */
9248 	SCIP_RETCODE SCIPincludeConshdlrSetppc(
9249 	   SCIP*                 scip                /**< SCIP data structure */
9250 	   )
9251 	{
9252 	   SCIP_CONSHDLRDATA* conshdlrdata;
9253 	   SCIP_CONSHDLR* conshdlr;
9254 	   SCIP_EVENTHDLR* eventhdlr;
9255 	
9256 	   /* create event handler for bound change events */
9257 	   SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC,
9258 	         eventExecSetppc, NULL) );
9259 	
9260 	   /* create conflict handler for setppc constraints */
9261 	   SCIP_CALL( SCIPincludeConflicthdlrBasic(scip, NULL, CONFLICTHDLR_NAME, CONFLICTHDLR_DESC, CONFLICTHDLR_PRIORITY,
9262 	         conflictExecSetppc, NULL) );
9263 	
9264 	   /* create constraint handler data */
9265 	   SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
9266 	
9267 	   /* include constraint handler */
9268 	   SCIP_CALL( SCIPincludeConshdlrBasic(scip, &conshdlr, CONSHDLR_NAME, CONSHDLR_DESC,
9269 	         CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY, CONSHDLR_EAGERFREQ, CONSHDLR_NEEDSCONS,
9270 	         consEnfolpSetppc, consEnfopsSetppc, consCheckSetppc, consLockSetppc,
9271 	         conshdlrdata) );
9272 	   assert(conshdlr != NULL);
9273 	
9274 	   /* set non-fundamental callbacks via specific setter functions */
9275 	   SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveSetppc) );
9276 	   SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveSetppc) );
9277 	   SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopySetppc, consCopySetppc) );
9278 	   SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteSetppc) );
9279 	   SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsSetppc) );
9280 	   SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreSetppc) );
9281 	   SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolSetppc) );
9282 	   SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolSetppc) );
9283 	   SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeSetppc) );
9284 	   SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsSetppc) );
9285 	   SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsSetppc) );
9286 	   SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitSetppc) );
9287 	   SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpSetppc) );
9288 	   SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseSetppc) );
9289 	   SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolSetppc, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
9290 	   SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintSetppc) );
9291 	   SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropSetppc, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
9292 	         CONSHDLR_PROP_TIMING) );
9293 	   SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropSetppc) );
9294 	   SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpSetppc, consSepasolSetppc, CONSHDLR_SEPAFREQ,
9295 	         CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
9296 	   SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransSetppc) );
9297 	   SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxSetppc) );
9298 	   SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphSetppc) );
9299 	   SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphSetppc) );
9300 	
9301 	   conshdlrdata->conshdlrlinear = SCIPfindConshdlr(scip,"linear");
9302 	
9303 	   if( conshdlrdata->conshdlrlinear != NULL )
9304 	   {
9305 	      /* include the linear constraint to setppc constraint upgrade in the linear constraint handler */
9306 	      SCIP_CALL( SCIPincludeLinconsUpgrade(scip, linconsUpgdSetppc, LINCONSUPGD_PRIORITY, CONSHDLR_NAME) );
9307 	   }
9308 	   if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
9309 	   {
9310 	      /* notify function that upgrades quadratic constraint to setpacking */
9311 	      SCIP_CALL( SCIPincludeConsUpgradeNonlinear(scip, nonlinUpgdSetppc, NONLINCONSUPGD_PRIORITY, TRUE, CONSHDLR_NAME) );
9312 	   }
9313 	
9314 	   /* set partitioning constraint handler parameters */
9315 	   SCIP_CALL( SCIPaddIntParam(scip,
9316 	         "constraints/" CONSHDLR_NAME "/npseudobranches",
9317 	         "number of children created in pseudo branching (0: disable pseudo branching)",
9318 	         &conshdlrdata->npseudobranches, TRUE, DEFAULT_NPSEUDOBRANCHES, 0, INT_MAX, NULL, NULL) );
9319 	   SCIP_CALL( SCIPaddBoolParam(scip,
9320 	         "constraints/" CONSHDLR_NAME "/presolpairwise",
9321 	         "should pairwise constraint comparison be performed in presolving?",
9322 	         &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
9323 	   SCIP_CALL( SCIPaddBoolParam(scip,
9324 	         "constraints/" CONSHDLR_NAME "/presolusehashing",
9325 	         "should hash table be used for detecting redundant constraints in advance",
9326 	         &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
9327 	   SCIP_CALL( SCIPaddBoolParam(scip,
9328 	         "constraints/" CONSHDLR_NAME "/dualpresolving",
9329 	         "should dual presolving steps be performed?",
9330 	         &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
9331 	   SCIP_CALL( SCIPaddBoolParam(scip,
9332 	         "constraints/" CONSHDLR_NAME "/cliquelifting",
9333 	         " should we try to lift variables into other clique constraints, fix variables, aggregate them, and also shrink the amount of variables in clique constraints",
9334 	         &conshdlrdata->cliquelifting, TRUE, DEFAULT_CLIQUELIFTING, NULL, NULL) );
9335 	   SCIP_CALL( SCIPaddBoolParam(scip,
9336 	         "constraints/" CONSHDLR_NAME "/addvariablesascliques",
9337 	         "should we try to generate extra cliques out of all binary variables to maybe fasten redundant constraint detection",
9338 	         &conshdlrdata->addvariablesascliques, TRUE, DEFAULT_ADDVARIABLESASCLIQUES, NULL, NULL) );
9339 	   SCIP_CALL( SCIPaddBoolParam(scip,
9340 	         "constraints/" CONSHDLR_NAME "/cliqueshrinking",
9341 	         "should we try to shrink the number of variables in a clique constraints, by replacing more than one variable by only one",
9342 	         &conshdlrdata->cliqueshrinking, TRUE, DEFAULT_CLIQUESHRINKING, NULL, NULL) );
9343 	
9344 	   return SCIP_OKAY;
9345 	}
9346 	
9347 	/** creates and captures a set partitioning constraint
9348 	 *
9349 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9350 	 */
9351 	SCIP_RETCODE SCIPcreateConsSetpart(
9352 	   SCIP*                 scip,               /**< SCIP data structure */
9353 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
9354 	   const char*           name,               /**< name of constraint */
9355 	   int                   nvars,              /**< number of variables in the constraint */
9356 	   SCIP_VAR**            vars,               /**< array with variables of constraint entries */
9357 	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
9358 	                                              *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
9359 	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
9360 	                                              *   Usually set to TRUE. */
9361 	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
9362 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
9363 	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
9364 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
9365 	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
9366 	                                              *   Usually set to TRUE. */
9367 	   SCIP_Bool             local,              /**< is constraint only valid locally?
9368 	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
9369 	   SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)?
9370 	                                              *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
9371 	                                              *   adds coefficients to this constraint. */
9372 	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
9373 	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
9374 	                                              *   are separated as constraints. */
9375 	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
9376 	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
9377 	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
9378 	                                              *   if it may be moved to a more global node?
9379 	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
9380 	   )
9381 	{
9382 	   return createConsSetppc(scip, cons, name, nvars, vars, SCIP_SETPPCTYPE_PARTITIONING,
9383 	      initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode);
9384 	}
9385 	
9386 	/** creates and captures a set partitioning constraint with all constraint flags set
9387 	 *  to their default values
9388 	 *
9389 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9390 	 */
9391 	SCIP_RETCODE SCIPcreateConsBasicSetpart(
9392 	   SCIP*                 scip,               /**< SCIP data structure */
9393 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
9394 	   const char*           name,               /**< name of constraint */
9395 	   int                   nvars,              /**< number of variables in the constraint */
9396 	   SCIP_VAR**            vars                /**< array with variables of constraint entries */
9397 	   )
9398 	{
9399 	   SCIP_CALL( SCIPcreateConsSetpart(scip, cons, name, nvars, vars,
9400 	         TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
9401 	
9402 	   return SCIP_OKAY;
9403 	}
9404 	
9405 	/** creates and captures a set packing constraint
9406 	 *
9407 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9408 	 */
9409 	SCIP_RETCODE SCIPcreateConsSetpack(
9410 	   SCIP*                 scip,               /**< SCIP data structure */
9411 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
9412 	   const char*           name,               /**< name of constraint */
9413 	   int                   nvars,              /**< number of variables in the constraint */
9414 	   SCIP_VAR**            vars,               /**< array with variables of constraint entries */
9415 	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
9416 	                                              *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
9417 	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
9418 	                                              *   Usually set to TRUE. */
9419 	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
9420 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
9421 	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
9422 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
9423 	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
9424 	                                              *   Usually set to TRUE. */
9425 	   SCIP_Bool             local,              /**< is constraint only valid locally?
9426 	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
9427 	   SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)?
9428 	                                              *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
9429 	                                              *   adds coefficients to this constraint. */
9430 	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
9431 	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
9432 	                                              *   are separated as constraints. */
9433 	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
9434 	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
9435 	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
9436 	                                              *   if it may be moved to a more global node?
9437 	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
9438 	   )
9439 	{
9440 	   return createConsSetppc(scip, cons, name, nvars, vars, SCIP_SETPPCTYPE_PACKING,
9441 	      initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode);
9442 	}
9443 	
9444 	/** creates and captures a set packing constraint with all constraint flags set
9445 	 *  to their default values
9446 	 *
9447 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9448 	 */
9449 	SCIP_RETCODE SCIPcreateConsBasicSetpack(
9450 	   SCIP*                 scip,               /**< SCIP data structure */
9451 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
9452 	   const char*           name,               /**< name of constraint */
9453 	   int                   nvars,              /**< number of variables in the constraint */
9454 	   SCIP_VAR**            vars                /**< array with variables of constraint entries */
9455 	   )
9456 	{
9457 	   SCIP_CALL( SCIPcreateConsSetpack(scip, cons, name, nvars, vars,
9458 	         TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
9459 	
9460 	   return SCIP_OKAY;
9461 	}
9462 	
9463 	/** creates and captures a set covering constraint
9464 	 *
9465 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9466 	 */
9467 	SCIP_RETCODE SCIPcreateConsSetcover(
9468 	   SCIP*                 scip,               /**< SCIP data structure */
9469 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
9470 	   const char*           name,               /**< name of constraint */
9471 	   int                   nvars,              /**< number of variables in the constraint */
9472 	   SCIP_VAR**            vars,               /**< array with variables of constraint entries */
9473 	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
9474 	                                              *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
9475 	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
9476 	                                              *   Usually set to TRUE. */
9477 	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
9478 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
9479 	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
9480 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
9481 	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
9482 	                                              *   Usually set to TRUE. */
9483 	   SCIP_Bool             local,              /**< is constraint only valid locally?
9484 	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
9485 	   SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)?
9486 	                                              *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
9487 	                                              *   adds coefficients to this constraint. */
9488 	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
9489 	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
9490 	                                              *   are separated as constraints. */
9491 	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
9492 	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
9493 	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
9494 	                                              *   if it may be moved to a more global node?
9495 	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
9496 	   )
9497 	{
9498 	   return createConsSetppc(scip, cons, name, nvars, vars, SCIP_SETPPCTYPE_COVERING,
9499 	      initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode);
9500 	}
9501 	
9502 	/** creates and captures a set covering constraint with all constraint flags set
9503 	 *  to their default values
9504 	 *
9505 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
9506 	 */
9507 	SCIP_RETCODE SCIPcreateConsBasicSetcover(
9508 	   SCIP*                 scip,               /**< SCIP data structure */
9509 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
9510 	   const char*           name,               /**< name of constraint */
9511 	   int                   nvars,              /**< number of variables in the constraint */
9512 	   SCIP_VAR**            vars                /**< array with variables of constraint entries */
9513 	   )
9514 	{
9515 	   SCIP_CALL( SCIPcreateConsSetcover(scip, cons, name, nvars, vars,
9516 	         TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
9517 	
9518 	   return SCIP_OKAY;
9519 	}
9520 	
9521 	/** adds coefficient in set partitioning / packing / covering constraint */
9522 	SCIP_RETCODE SCIPaddCoefSetppc(
9523 	   SCIP*                 scip,               /**< SCIP data structure */
9524 	   SCIP_CONS*            cons,               /**< constraint data */
9525 	   SCIP_VAR*             var                 /**< variable to add to the constraint */
9526 	   )
9527 	{
9528 	   assert(var != NULL);
9529 	
9530 	   /*debugMsg(scip, "adding variable <%s> to setppc constraint <%s>\n",
9531 	     SCIPvarGetName(var), SCIPconsGetName(cons));*/
9532 	
9533 	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9534 	   {
9535 	      SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9536 	      return SCIP_INVALIDDATA;
9537 	   }
9538 	
9539 	   SCIP_CALL( addCoef(scip, cons, var) );
9540 	
9541 	   return SCIP_OKAY;
9542 	}
9543 	
9544 	/** gets number of variables in set partitioning / packing / covering constraint */
9545 	int SCIPgetNVarsSetppc(
9546 	   SCIP*                 scip,               /**< SCIP data structure */
9547 	   SCIP_CONS*            cons                /**< constraint data */
9548 	   )
9549 	{
9550 	   SCIP_CONSDATA* consdata;
9551 	
9552 	   assert(scip != NULL);
9553 	
9554 	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9555 	   {
9556 	      SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9557 	      SCIPABORT();
9558 	      return -1;  /*lint !e527*/
9559 	   }
9560 	
9561 	   consdata = SCIPconsGetData(cons);
9562 	   assert(consdata != NULL);
9563 	
9564 	   return consdata->nvars;
9565 	}
9566 	
9567 	/** gets array of variables in set partitioning / packing / covering constraint */
9568 	SCIP_VAR** SCIPgetVarsSetppc(
9569 	   SCIP*                 scip,               /**< SCIP data structure */
9570 	   SCIP_CONS*            cons                /**< constraint data */
9571 	   )
9572 	{
9573 	   SCIP_CONSDATA* consdata;
9574 	
9575 	   assert(scip != NULL);
9576 	
9577 	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9578 	   {
9579 	      SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9580 	      SCIPABORT();
9581 	      return NULL;  /*lint !e527*/
9582 	   }
9583 	
9584 	   consdata = SCIPconsGetData(cons);
9585 	   assert(consdata != NULL);
9586 	
9587 	   return consdata->vars;
9588 	}
9589 	
9590 	/** gets type of set partitioning / packing / covering constraint */
9591 	SCIP_SETPPCTYPE SCIPgetTypeSetppc(
9592 	   SCIP*                 scip,               /**< SCIP data structure */
9593 	   SCIP_CONS*            cons                /**< constraint data */
9594 	   )
9595 	{
9596 	   SCIP_CONSDATA* consdata;
9597 	
9598 	   assert(scip != NULL);
9599 	
9600 	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9601 	   {
9602 	      SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9603 	      SCIPABORT();
9604 	   }
9605 	
9606 	   consdata = SCIPconsGetData(cons);
9607 	   assert(consdata != NULL);
9608 	
9609 	   return (SCIP_SETPPCTYPE)(consdata->setppctype);
9610 	}
9611 	
9612 	/** gets the dual solution of the set partitioning / packing / covering constraint in the current LP */
9613 	SCIP_Real SCIPgetDualsolSetppc(
9614 	   SCIP*                 scip,               /**< SCIP data structure */
9615 	   SCIP_CONS*            cons                /**< constraint data */
9616 	   )
9617 	{
9618 	   SCIP_CONSDATA* consdata;
9619 	
9620 	   assert(scip != NULL);
9621 	
9622 	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9623 	   {
9624 	      SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9625 	      SCIPABORT();
9626 	      return SCIP_INVALID;  /*lint !e527*/
9627 	   }
9628 	
9629 	   consdata = SCIPconsGetData(cons);
9630 	   assert(consdata != NULL);
9631 	
9632 	   if( consdata->row != NULL )
9633 	      return SCIProwGetDualsol(consdata->row);
9634 	   else
9635 	      return 0.0;
9636 	}
9637 	
9638 	/** gets the dual Farkas value of the set partitioning / packing / covering constraint in the current infeasible LP */
9639 	SCIP_Real SCIPgetDualfarkasSetppc(
9640 	   SCIP*                 scip,               /**< SCIP data structure */
9641 	   SCIP_CONS*            cons                /**< constraint data */
9642 	   )
9643 	{
9644 	   SCIP_CONSDATA* consdata;
9645 	
9646 	   assert(scip != NULL);
9647 	
9648 	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9649 	   {
9650 	      SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9651 	      SCIPABORT();
9652 	      return SCIP_INVALID;  /*lint !e527*/
9653 	   }
9654 	
9655 	   consdata = SCIPconsGetData(cons);
9656 	   assert(consdata != NULL);
9657 	
9658 	   if( consdata->row != NULL )
9659 	      return SCIProwGetDualfarkas(consdata->row);
9660 	   else
9661 	      return 0.0;
9662 	}
9663 	
9664 	/** returns the linear relaxation of the given set partitioning / packing / covering constraint; may return NULL if no
9665 	 *  LP row was yet created; the user must not modify the row!
9666 	 */
9667 	SCIP_ROW* SCIPgetRowSetppc(
9668 	   SCIP*                 scip,               /**< SCIP data structure */
9669 	   SCIP_CONS*            cons                /**< constraint data */
9670 	   )
9671 	{
9672 	   SCIP_CONSDATA* consdata;
9673 	
9674 	   assert(scip != NULL);
9675 	
9676 	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9677 	   {
9678 	      SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9679 	      SCIPABORT();
9680 	      return NULL;  /*lint !e527*/
9681 	   }
9682 	
9683 	   consdata = SCIPconsGetData(cons);
9684 	   assert(consdata != NULL);
9685 	
9686 	   return consdata->row;
9687 	}
9688 	
9689 	/** returns current number of variables fixed to one in the constraint  */
9690 	int SCIPgetNFixedonesSetppc(
9691 	   SCIP*                 scip,               /**< SCIP data structure */
9692 	   SCIP_CONS*            cons                /**< constraint data */
9693 	   )
9694 	{
9695 	   SCIP_CONSDATA* consdata;
9696 	
9697 	   assert(scip != NULL);
9698 	
9699 	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9700 	   {
9701 	      SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9702 	      SCIPABORT();
9703 	      return -1;  /*lint !e527*/
9704 	   }
9705 	
9706 	   consdata = SCIPconsGetData(cons);
9707 	   assert(consdata != NULL);
9708 	
9709 	   return consdata->nfixedones;
9710 	}
9711 	
9712 	
9713 	/** returns current number of variables fixed to zero in the constraint  */
9714 	int SCIPgetNFixedzerosSetppc(
9715 	   SCIP*                 scip,               /**< SCIP data structure */
9716 	   SCIP_CONS*            cons                /**< constraint data */
9717 	   )
9718 	{
9719 	   SCIP_CONSDATA* consdata;
9720 	
9721 	   assert(scip != NULL);
9722 	
9723 	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
9724 	   {
9725 	      SCIPerrorMessage("constraint is not a set partitioning / packing / covering constraint\n");
9726 	      SCIPABORT();
9727 	      return -1;  /*lint !e527*/
9728 	   }
9729 	
9730 	   consdata = SCIPconsGetData(cons);
9731 	   assert(consdata != NULL);
9732 	
9733 	   return consdata->nfixedzeros;
9734 	}
9735 	
9736 	/** cleans up (multi-)aggregations and fixings from setppc constraints */
9737 	SCIP_RETCODE SCIPcleanupConssSetppc(
9738 	   SCIP*                 scip,               /**< SCIP data structure */
9739 	   SCIP_Bool             onlychecked,        /**< should only checked constraints be cleaned up? */
9740 	   SCIP_Bool*            infeasible,         /**< pointer to return whether problem was detected to be infeasible */
9741 	   int*                  naddconss,          /**< pointer to count number of added (linear) constraints */
9742 	   int*                  ndelconss,          /**< pointer to count number of deleted (setppc) constraints */
9743 	   int*                  nchgcoefs,          /**< pointer to count number of changed coefficients */
9744 	   int*                  nfixedvars          /**< pointer to count number of fixed variables */
9745 	   )
9746 	{
9747 	   SCIP_CONSHDLR* conshdlr;
9748 	   SCIP_CONS** conss;
9749 	   int nconss;
9750 	   int i;
9751 	
9752 	   conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
9753 	   if( conshdlr == NULL )
9754 	      return SCIP_OKAY;
9755 	
9756 	   assert(naddconss != NULL);
9757 	   assert(ndelconss != NULL);
9758 	   assert(nfixedvars != NULL);
9759 	   assert(infeasible != NULL);
9760 	   *infeasible = FALSE;
9761 	
9762 	   nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
9763 	   conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
9764 	
9765 	   /* loop backwards since then deleted constraints do not interfere with the loop */
9766 	   for( i = nconss - 1; i > 0; --i )
9767 	   {
9768 	      SCIP_CONS* cons = conss[i];
9769 	
9770 	      SCIP_CALL( applyFixings(scip, cons, naddconss, ndelconss, nfixedvars, infeasible) );
9771 	
9772 	      if( *infeasible )
9773 	         break;
9774 	
9775 	      if( SCIPconsIsDeleted(cons) )
9776 	         continue;
9777 	
9778 	      /* merging unmerged constraints */
9779 	      SCIP_CALL( mergeMultiples(scip, cons, nfixedvars, ndelconss, nchgcoefs, infeasible) );
9780 	
9781 	      if( *infeasible )
9782 	         break;
9783 	   }
9784 	
9785 	   return SCIP_OKAY;
9786 	}
9787