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_knapsack.c
26   	 * @ingroup DEFPLUGINS_CONS
27   	 * @brief  Constraint handler for knapsack constraints of the form  \f$a^T x \le b\f$, x binary and \f$a \ge 0\f$.
28   	 * @author Tobias Achterberg
29   	 * @author Xin Liu
30   	 * @author Kati Wolter
31   	 * @author Michael Winkler
32   	 * @author Tobias Fischer
33   	 */
34   	
35   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36   	
37   	#include "blockmemshell/memory.h"
38   	#include "scip/cons_knapsack.h"
39   	#include "scip/cons_linear.h"
40   	#include "scip/cons_logicor.h"
41   	#include "scip/cons_setppc.h"
42   	#include "scip/pub_cons.h"
43   	#include "scip/pub_event.h"
44   	#include "scip/pub_implics.h"
45   	#include "scip/pub_lp.h"
46   	#include "scip/pub_message.h"
47   	#include "scip/pub_misc.h"
48   	#include "scip/pub_misc_select.h"
49   	#include "scip/pub_misc_sort.h"
50   	#include "scip/pub_sepa.h"
51   	#include "scip/pub_var.h"
52   	#include "scip/scip_branch.h"
53   	#include "scip/scip_conflict.h"
54   	#include "scip/scip_cons.h"
55   	#include "scip/scip_copy.h"
56   	#include "scip/scip_cut.h"
57   	#include "scip/scip_event.h"
58   	#include "scip/scip_general.h"
59   	#include "scip/scip_lp.h"
60   	#include "scip/scip_mem.h"
61   	#include "scip/scip_message.h"
62   	#include "scip/scip_nlp.h"
63   	#include "scip/scip_numerics.h"
64   	#include "scip/scip_param.h"
65   	#include "scip/scip_prob.h"
66   	#include "scip/scip_probing.h"
67   	#include "scip/scip_sol.h"
68   	#include "scip/scip_solvingstats.h"
69   	#include "scip/scip_tree.h"
70   	#include "scip/scip_var.h"
71   	#include "scip/symmetry_graph.h"
72   	#include "symmetry/struct_symmetry.h"
73   	#include <ctype.h>
74   	#include <string.h>
75   	
76   	#ifdef WITH_CARDINALITY_UPGRADE
77   	#include "scip/cons_cardinality.h"
78   	#endif
79   	
80   	/* constraint handler properties */
81   	#define CONSHDLR_NAME          "knapsack"
82   	#define CONSHDLR_DESC          "knapsack constraint of the form  a^T x <= b, x binary and a >= 0"
83   	#define CONSHDLR_SEPAPRIORITY   +600000 /**< priority of the constraint handler for separation */
84   	#define CONSHDLR_ENFOPRIORITY   -600000 /**< priority of the constraint handler for constraint enforcing */
85   	#define CONSHDLR_CHECKPRIORITY  -600000 /**< priority of the constraint handler for checking feasibility */
86   	#define CONSHDLR_SEPAFREQ             0 /**< frequency for separating cuts; zero means to separate only in the root node */
87   	#define CONSHDLR_PROPFREQ             1 /**< frequency for propagating domains; zero means only preprocessing propagation */
88   	#define CONSHDLR_EAGERFREQ          100 /**< frequency for using all instead of only the useful constraints in separation,
89   	                                         *   propagation and enforcement, -1 for no eager evaluations, 0 for first only */
90   	#define CONSHDLR_MAXPREROUNDS        -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
91   	#define CONSHDLR_DELAYSEPA        FALSE /**< should separation method be delayed, if other separators found cuts? */
92   	#define CONSHDLR_DELAYPROP        FALSE /**< should propagation method be delayed, if other propagators found reductions? */
93   	#define CONSHDLR_NEEDSCONS         TRUE /**< should the constraint handler be skipped, if no constraints are available? */
94   	
95   	#define CONSHDLR_PRESOLTIMING            SCIP_PRESOLTIMING_ALWAYS
96   	#define CONSHDLR_PROP_TIMING             SCIP_PROPTIMING_BEFORELP
97   	
98   	#define EVENTHDLR_NAME         "knapsack"
99   	#define EVENTHDLR_DESC         "bound change event handler for knapsack constraints"
100  	#define EVENTTYPE_KNAPSACK SCIP_EVENTTYPE_LBCHANGED \
101  	                         | SCIP_EVENTTYPE_UBTIGHTENED \
102  	                         | SCIP_EVENTTYPE_VARFIXED \
103  	                         | SCIP_EVENTTYPE_VARDELETED \
104  	                         | SCIP_EVENTTYPE_IMPLADDED /**< variable events that should be caught by the event handler */
105  	
106  	#define LINCONSUPGD_PRIORITY    +100000 /**< priority of the constraint handler for upgrading of linear constraints */
107  	
108  	#define MAX_USECLIQUES_SIZE        1000 /**< maximal number of items in knapsack where clique information is used */
109  	#define MAX_ZEROITEMS_SIZE        10000 /**< maximal number of items to store in the zero list in preprocessing */
110  	
111  	#define KNAPSACKRELAX_MAXDELTA        0.1 /**< maximal allowed rounding distance for scaling in knapsack relaxation */
112  	#define KNAPSACKRELAX_MAXDNOM      1000LL /**< maximal allowed denominator in knapsack rational relaxation */
113  	#define KNAPSACKRELAX_MAXSCALE     1000.0 /**< maximal allowed scaling factor in knapsack rational relaxation */
114  	
115  	#define DEFAULT_SEPACARDFREQ          1 /**< multiplier on separation frequency, how often knapsack cuts are separated */
116  	#define DEFAULT_MAXROUNDS             5 /**< maximal number of separation rounds per node (-1: unlimited) */
117  	#define DEFAULT_MAXROUNDSROOT        -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
118  	#define DEFAULT_MAXSEPACUTS          50 /**< maximal number of cuts separated per separation round */
119  	#define DEFAULT_MAXSEPACUTSROOT     200 /**< maximal number of cuts separated per separation round in the root node */
120  	#define DEFAULT_MAXCARDBOUNDDIST    0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
121  	                                         *   to best node's dual bound for separating knapsack cuts */
122  	#define DEFAULT_DISAGGREGATION     TRUE /**< should disaggregation of knapsack constraints be allowed in preprocessing? */
123  	#define DEFAULT_SIMPLIFYINEQUALITIES TRUE/**< should presolving try to simplify knapsacks */
124  	#define DEFAULT_NEGATEDCLIQUE      TRUE /**< should negated clique information be used in solving process */
125  	
126  	#define MAXABSVBCOEF               1e+5 /**< maximal absolute coefficient in variable bounds used for knapsack relaxation */
127  	#define USESUPADDLIFT             FALSE /**< should lifted minimal cover inequalities using superadditive up-lifting be separated in addition */
128  	
129  	#define DEFAULT_PRESOLUSEHASHING   TRUE /**< should hash table be used for detecting redundant constraints in advance */
130  	#define HASHSIZE_KNAPSACKCONS       500 /**< minimal size of hash table in linear constraint tables */
131  	
132  	#define DEFAULT_PRESOLPAIRWISE     TRUE /**< should pairwise constraint comparison be performed in presolving? */
133  	#define NMINCOMPARISONS          200000 /**< number for minimal pairwise presolving comparisons */
134  	#define MINGAINPERNMINCOMPARISONS 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
135  	                                         *   comparison round */
136  	#define DEFAULT_DUALPRESOLVING     TRUE /**< should dual presolving steps be performed? */
137  	#define DEFAULT_DETECTCUTOFFBOUND  TRUE /**< should presolving try to detect constraints parallel to the objective
138  	                                         *   function defining an upper bound and prevent these constraints from
139  	                                         *   entering the LP */
140  	#define DEFAULT_DETECTLOWERBOUND TRUE   /**< should presolving try to detect constraints parallel to the objective
141  	                                         *   function defining a lower bound and prevent these constraints from
142  	                                         *   entering the LP */
143  	#define DEFAULT_CLIQUEEXTRACTFACTOR 0.5 /**< lower clique size limit for greedy clique extraction algorithm (relative to largest clique) */
144  	#define MAXCOVERSIZEITERLEWI       1000 /**< maximal size for which LEWI are iteratively separated by reducing the feasible set */
145  	
146  	#define DEFAULT_USEGUBS           FALSE /**< should GUB information be used for separation? */
147  	#define GUBCONSGROWVALUE              6 /**< memory growing value for GUB constraint array */
148  	#define GUBSPLITGNC1GUBS          FALSE /**< should GNC1 GUB conss without F vars be split into GOC1 and GR GUB conss? */
149  	#define DEFAULT_CLQPARTUPDATEFAC   1.5  /**< factor on the growth of global cliques to decide when to update a previous
150  	                                         *   (negated) clique partition (used only if updatecliquepartitions is set to TRUE) */
151  	#define DEFAULT_UPDATECLIQUEPARTITIONS FALSE /**< should clique partition information be updated when old partition seems outdated? */
152  	#define MAXNCLIQUEVARSCOMP 1000000      /**< limit on number of pairwise comparisons in clique partitioning algorithm */
153  	#ifdef WITH_CARDINALITY_UPGRADE
154  	#define DEFAULT_UPGDCARDINALITY   FALSE /**< if TRUE then try to update knapsack constraints to cardinality constraints */
155  	#endif
156  	
157  	/* @todo maybe use event SCIP_EVENTTYPE_VARUNLOCKED to decide for another dual-presolving run on a constraint */
158  	
159  	/*
160  	 * Data structures
161  	 */
162  	
163  	/** constraint handler data */
164  	struct SCIP_ConshdlrData
165  	{
166  	   int*                  ints1;              /**< cleared memory array, all entries are set to zero in initpre, if you use this
167  	                                              *   you have to clear it at the end, exists only in presolving stage */
168  	   int*                  ints2;              /**< cleared memory array, all entries are set to zero in initpre, if you use this
169  	                                              *   you have to clear it at the end, exists only in presolving stage */
170  	   SCIP_Longint*         longints1;          /**< cleared memory array, all entries are set to zero in initpre, if you use this
171  	                                              *   you have to clear it at the end, exists only in presolving stage */
172  	   SCIP_Longint*         longints2;          /**< cleared memory array, all entries are set to zero in initpre, if you use this
173  	                                              *   you have to clear it at the end, exists only in presolving stage */
174  	   SCIP_Bool*            bools1;             /**< cleared memory array, all entries are set to zero in initpre, if you use this
175  	                                              *   you have to clear it at the end, exists only in presolving stage */
176  	   SCIP_Bool*            bools2;             /**< cleared memory array, all entries are set to zero in initpre, if you use this
177  	                                              *   you have to clear it at the end, exists only in presolving stage */
178  	   SCIP_Bool*            bools3;             /**< cleared memory array, all entries are set to zero in initpre, if you use this
179  	                                              *   you have to clear it at the end, exists only in presolving stage */
180  	   SCIP_Bool*            bools4;             /**< cleared memory array, all entries are set to zero in initpre, if you use this
181  	                                              *   you have to clear it at the end, exists only in presolving stage */
182  	   SCIP_Real*            reals1;             /**< cleared memory array, all entries are set to zero in consinit, if you use this
183  	                                              *   you have to clear it at the end */
184  	   int                   ints1size;          /**< size of ints1 array */
185  	   int                   ints2size;          /**< size of ints2 array */
186  	   int                   longints1size;      /**< size of longints1 array */
187  	   int                   longints2size;      /**< size of longints2 array */
188  	   int                   bools1size;         /**< size of bools1 array */
189  	   int                   bools2size;         /**< size of bools2 array */
190  	   int                   bools3size;         /**< size of bools3 array */
191  	   int                   bools4size;         /**< size of bools4 array */
192  	   int                   reals1size;         /**< size of reals1 array */
193  	   SCIP_EVENTHDLR*       eventhdlr;          /**< event handler for bound change events */
194  	   SCIP_Real             maxcardbounddist;   /**< maximal relative distance from current node's dual bound to primal bound compared
195  	                                              *   to best node's dual bound for separating knapsack cuts */
196  	   int                   sepacardfreq;       /**< multiplier on separation frequency, how often knapsack cuts are separated */
197  	   int                   maxrounds;          /**< maximal number of separation rounds per node (-1: unlimited) */
198  	   int                   maxroundsroot;      /**< maximal number of separation rounds in the root node (-1: unlimited) */
199  	   int                   maxsepacuts;        /**< maximal number of cuts separated per separation round */
200  	   int                   maxsepacutsroot;    /**< maximal number of cuts separated per separation round in the root node */
201  	   SCIP_Bool             disaggregation;     /**< should disaggregation of knapsack constraints be allowed in preprocessing? */
202  	   SCIP_Bool             simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
203  	   SCIP_Bool             negatedclique;      /**< should negated clique information be used in solving process */
204  	   SCIP_Bool             presolpairwise;     /**< should pairwise constraint comparison be performed in presolving? */
205  	   SCIP_Bool             presolusehashing;   /**< should hash table be used for detecting redundant constraints in advance */
206  	   SCIP_Bool             dualpresolving;     /**< should dual presolving steps be performed? */
207  	   SCIP_Bool             usegubs;            /**< should GUB information be used for separation? */
208  	   SCIP_Bool             detectcutoffbound;  /**< should presolving try to detect constraints parallel to the objective
209  	                                              *   function defining an upper bound and prevent these constraints from
210  	                                              *   entering the LP */
211  	   SCIP_Bool             detectlowerbound;   /**< should presolving try to detect constraints parallel to the objective
212  	                                              *   function defining a lower bound and prevent these constraints from
213  	                                              *   entering the LP */
214  	   SCIP_Bool             updatecliquepartitions; /**< should clique partition information be updated when old partition seems outdated? */
215  	   SCIP_Real             cliqueextractfactor;/**< lower clique size limit for greedy clique extraction algorithm (relative to largest clique) */
216  	   SCIP_Real             clqpartupdatefac;   /**< factor on the growth of global cliques to decide when to update a previous
217  	                                              *   (negated) clique partition (used only if updatecliquepartitions is set to TRUE) */
218  	#ifdef WITH_CARDINALITY_UPGRADE
219  	   SCIP_Bool             upgdcardinality;    /**< if TRUE then try to update knapsack constraints to cardinality constraints */
220  	   SCIP_Bool             upgradedcard;       /**< whether we have already upgraded knapsack constraints to cardinality constraints */
221  	#endif
222  	};
223  	
224  	
225  	/** constraint data for knapsack constraints */
226  	struct SCIP_ConsData
227  	{
228  	   SCIP_VAR**            vars;               /**< variables in knapsack constraint */
229  	   SCIP_Longint*         weights;            /**< weights of variables in knapsack constraint */
230  	   SCIP_EVENTDATA**      eventdata;          /**< event data for bound change events of the variables */
231  	   int*                  cliquepartition;    /**< clique indices of the clique partition */
232  	   int*                  negcliquepartition; /**< clique indices of the negated clique partition */
233  	   SCIP_ROW*             row;                /**< corresponding LP row */
234  	   SCIP_NLROW*           nlrow;              /**< corresponding NLP row */
235  	   int                   nvars;              /**< number of variables in knapsack constraint */
236  	   int                   varssize;           /**< size of vars, weights, and eventdata arrays */
237  	   int                   ncliques;           /**< number of cliques in the clique partition */
238  	   int                   nnegcliques;        /**< number of cliques in the negated clique partition */
239  	   int                   ncliqueslastnegpart;/**< number of global cliques the last time a negated clique partition was computed */
240  	   int                   ncliqueslastpart;   /**< number of global cliques the last time a clique partition was computed */
241  	   SCIP_Longint          capacity;           /**< capacity of knapsack */
242  	   SCIP_Longint          weightsum;          /**< sum of all weights */
243  	   SCIP_Longint          onesweightsum;      /**< sum of weights of variables fixed to one */
244  	   unsigned int          presolvedtiming:5;  /**< max level in which the knapsack constraint is already presolved */
245  	   unsigned int          sorted:1;           /**< are the knapsack items sorted by weight? */
246  	   unsigned int          cliquepartitioned:1;/**< is the clique partition valid? */
247  	   unsigned int          negcliquepartitioned:1;/**< is the negated clique partition valid? */
248  	   unsigned int          merged:1;           /**< are the constraint's equal variables already merged? */
249  	   unsigned int          cliquesadded:1;     /**< were the cliques of the knapsack already added to clique table? */
250  	   unsigned int          varsdeleted:1;      /**< were variables deleted after last cleanup? */
251  	   unsigned int          existmultaggr:1;    /**< does this constraint contain multi-aggregations */
252  	};
253  	
254  	/** event data for bound changes events */
255  	struct SCIP_EventData
256  	{
257  	   SCIP_CONS*            cons;               /**< knapsack constraint to process the bound change for */
258  	   SCIP_Longint          weight;             /**< weight of variable */
259  	   int                   filterpos;          /**< position of event in variable's event filter */
260  	};
261  	
262  	
263  	/** data structure to combine two sorting key values */
264  	struct sortkeypair
265  	{
266  	   SCIP_Real             key1;               /**< first sort key value */
267  	   SCIP_Real             key2;               /**< second sort key value */
268  	};
269  	typedef struct sortkeypair SORTKEYPAIR;
270  	
271  	/** status of GUB constraint */
272  	enum GUBVarstatus
273  	{
274  	   GUBVARSTATUS_UNINITIAL        = -1,       /** unintitialized variable status */
275  	   GUBVARSTATUS_CAPACITYEXCEEDED =  0,       /** variable with weight exceeding the knapsack capacity */
276  	   GUBVARSTATUS_BELONGSTOSET_R   =  1,       /** variable in noncovervars R */
277  	   GUBVARSTATUS_BELONGSTOSET_F   =  2,       /** variable in noncovervars F */
278  	   GUBVARSTATUS_BELONGSTOSET_C2  =  3,       /** variable in covervars C2 */
279  	   GUBVARSTATUS_BELONGSTOSET_C1  =  4        /** variable in covervars C1 */
280  	};
281  	typedef enum GUBVarstatus GUBVARSTATUS;
282  	
283  	/** status of variable in GUB constraint */
284  	enum GUBConsstatus
285  	{
286  	   GUBCONSSTATUS_UNINITIAL         = -1,     /** unintitialized GUB constraint status */
287  	   GUBCONSSTATUS_BELONGSTOSET_GR   =  0,     /** all GUB variables are in noncovervars R */
288  	   GUBCONSSTATUS_BELONGSTOSET_GF   =  1,     /** all GUB variables are in noncovervars F (and noncovervars R) */
289  	   GUBCONSSTATUS_BELONGSTOSET_GC2  =  2,     /** all GUB variables are in covervars C2 */
290  	   GUBCONSSTATUS_BELONGSTOSET_GNC1 =  3,     /** some GUB variables are in covervars C1, others in noncovervars R or F */
291  	   GUBCONSSTATUS_BELONGSTOSET_GOC1 =  4      /** all GUB variables are in covervars C1 */
292  	};
293  	typedef enum GUBConsstatus GUBCONSSTATUS;
294  	
295  	/** data structure of GUB constraints */
296  	struct SCIP_GUBCons
297  	{
298  	   int*                  gubvars;            /**< indices of GUB variables in knapsack constraint */
299  	   GUBVARSTATUS*         gubvarsstatus;      /**< status of GUB variables */
300  	   int                   ngubvars;           /**< number of GUB variables */
301  	   int                   gubvarssize;        /**< size of gubvars array */
302  	};
303  	typedef struct SCIP_GUBCons SCIP_GUBCONS;
304  	
305  	/** data structure of a set of GUB constraints */
306  	struct SCIP_GUBSet
307  	{
308  	   SCIP_GUBCONS**        gubconss;           /**< GUB constraints in GUB set */
309  	   GUBCONSSTATUS*        gubconsstatus;      /**< status of GUB constraints */
310  	   int                   ngubconss;          /**< number of GUB constraints */
311  	   int                   nvars;              /**< number of variables in knapsack constraint */
312  	   int*                  gubconssidx;        /**< index of GUB constraint (in gubconss array) of each knapsack variable */
313  	   int*                  gubvarsidx;         /**< index in GUB constraint (in gubvars array) of each knapsack variable  */
314  	};
315  	typedef struct SCIP_GUBSet SCIP_GUBSET;
316  	
317  	/*
318  	 * Local methods
319  	 */
320  	
321  	/** comparison method for two sorting key pairs */
322  	static
323  	SCIP_DECL_SORTPTRCOMP(compSortkeypairs)
324  	{
325  	   SORTKEYPAIR* sortkeypair1 = (SORTKEYPAIR*)elem1;
326  	   SORTKEYPAIR* sortkeypair2 = (SORTKEYPAIR*)elem2;
327  	
328  	   if( sortkeypair1->key1 < sortkeypair2->key1 )
329  	      return -1;
330  	   else if( sortkeypair1->key1 > sortkeypair2->key1 )
331  	      return +1;
332  	   else if( sortkeypair1->key2 < sortkeypair2->key2 )
333  	      return -1;
334  	   else if( sortkeypair1->key2 > sortkeypair2->key2 )
335  	      return +1;
336  	   else
337  	      return 0;
338  	}
339  	
340  	/** creates event data */
341  	static
342  	SCIP_RETCODE eventdataCreate(
343  	   SCIP*                 scip,               /**< SCIP data structure */
344  	   SCIP_EVENTDATA**      eventdata,          /**< pointer to store event data */
345  	   SCIP_CONS*            cons,               /**< constraint */
346  	   SCIP_Longint          weight              /**< weight of variable */
347  	   )
348  	{
349  	   assert(eventdata != NULL);
350  	
351  	   SCIP_CALL( SCIPallocBlockMemory(scip, eventdata) );
352  	   (*eventdata)->cons = cons;
353  	   (*eventdata)->weight = weight;
354  	
355  	   return SCIP_OKAY;
356  	}
357  	
358  	/** frees event data */
359  	static
360  	SCIP_RETCODE eventdataFree(
361  	   SCIP*                 scip,               /**< SCIP data structure */
362  	   SCIP_EVENTDATA**      eventdata           /**< pointer to event data */
363  	   )
364  	{
365  	   assert(eventdata != NULL);
366  	
367  	   SCIPfreeBlockMemory(scip, eventdata);
368  	
369  	   return SCIP_OKAY;
370  	}
371  	
372  	/** sorts items in knapsack with nonincreasing weights */
373  	static
374  	void sortItems(
375  	   SCIP_CONSDATA*        consdata            /**< constraint data */
376  	   )
377  	{
378  	   assert(consdata != NULL);
379  	   assert(consdata->nvars == 0 || consdata->vars != NULL);
380  	   assert(consdata->nvars == 0 || consdata->weights != NULL);
381  	   assert(consdata->nvars == 0 || consdata->eventdata != NULL);
382  	   assert(consdata->nvars == 0 || (consdata->cliquepartition != NULL && consdata->negcliquepartition != NULL));
383  	
384  	   if( !consdata->sorted )
385  	   {
386  	      int pos;
387  	      int lastcliquenum;
388  	      int v;
389  	
390  	      /* sort of five joint arrays of Long/pointer/pointer/ints/ints,
391  	       * sorted by first array in non-increasing order via sort template */
392  	      SCIPsortDownLongPtrPtrIntInt(
393  	         consdata->weights,
394  	         (void**)consdata->vars,
395  	         (void**)consdata->eventdata,
396  	         consdata->cliquepartition,
397  	         consdata->negcliquepartition,
398  	         consdata->nvars);
399  	
400  	      v = consdata->nvars - 1;
401  	      /* sort all items with same weight according to their variable index, used for hash value for fast pairwise comparison of all constraints */
402  	      while( v >= 0 )
403  	      {
404  	         int w = v - 1;
405  	
406  	         while( w >= 0 && consdata->weights[v] == consdata->weights[w] )
407  	            --w;
408  	
409  	         if( v - w > 1 )
410  	         {
411  	            /* sort all corresponding parts of arrays for which the weights are equal by using the variable index */
412  	            SCIPsortPtrPtrIntInt(
413  	               (void**)(&(consdata->vars[w+1])),
414  	               (void**)(&(consdata->eventdata[w+1])),
415  	               &(consdata->cliquepartition[w+1]),
416  	               &(consdata->negcliquepartition[w+1]),
417  	               SCIPvarComp,
418  	               v - w);
419  	         }
420  	         v = w;
421  	      }
422  	
423  	      /* we need to make sure that our clique numbers of our normal clique will be in increasing order without gaps */
424  	      if( consdata->cliquepartitioned )
425  	      {
426  	         lastcliquenum = 0;
427  	
428  	         for( pos = 0; pos < consdata->nvars; ++pos )
429  	         {
430  	            /* if the clique number in the normal clique at position pos is greater than the last found clique number the
431  	             * partition is invalid */
432  	            if( consdata->cliquepartition[pos] > lastcliquenum )
433  	            {
434  	               consdata->cliquepartitioned = FALSE;
435  	               break;
436  	            }
437  	            else if( consdata->cliquepartition[pos] == lastcliquenum )
438  	               ++lastcliquenum;
439  	         }
440  	      }
441  	      /* we need to make sure that our clique numbers of our negated clique will be in increasing order without gaps */
442  	      if( consdata->negcliquepartitioned )
443  	      {
444  	         lastcliquenum = 0;
445  	
446  	         for( pos = 0; pos < consdata->nvars; ++pos )
447  	         {
448  	            /* if the clique number in the negated clique at position pos is greater than the last found clique number the
449  	             * partition is invalid */
450  	            if( consdata->negcliquepartition[pos] > lastcliquenum )
451  	            {
452  	               consdata->negcliquepartitioned = FALSE;
453  	               break;
454  	            }
455  	            else if( consdata->negcliquepartition[pos] == lastcliquenum )
456  	               ++lastcliquenum;
457  	         }
458  	      }
459  	
460  	      consdata->sorted = TRUE;
461  	   }
462  	#ifndef NDEBUG
463  	   {
464  	      /* check if the weight array is sorted in a non-increasing way */
465  	      int i;
466  	      for( i = 0; i < consdata->nvars-1; ++i )
467  	         assert(consdata->weights[i] >= consdata->weights[i+1]);
468  	   }
469  	#endif
470  	}
471  	
472  	/** calculates a partition of the variables into cliques */
473  	static
474  	SCIP_RETCODE calcCliquepartition(
475  	   SCIP*                 scip,               /**< SCIP data structure */
476  	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< knapsack constraint handler data */
477  	   SCIP_CONSDATA*        consdata,           /**< constraint data */
478  	   SCIP_Bool             normalclique,       /**< Should normal cliquepartition be created? */
479  	   SCIP_Bool             negatedclique       /**< Should negated cliquepartition be created? */
480  	   )
481  	{
482  	   SCIP_Bool ispartitionoutdated;
483  	   SCIP_Bool isnegpartitionoutdated;
484  	   assert(consdata != NULL);
485  	   assert(consdata->nvars == 0 || (consdata->cliquepartition != NULL && consdata->negcliquepartition != NULL));
486  	
487  	   /* rerun eventually if number of global cliques increased considerably since last partition */
488  	   ispartitionoutdated = (conshdlrdata->updatecliquepartitions && consdata->ncliques > 1
489  	         && SCIPgetNCliques(scip) >= (int)(conshdlrdata->clqpartupdatefac * consdata->ncliqueslastpart));
490  	
491  	   if( normalclique && ( !consdata->cliquepartitioned || ispartitionoutdated ) )
492  	   {
493  	      SCIP_CALL( SCIPcalcCliquePartition(scip, consdata->vars, consdata->nvars, consdata->cliquepartition, &consdata->ncliques) );
494  	      consdata->cliquepartitioned = TRUE;
495  	      consdata->ncliqueslastpart = SCIPgetNCliques(scip);
496  	   }
497  	
498  	   /* rerun eventually if number of global cliques increased considerably since last negated partition */
499  	   isnegpartitionoutdated = (conshdlrdata->updatecliquepartitions && consdata->nnegcliques > 1
500  	         && SCIPgetNCliques(scip) >= (int)(conshdlrdata->clqpartupdatefac * consdata->ncliqueslastnegpart));
501  	
502  	   if( negatedclique && (!consdata->negcliquepartitioned || isnegpartitionoutdated) )
503  	   {
504  	      SCIP_CALL( SCIPcalcNegatedCliquePartition(scip, consdata->vars, consdata->nvars, consdata->negcliquepartition, &consdata->nnegcliques) );
505  	      consdata->negcliquepartitioned = TRUE;
506  	      consdata->ncliqueslastnegpart = SCIPgetNCliques(scip);
507  	   }
508  	   assert(!consdata->cliquepartitioned || consdata->ncliques <= consdata->nvars);
509  	   assert(!consdata->negcliquepartitioned || consdata->nnegcliques <= consdata->nvars);
510  	
511  	   return SCIP_OKAY;
512  	}
513  	
514  	/** installs rounding locks for the given variable in the given knapsack constraint */
515  	static
516  	SCIP_RETCODE lockRounding(
517  	   SCIP*                 scip,               /**< SCIP data structure */
518  	   SCIP_CONS*            cons,               /**< knapsack constraint */
519  	   SCIP_VAR*             var                 /**< variable of constraint entry */
520  	   )
521  	{
522  	   SCIP_CALL( SCIPlockVarCons(scip, var, cons, FALSE, TRUE) );
523  	
524  	   return SCIP_OKAY;
525  	}
526  	
527  	/** removes rounding locks for the given variable in the given knapsack constraint */
528  	static
529  	SCIP_RETCODE unlockRounding(
530  	   SCIP*                 scip,               /**< SCIP data structure */
531  	   SCIP_CONS*            cons,               /**< knapsack constraint */
532  	   SCIP_VAR*             var                 /**< variable of constraint entry */
533  	   )
534  	{
535  	   SCIP_CALL( SCIPunlockVarCons(scip, var, cons, FALSE, TRUE) );
536  	
537  	   return SCIP_OKAY;
538  	}
539  	
540  	/** catches bound change events for variables in knapsack */
541  	static
542  	SCIP_RETCODE catchEvents(
543  	   SCIP*                 scip,               /**< SCIP data structure */
544  	   SCIP_CONS*            cons,               /**< constraint */
545  	   SCIP_CONSDATA*        consdata,           /**< constraint data */
546  	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler to call for the event processing */
547  	   )
548  	{
549  	   int i;
550  	
551  	   assert(cons != NULL);
552  	   assert(consdata != NULL);
553  	   assert(consdata->nvars == 0 || consdata->vars != NULL);
554  	   assert(consdata->nvars == 0 || consdata->weights != NULL);
555  	   assert(consdata->nvars == 0 || consdata->eventdata != NULL);
556  	
557  	   for( i = 0; i < consdata->nvars; i++)
558  	   {
559  	      SCIP_CALL( eventdataCreate(scip, &consdata->eventdata[i], cons, consdata->weights[i]) );
560  	      SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[i], EVENTTYPE_KNAPSACK,
561  	            eventhdlr, consdata->eventdata[i], &consdata->eventdata[i]->filterpos) );
562  	   }
563  	
564  	   return SCIP_OKAY;
565  	}
566  	
567  	/** drops bound change events for variables in knapsack */
568  	static
569  	SCIP_RETCODE dropEvents(
570  	   SCIP*                 scip,               /**< SCIP data structure */
571  	   SCIP_CONSDATA*        consdata,           /**< constraint data */
572  	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler to call for the event processing */
573  	   )
574  	{
575  	   int i;
576  	
577  	   assert(consdata != NULL);
578  	   assert(consdata->nvars == 0 || consdata->vars != NULL);
579  	   assert(consdata->nvars == 0 || consdata->weights != NULL);
580  	   assert(consdata->nvars == 0 || consdata->eventdata != NULL);
581  	
582  	   for( i = 0; i < consdata->nvars; i++)
583  	   {
584  	      SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[i], EVENTTYPE_KNAPSACK,
585  	            eventhdlr, consdata->eventdata[i], consdata->eventdata[i]->filterpos) );
586  	      SCIP_CALL( eventdataFree(scip, &consdata->eventdata[i]) );
587  	   }
588  	
589  	   return SCIP_OKAY;
590  	}
591  	
592  	/** ensures, that vars and vals arrays can store at least num entries */
593  	static
594  	SCIP_RETCODE consdataEnsureVarsSize(
595  	   SCIP*                 scip,               /**< SCIP data structure */
596  	   SCIP_CONSDATA*        consdata,           /**< knapsack constraint data */
597  	   int                   num,                /**< minimum number of entries to store */
598  	   SCIP_Bool             transformed         /**< is constraint from transformed problem? */
599  	   )
600  	{
601  	   assert(consdata != NULL);
602  	   assert(consdata->nvars <= consdata->varssize);
603  	
604  	   if( num > consdata->varssize )
605  	   {
606  	      int newsize;
607  	
608  	      newsize = SCIPcalcMemGrowSize(scip, num);
609  	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
610  	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->weights, consdata->varssize, newsize) );
611  	      if( transformed )
612  	      {
613  	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
614  	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->cliquepartition, consdata->varssize, newsize) );
615  	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->negcliquepartition, consdata->varssize, newsize) );
616  	      }
617  	      else
618  	      {
619  	         assert(consdata->eventdata == NULL);
620  	         assert(consdata->cliquepartition == NULL);
621  	         assert(consdata->negcliquepartition == NULL);
622  	      }
623  	      consdata->varssize = newsize;
624  	   }
625  	   assert(num <= consdata->varssize);
626  	
627  	   return SCIP_OKAY;
628  	}
629  	
630  	/** updates all weight sums for fixed and unfixed variables */
631  	static
632  	void updateWeightSums(
633  	   SCIP_CONSDATA*        consdata,           /**< knapsack constraint data */
634  	   SCIP_VAR*             var,                /**< variable for this weight */
635  	   SCIP_Longint          weightdelta         /**< difference between the old and the new weight of the variable */
636  	   )
637  	{
638  	   assert(consdata != NULL);
639  	   assert(var != NULL);
640  	
641  	   consdata->weightsum += weightdelta;
642  	
643  	   if( SCIPvarGetLbLocal(var) > 0.5 )
644  	      consdata->onesweightsum += weightdelta;
645  	
646  	   assert(consdata->weightsum >= 0);
647  	   assert(consdata->onesweightsum >= 0);
648  	}
649  	
650  	/** creates knapsack constraint data */
651  	static
652  	SCIP_RETCODE consdataCreate(
653  	   SCIP*                 scip,               /**< SCIP data structure */
654  	   SCIP_CONSDATA**       consdata,           /**< pointer to store constraint data */
655  	   int                   nvars,              /**< number of variables in knapsack */
656  	   SCIP_VAR**            vars,               /**< variables of knapsack */
657  	   SCIP_Longint*         weights,            /**< weights of knapsack items */
658  	   SCIP_Longint          capacity            /**< capacity of knapsack */
659  	   )
660  	{
661  	   int v;
662  	   SCIP_Longint constant;
663  	
664  	   assert(consdata != NULL);
665  	
666  	   SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
667  	
668  	   constant = 0L;
669  	   (*consdata)->vars = NULL;
670  	   (*consdata)->weights = NULL;
671  	   (*consdata)->nvars = 0;
672  	   if( nvars > 0 )
673  	   {
674  	      SCIP_VAR** varsbuffer;
675  	      SCIP_Longint* weightsbuffer;
676  	      int k;
677  	
678  	      SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
679  	      SCIP_CALL( SCIPallocBufferArray(scip, &weightsbuffer, nvars) );
680  	
681  	      k = 0;
682  	      for( v = 0; v < nvars; ++v )
683  	      {
684  	         assert(vars[v] != NULL);
685  	         assert(SCIPvarIsBinary(vars[v]));
686  	
687  	         /* all weight have to be non negative */
688  	         assert( weights[v] >= 0 );
689  	
690  	         if( weights[v] > 0 )
691  	         {
692  	            /* treat fixed variables as constants if problem compression is enabled */
693  	            if( SCIPisConsCompressionEnabled(scip) && SCIPvarGetLbGlobal(vars[v]) > SCIPvarGetUbGlobal(vars[v]) - 0.5 )
694  	            {
695  	               /* only if the variable is fixed to 1, we add its weight to the constant */
696  	               if( SCIPvarGetUbGlobal(vars[v]) > 0.5 )
697  	                  constant += weights[v];
698  	            }
699  	            else
700  	            {
701  	               varsbuffer[k] = vars[v];
702  	               weightsbuffer[k] = weights[v];
703  	               ++k;
704  	            }
705  	         }
706  	      }
707  	      assert(k >= 0);
708  	      assert(constant >= 0);
709  	
710  	      (*consdata)->nvars = k;
711  	
712  	      /* copy the active variables and weights into the constraint data structure */
713  	      if( k > 0 )
714  	      {
715  	         SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
716  	         SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->weights, weightsbuffer, k) );
717  	      }
718  	
719  	      /* free buffer storage */
720  	      SCIPfreeBufferArray(scip, &weightsbuffer);
721  	      SCIPfreeBufferArray(scip, &varsbuffer);
722  	   }
723  	
724  	   (*consdata)->varssize = (*consdata)->nvars;
725  	   (*consdata)->capacity = capacity - constant;
726  	   (*consdata)->eventdata = NULL;
727  	   (*consdata)->cliquepartition = NULL;
728  	   (*consdata)->negcliquepartition = NULL;
729  	   (*consdata)->row = NULL;
730  	   (*consdata)->nlrow = NULL;
731  	   (*consdata)->weightsum = 0;
732  	   (*consdata)->onesweightsum = 0;
733  	   (*consdata)->ncliques = 0;
734  	   (*consdata)->nnegcliques = 0;
735  	   (*consdata)->presolvedtiming = 0;
736  	   (*consdata)->sorted = FALSE;
737  	   (*consdata)->cliquepartitioned = FALSE;
738  	   (*consdata)->negcliquepartitioned = FALSE;
739  	   (*consdata)->ncliqueslastpart = -1;
740  	   (*consdata)->ncliqueslastnegpart = -1;
741  	   (*consdata)->merged = FALSE;
742  	   (*consdata)->cliquesadded = FALSE;
743  	   (*consdata)->varsdeleted = FALSE;
744  	   (*consdata)->existmultaggr = FALSE;
745  	
746  	   /* get transformed variables, if we are in the transformed problem */
747  	   if( SCIPisTransformed(scip) )
748  	   {
749  	      SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
750  	
751  	      for( v = 0; v < (*consdata)->nvars; v++ )
752  	      {
753  	         SCIP_VAR* var = SCIPvarGetProbvar((*consdata)->vars[v]);
754  	         assert(var != NULL);
755  	         (*consdata)->existmultaggr = (*consdata)->existmultaggr || (SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
756  	      }
757  	
758  	      /* allocate memory for additional data structures */
759  	      SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->eventdata, (*consdata)->nvars) );
760  	      SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->cliquepartition, (*consdata)->nvars) );
761  	      SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->negcliquepartition, (*consdata)->nvars) );
762  	   }
763  	
764  	   /* calculate sum of weights and capture variables */
765  	   for( v = 0; v < (*consdata)->nvars; ++v )
766  	   {
767  	      /* calculate sum of weights */
768  	      updateWeightSums(*consdata, (*consdata)->vars[v], (*consdata)->weights[v]);
769  	
770  	      /* capture variables */
771  	      SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
772  	   }
773  	   return SCIP_OKAY;
774  	}
775  	
776  	/** frees knapsack constraint data */
777  	static
778  	SCIP_RETCODE consdataFree(
779  	   SCIP*                 scip,               /**< SCIP data structure */
780  	   SCIP_CONSDATA**       consdata,           /**< pointer to the constraint data */
781  	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler to call for the event processing */
782  	   )
783  	{
784  	   assert(consdata != NULL);
785  	   assert(*consdata != NULL);
786  	
787  	   if( (*consdata)->row != NULL )
788  	   {
789  	      SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
790  	   }
791  	   if( (*consdata)->nlrow != NULL )
792  	   {
793  	      SCIP_CALL( SCIPreleaseNlRow(scip, &(*consdata)->nlrow) );
794  	   }
795  	   if( (*consdata)->eventdata != NULL )
796  	   {
797  	      SCIP_CALL( dropEvents(scip, *consdata, eventhdlr) );
798  	      SCIPfreeBlockMemoryArray(scip, &(*consdata)->eventdata, (*consdata)->varssize);
799  	   }
800  	   if( (*consdata)->negcliquepartition != NULL )
801  	   {
802  	      SCIPfreeBlockMemoryArray(scip, &(*consdata)->negcliquepartition, (*consdata)->varssize);
803  	   }
804  	   if( (*consdata)->cliquepartition != NULL )
805  	   {
806  	      SCIPfreeBlockMemoryArray(scip, &(*consdata)->cliquepartition, (*consdata)->varssize);
807  	   }
808  	   if( (*consdata)->vars != NULL )
809  	   {
810  	      int v;
811  	
812  	      /* release variables */
813  	      for( v = 0; v < (*consdata)->nvars; v++ )
814  	      {
815  	         assert((*consdata)->vars[v] != NULL);
816  	         SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
817  	      }
818  	
819  	      assert( (*consdata)->weights != NULL );
820  	      assert( (*consdata)->varssize > 0 );
821  	      SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->varssize);
822  	      SCIPfreeBlockMemoryArray(scip, &(*consdata)->weights, (*consdata)->varssize);
823  	   }
824  	
825  	   SCIPfreeBlockMemory(scip, consdata);
826  	
827  	   return SCIP_OKAY;
828  	}
829  	
830  	/** changes a single weight in knapsack constraint data */
831  	static
832  	void consdataChgWeight(
833  	   SCIP_CONSDATA*        consdata,           /**< knapsack constraint data */
834  	   int                   item,               /**< item number */
835  	   SCIP_Longint          newweight           /**< new weight of item */
836  	   )
837  	{
838  	   SCIP_Longint oldweight;
839  	   SCIP_Longint weightdiff;
840  	
841  	   assert(consdata != NULL);
842  	   assert(0 <= item && item < consdata->nvars);
843  	
844  	   oldweight = consdata->weights[item];
845  	   weightdiff = newweight - oldweight;
846  	   consdata->weights[item] = newweight;
847  	
848  	   /* update weight sums for all and fixed variables */
849  	   updateWeightSums(consdata, consdata->vars[item], weightdiff);
850  	
851  	   if( consdata->eventdata != NULL )
852  	   {
853  	      assert(consdata->eventdata[item] != NULL);
854  	      assert(consdata->eventdata[item]->weight == oldweight);
855  	      consdata->eventdata[item]->weight = newweight;
856  	   }
857  	
858  	   consdata->presolvedtiming = 0;
859  	   consdata->sorted = FALSE;
860  	
861  	   /* recalculate cliques extraction after a weight was increased */
862  	   if( oldweight < newweight )
863  	   {
864  	      consdata->cliquesadded = FALSE;
865  	   }
866  	}
867  	
868  	/** creates LP row corresponding to knapsack constraint */
869  	static
870  	SCIP_RETCODE createRelaxation(
871  	   SCIP*                 scip,               /**< SCIP data structure */
872  	   SCIP_CONS*            cons                /**< knapsack constraint */
873  	   )
874  	{
875  	   SCIP_CONSDATA* consdata;
876  	   int i;
877  	
878  	   consdata = SCIPconsGetData(cons);
879  	   assert(consdata != NULL);
880  	   assert(consdata->row == NULL);
881  	
882  	   SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons),
883  	         -SCIPinfinity(scip), (SCIP_Real)consdata->capacity,
884  	         SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsRemovable(cons)) );
885  	
886  	   SCIP_CALL( SCIPcacheRowExtensions(scip, consdata->row) );
887  	   for( i = 0; i < consdata->nvars; ++i )
888  	   {
889  	      SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, consdata->vars[i], (SCIP_Real)consdata->weights[i]) );
890  	   }
891  	   SCIP_CALL( SCIPflushRowExtensions(scip, consdata->row) );
892  	
893  	   return SCIP_OKAY;
894  	}
895  	
896  	/** adds linear relaxation of knapsack constraint to the LP */
897  	static
898  	SCIP_RETCODE addRelaxation(
899  	   SCIP*                 scip,               /**< SCIP data structure */
900  	   SCIP_CONS*            cons,               /**< knapsack constraint */
901  	   SCIP_Bool*            cutoff              /**< whether a cutoff has been detected */
902  	   )
903  	{
904  	   SCIP_CONSDATA* consdata;
905  	
906  	   assert( cutoff != NULL );
907  	   *cutoff = FALSE;
908  	
909  	   consdata = SCIPconsGetData(cons);
910  	   assert(consdata != NULL);
911  	
912  	   if( consdata->row == NULL )
913  	   {
914  	      SCIP_CALL( createRelaxation(scip, cons) );
915  	   }
916  	   assert(consdata->row != NULL);
917  	
918  	   /* insert LP row as cut */
919  	   if( !SCIProwIsInLP(consdata->row) )
920  	   {
921  	      SCIPdebugMsg(scip, "adding relaxation of knapsack constraint <%s> (capacity %" SCIP_LONGINT_FORMAT "): ",
922  	         SCIPconsGetName(cons), consdata->capacity);
923  	      SCIPdebug( SCIP_CALL(SCIPprintRow(scip, consdata->row, NULL)) );
924  	      SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
925  	   }
926  	
927  	   return SCIP_OKAY;
928  	}
929  	
930  	/** adds knapsack constraint as row to the NLP, if not added yet */
931  	static
932  	SCIP_RETCODE addNlrow(
933  	   SCIP*                 scip,               /**< SCIP data structure */
934  	   SCIP_CONS*            cons                /**< knapsack constraint */
935  	   )
936  	{
937  	   SCIP_CONSDATA* consdata;
938  	
939  	   assert(SCIPisNLPConstructed(scip));
940  	
941  	   /* skip deactivated, redundant, or local linear constraints (the NLP does not allow for local rows at the moment) */
942  	   if( !SCIPconsIsActive(cons) || !SCIPconsIsChecked(cons) || SCIPconsIsLocal(cons) )
943  	      return SCIP_OKAY;
944  	
945  	   consdata = SCIPconsGetData(cons);
946  	   assert(consdata != NULL);
947  	
948  	   if( consdata->nlrow == NULL )
949  	   {
950  	      SCIP_Real* coefs;
951  	      int i;
952  	
953  	      SCIP_CALL( SCIPallocBufferArray(scip, &coefs, consdata->nvars) );
954  	      for( i = 0; i < consdata->nvars; ++i )
955  	         coefs[i] = (SCIP_Real)consdata->weights[i];  /*lint !e613*/
956  	
957  	      SCIP_CALL( SCIPcreateNlRow(scip, &consdata->nlrow, SCIPconsGetName(cons), 0.0,
958  	            consdata->nvars, consdata->vars, coefs, NULL,
959  	            -SCIPinfinity(scip), (SCIP_Real)consdata->capacity, SCIP_EXPRCURV_LINEAR) );
960  	
961  	      assert(consdata->nlrow != NULL);
962  	
963  	      SCIPfreeBufferArray(scip, &coefs);
964  	   }
965  	
966  	   if( !SCIPnlrowIsInNLP(consdata->nlrow) )
967  	   {
968  	      SCIP_CALL( SCIPaddNlRow(scip, consdata->nlrow) );
969  	   }
970  	
971  	   return SCIP_OKAY;
972  	}
973  	
974  	/** checks knapsack constraint for feasibility of given solution: returns TRUE iff constraint is feasible */
975  	static
976  	SCIP_RETCODE checkCons(
977  	   SCIP*                 scip,               /**< SCIP data structure */
978  	   SCIP_CONS*            cons,               /**< constraint to check */
979  	   SCIP_SOL*             sol,                /**< solution to check, NULL for current solution */
980  	   SCIP_Bool             checklprows,        /**< Do constraints represented by rows in the current LP have to be checked? */
981  	   SCIP_Bool             printreason,        /**< Should the reason for the violation be printed? */
982  	   SCIP_Bool*            violated            /**< pointer to store whether the constraint is violated */
983  	   )
984  	{
985  	   SCIP_CONSDATA* consdata;
986  	
987  	   assert(violated != NULL);
988  	
989  	   consdata = SCIPconsGetData(cons);
990  	   assert(consdata != NULL);
991  	
992  	   SCIPdebugMsg(scip, "checking knapsack constraint <%s> for feasibility of solution %p (lprows=%u)\n",
993  	      SCIPconsGetName(cons), (void*)sol, checklprows);
994  	
995  	   *violated = FALSE;
996  	
997  	   if( checklprows || consdata->row == NULL || !SCIProwIsInLP(consdata->row) )
998  	   {
999  	      SCIP_Real sum;
1000 	      SCIP_Longint integralsum;
1001 	      SCIP_Bool ishuge;
1002 	      SCIP_Real absviol;
1003 	      SCIP_Real relviol;
1004 	      int v;
1005 	
1006 	      /* increase age of constraint; age is reset to zero, if a violation was found only in case we are in
1007 	       * enforcement
1008 	       */
1009 	      if( sol == NULL )
1010 	      {
1011 	         SCIP_CALL( SCIPincConsAge(scip, cons) );
1012 	      }
1013 	
1014 	      sum = 0.0;
1015 	      integralsum = 0;
1016 	      /* we perform a more exact comparison if the capacity does not exceed the huge value */
1017 	      if( SCIPisHugeValue(scip, (SCIP_Real) consdata->capacity) )
1018 	      {
1019 	         ishuge = TRUE;
1020 	
1021 	         /* sum over all weight times the corresponding solution value */
1022 	         for( v = consdata->nvars - 1; v >= 0; --v )
1023 	         {
1024 	            assert(SCIPvarIsBinary(consdata->vars[v]));
1025 	            sum += consdata->weights[v] * SCIPgetSolVal(scip, sol, consdata->vars[v]);
1026 	         }
1027 	      }
1028 	      else
1029 	      {
1030 	         ishuge = FALSE;
1031 	
1032 	         /* sum over all weight for which the variable has a solution value of 1 in feastol */
1033 	         for( v = consdata->nvars - 1; v >= 0; --v )
1034 	         {
1035 	            assert(SCIPvarIsBinary(consdata->vars[v]));
1036 	
1037 	            if( SCIPgetSolVal(scip, sol, consdata->vars[v]) > 0.5 )
1038 	               integralsum += consdata->weights[v];
1039 	         }
1040 	      }
1041 	
1042 	      /* calculate constraint violation and update it in solution */
1043 	      absviol = ishuge ? sum : (SCIP_Real)integralsum;
1044 	      absviol -= consdata->capacity;
1045 	      relviol = SCIPrelDiff(absviol + consdata->capacity, (SCIP_Real)consdata->capacity);
1046 	      if( sol != NULL )
1047 	         SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
1048 	
1049 	      if( SCIPisFeasPositive(scip, absviol) )
1050 	      {
1051 	         *violated = TRUE;
1052 	
1053 	         /* only reset constraint age if we are in enforcement */
1054 	         if( sol == NULL )
1055 	         {
1056 	            SCIP_CALL( SCIPresetConsAge(scip, cons) );
1057 	         }
1058 	
1059 	         if( printreason )
1060 	         {
1061 	            SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
1062 	
1063 	            SCIPinfoMessage(scip, NULL, ";\n");
1064 	            SCIPinfoMessage(scip, NULL, "violation: the capacity is violated by %.15g\n", absviol);
1065 	         }
1066 	      }
1067 	   }
1068 	
1069 	   return SCIP_OKAY;
1070 	}
1071 	
1072 	/* IDX computes the integer index for the optimal solution array */
1073 	#define IDX(j,d) ((j)*(intcap)+(d))
1074 	
1075 	/** solves knapsack problem in maximization form exactly using dynamic programming;
1076 	 *  if needed, one can provide arrays to store all selected items and all not selected items
1077 	 *
1078 	 * @note in case you provide the solitems or nonsolitems array you also have to provide the counter part, as well
1079 	 *
1080 	 * @note the algorithm will first compute a greedy solution and terminate
1081 	 *       if the greedy solution is proven to be optimal.
1082 	 *       The dynamic programming algorithm runs with a time and space complexity
1083 	 *       of O(nitems * capacity).
1084 	 *
1085 	 * @todo If only the objective is relevant, it is easy to change the code to use only one slice with O(capacity) space.
1086 	 *       There are recursive methods (see the book by Kellerer et al.) that require O(capacity) space, but it remains
1087 	 *       to be checked whether they are faster and whether they can reconstruct the solution.
1088 	 *       Dembo and Hammer (see Kellerer et al. Section 5.1.3, page 126) found a method that relies on a fast probing method.
1089 	 *       This fixes additional elements to 0 or 1 similar to a reduced cost fixing.
1090 	 *       This could be implemented, however, it would be technically a bit cumbersome,
1091 	 *       since one needs the greedy solution and the LP-value for this.
1092 	 *       This is currently only available after the redundant items have already been sorted out.
1093 	 */
1094 	SCIP_RETCODE SCIPsolveKnapsackExactly(
1095 	   SCIP*                 scip,               /**< SCIP data structure */
1096 	   int                   nitems,             /**< number of available items */
1097 	   SCIP_Longint*         weights,            /**< item weights */
1098 	   SCIP_Real*            profits,            /**< item profits */
1099 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
1100 	   int*                  items,              /**< item numbers */
1101 	   int*                  solitems,           /**< array to store items in solution, or NULL */
1102 	   int*                  nonsolitems,        /**< array to store items not in solution, or NULL */
1103 	   int*                  nsolitems,          /**< pointer to store number of items in solution, or NULL */
1104 	   int*                  nnonsolitems,       /**< pointer to store number of items not in solution, or NULL */
1105 	   SCIP_Real*            solval,             /**< pointer to store optimal solution value, or NULL */
1106 	   SCIP_Bool*            success             /**< pointer to store if an error occured during solving
1107 	                                              *   (normally a memory problem) */
1108 	   )
1109 	{
1110 	   SCIP_RETCODE retcode;
1111 	   SCIP_Real* tempsort;
1112 	   SCIP_Real* optvalues;
1113 	   int intcap;
1114 	   int d;
1115 	   int j;
1116 	   int greedymedianpos;
1117 	   SCIP_Longint weightsum;
1118 	   int* myitems;
1119 	   SCIP_Longint* myweights;
1120 	   SCIP_Real* realweights;
1121 	   int* allcurrminweight;
1122 	   SCIP_Real* myprofits;
1123 	   int nmyitems;
1124 	   SCIP_Longint gcd;
1125 	   SCIP_Longint minweight;
1126 	   SCIP_Longint maxweight;
1127 	   int currminweight;
1128 	   SCIP_Longint greedysolweight;
1129 	   SCIP_Real greedysolvalue;
1130 	   SCIP_Real greedyupperbound;
1131 	   SCIP_Bool eqweights;
1132 	   SCIP_Bool intprofits;
1133 	
1134 	   assert(weights != NULL);
1135 	   assert(profits != NULL);
1136 	   assert(capacity >= 0);
1137 	   assert(items != NULL);
1138 	   assert(nitems >= 0);
1139 	   assert(success != NULL);
1140 	
1141 	   *success = TRUE;
1142 	
1143 	#ifndef NDEBUG
1144 	   for( j = nitems - 1; j >= 0; --j )
1145 	      assert(weights[j] >= 0);
1146 	#endif
1147 	
1148 	   SCIPdebugMsg(scip, "Solving knapsack exactly.\n");
1149 	
1150 	   /* initializing solution value */
1151 	   if( solval != NULL )
1152 	      *solval = 0.0;
1153 	
1154 	   /* init solution information */
1155 	   if( solitems != NULL )
1156 	   {
1157 	      assert(items != NULL);
1158 	      assert(nsolitems != NULL);
1159 	      assert(nonsolitems != NULL);
1160 	      assert(nnonsolitems != NULL);
1161 	
1162 	      *nnonsolitems = 0;
1163 	      *nsolitems = 0;
1164 	   }
1165 	
1166 	   /* allocate temporary memory */
1167 	   SCIP_CALL( SCIPallocBufferArray(scip, &myweights, nitems) );
1168 	   SCIP_CALL( SCIPallocBufferArray(scip, &myprofits, nitems) );
1169 	   SCIP_CALL( SCIPallocBufferArray(scip, &myitems, nitems) );
1170 	   nmyitems = 0;
1171 	   weightsum = 0;
1172 	   minweight = SCIP_LONGINT_MAX;
1173 	   maxweight = 0;
1174 	
1175 	   /* remove unnecessary items */
1176 	   for( j = 0; j < nitems; ++j )
1177 	   {
1178 	      assert(0 <= weights[j] && weights[j] < SCIP_LONGINT_MAX);
1179 	
1180 	      /* item does not fit */
1181 	      if( weights[j] > capacity )
1182 	      {
1183 	         if( solitems != NULL )
1184 	            nonsolitems[(*nnonsolitems)++] = items[j]; /*lint !e413*/
1185 	      }
1186 	      /* item is not profitable */
1187 	      else if( profits[j] <= 0.0 )
1188 	      {
1189 	         if( solitems != NULL )
1190 	            nonsolitems[(*nnonsolitems)++] = items[j]; /*lint !e413*/
1191 	      }
1192 	      /* item always fits */
1193 	      else if( weights[j] == 0 )
1194 	      {
1195 	         if( solitems != NULL )
1196 	            solitems[(*nsolitems)++] = items[j]; /*lint !e413*/
1197 	
1198 	         if( solval != NULL )
1199 	            *solval += profits[j];
1200 	      }
1201 	      /* all important items */
1202 	      else
1203 	      {
1204 	         myweights[nmyitems] = weights[j];
1205 	         myprofits[nmyitems] = profits[j];
1206 	         myitems[nmyitems] = items[j];
1207 	
1208 	         /* remember smallest item */
1209 	         if( myweights[nmyitems] < minweight )
1210 	            minweight = myweights[nmyitems];
1211 	
1212 	         /* remember bigest item */
1213 	         if( myweights[nmyitems] > maxweight )
1214 	            maxweight = myweights[nmyitems];
1215 	
1216 	         weightsum += myweights[nmyitems];
1217 	         ++nmyitems;
1218 	      }
1219 	   }
1220 	
1221 	   intprofits = TRUE;
1222 	   /* check if all profits are integer to strengthen the upper bound on the greedy solution */
1223 	   for( j = 0; j < nmyitems && intprofits; ++j )
1224 	      intprofits = intprofits && SCIPisIntegral(scip, myprofits[j]);
1225 	
1226 	   /* if no item is left then goto end */
1227 	   if( nmyitems == 0 )
1228 	   {
1229 	      SCIPdebugMsg(scip, "After preprocessing no items are left.\n");
1230 	
1231 	      goto TERMINATE;
1232 	   }
1233 	
1234 	   /* if all items fit, we also do not need to do the expensive stuff later on */
1235 	   if( weightsum > 0 && weightsum <= capacity )
1236 	   {
1237 	      SCIPdebugMsg(scip, "After preprocessing all items fit into knapsack.\n");
1238 	
1239 	      for( j = nmyitems - 1; j >= 0; --j )
1240 	      {
1241 	         if( solitems != NULL )
1242 	            solitems[(*nsolitems)++] = myitems[j]; /*lint !e413*/
1243 	
1244 	         if( solval != NULL )
1245 	            *solval += myprofits[j];
1246 	      }
1247 	
1248 	      goto TERMINATE;
1249 	   }
1250 	
1251 	   assert(0 < minweight && minweight <= capacity );
1252 	   assert(0 < maxweight && maxweight <= capacity);
1253 	
1254 	   /* make weights relatively prime */
1255 	   eqweights = TRUE;
1256 	   if( maxweight > 1 )
1257 	   {
1258 	      /* determine greatest common divisor */
1259 	      gcd = myweights[nmyitems - 1];
1260 	      for( j = nmyitems - 2; j >= 0 && gcd >= 2; --j )
1261 	         gcd = SCIPcalcGreComDiv(gcd, myweights[j]);
1262 	
1263 	      SCIPdebugMsg(scip, "Gcd is %" SCIP_LONGINT_FORMAT ".\n", gcd);
1264 	
1265 	      /* divide by greatest common divisor */
1266 	      if( gcd > 1 )
1267 	      {
1268 	         for( j = nmyitems - 1; j >= 0; --j )
1269 	         {
1270 	            myweights[j] /= gcd;
1271 	            eqweights = eqweights && (myweights[j] == 1);
1272 	         }
1273 	         capacity /= gcd;
1274 	         minweight /= gcd;
1275 	      }
1276 	      else
1277 	         eqweights = FALSE;
1278 	   }
1279 	   assert(minweight <= capacity);
1280 	
1281 	   /* if only one item fits, then take the best */
1282 	   if( minweight > capacity / 2 )
1283 	   {
1284 	      int p;
1285 	
1286 	      SCIPdebugMsg(scip, "Only one item fits into knapsack, so take the best.\n");
1287 	
1288 	      p = nmyitems - 1;
1289 	
1290 	      /* find best item */
1291 	      for( j = nmyitems - 2; j >= 0; --j )
1292 	      {
1293 	         if( myprofits[j] > myprofits[p] )
1294 	            p = j;
1295 	      }
1296 	
1297 	      /* update solution information */
1298 	      if( solitems != NULL )
1299 	      {
1300 	         assert(nsolitems != NULL && nonsolitems != NULL && nnonsolitems != NULL);
1301 	
1302 	         solitems[(*nsolitems)++] = myitems[p];
1303 	         for( j = nmyitems - 1; j >= 0; --j )
1304 	         {
1305 	            if( j != p )
1306 	               nonsolitems[(*nnonsolitems)++] = myitems[j];
1307 	         }
1308 	      }
1309 	      /* update solution value */
1310 	      if( solval != NULL )
1311 	         *solval += myprofits[p];
1312 	
1313 	      goto TERMINATE;
1314 	   }
1315 	
1316 	   /* if all items have the same weight, then take the best */
1317 	   if( eqweights )
1318 	   {
1319 	      SCIP_Real addval = 0.0;
1320 	
1321 	      SCIPdebugMsg(scip, "All weights are equal, so take the best.\n");
1322 	
1323 	      SCIPsortDownRealIntLong(myprofits, myitems, myweights, nmyitems);
1324 	
1325 	      /* update solution information */
1326 	      if( solitems != NULL || solval != NULL )
1327 	      {
1328 	         SCIP_Longint i;
1329 	
1330 	         /* if all items would fit we had handled this case before */
1331 	         assert((SCIP_Longint) nmyitems > capacity);
1332 	         assert(nsolitems != NULL && nonsolitems != NULL && nnonsolitems != NULL);
1333 	
1334 	         /* take the first best items into the solution */
1335 	         for( i = capacity - 1; i >= 0; --i )
1336 	         {
1337 	            if( solitems != NULL )
1338 	               solitems[(*nsolitems)++] = myitems[i];
1339 	            addval += myprofits[i];
1340 	         }
1341 	
1342 	         if( solitems != NULL )
1343 	         {
1344 	            /* the rest are not in the solution */
1345 	            for( i = nmyitems - 1; i >= capacity; --i )
1346 	               nonsolitems[(*nnonsolitems)++] = myitems[i];
1347 	         }
1348 	      }
1349 	      /* update solution value */
1350 	      if( solval != NULL )
1351 	      {
1352 	         assert(addval > 0.0);
1353 	         *solval += addval;
1354 	      }
1355 	
1356 	      goto TERMINATE;
1357 	   }
1358 	
1359 	   SCIPdebugMsg(scip, "Determine greedy solution.\n");
1360 	
1361 	   /* sort myitems (plus corresponding arrays myweights and myprofits) such that
1362 	    * p_1/w_1 >= p_2/w_2 >= ... >= p_n/w_n, this is only used for the greedy solution
1363 	    */
1364 	   SCIP_CALL( SCIPallocBufferArray(scip, &tempsort, nmyitems) );
1365 	   SCIP_CALL( SCIPallocBufferArray(scip, &realweights, nmyitems) );
1366 	
1367 	   for( j = 0; j < nmyitems; ++j )
1368 	   {
1369 	      tempsort[j] = myprofits[j]/((SCIP_Real) myweights[j]);
1370 	      realweights[j] = (SCIP_Real)myweights[j];
1371 	   }
1372 	
1373 	   SCIPselectWeightedDownRealLongRealInt(tempsort, myweights, myprofits, myitems, realweights,
1374 	      (SCIP_Real)capacity, nmyitems, &greedymedianpos);
1375 	
1376 	   SCIPfreeBufferArray(scip, &realweights);
1377 	   SCIPfreeBufferArray(scip, &tempsort);
1378 	
1379 	   /* initialize values for greedy solution information */
1380 	   greedysolweight = 0;
1381 	   greedysolvalue = 0.0;
1382 	
1383 	   /* determine greedy solution */
1384 	   for( j = 0; j < greedymedianpos; ++j )
1385 	   {
1386 	      assert(myweights[j] <= capacity);
1387 	
1388 	      /* update greedy solution weight and value */
1389 	      greedysolweight += myweights[j];
1390 	      greedysolvalue += myprofits[j];
1391 	   }
1392 	
1393 	   assert(0 < greedysolweight && greedysolweight <= capacity);
1394 	   assert(greedysolvalue > 0.0);
1395 	
1396 	   /* If the greedy solution is optimal by comparing to the LP solution, we take this solution. This happens if:
1397 	    * - the greedy solution reaches the capacity, because then the LP solution is integral;
1398 	    * - the greedy solution has an objective that is at least the LP value rounded down in case that all profits are integer, too. */
1399 	   greedyupperbound = greedysolvalue + myprofits[j] * (SCIP_Real) (capacity - greedysolweight)/((SCIP_Real) myweights[j]);
1400 	   if( intprofits )
1401 	      greedyupperbound = SCIPfloor(scip, greedyupperbound);
1402 	   if( greedysolweight == capacity || SCIPisGE(scip, greedysolvalue, greedyupperbound) )
1403 	   {
1404 	      SCIPdebugMsg(scip, "Greedy solution is optimal.\n");
1405 	
1406 	      /* update solution information */
1407 	      if( solitems != NULL )
1408 	      {
1409 	         int l;
1410 	
1411 	         assert(nsolitems != NULL && nonsolitems != NULL && nnonsolitems != NULL);
1412 	
1413 	         /* collect items */
1414 	         for( l = 0; l < j; ++l )
1415 	            solitems[(*nsolitems)++] = myitems[l];
1416 	         for ( ; l < nmyitems; ++l )
1417 	            nonsolitems[(*nnonsolitems)++] = myitems[l];
1418 	      }
1419 	      /* update solution value */
1420 	      if( solval != NULL )
1421 	      {
1422 	         assert(greedysolvalue > 0.0);
1423 	         *solval += greedysolvalue;
1424 	      }
1425 	
1426 	      goto TERMINATE;
1427 	   }
1428 	
1429 	   /* in the following table we do not need the first minweight columns */
1430 	   capacity -= (minweight - 1);
1431 	
1432 	   /* we can only handle integers */
1433 	   if( capacity >= INT_MAX )
1434 	   {
1435 	      SCIPdebugMsg(scip, "Capacity is to big, so we cannot handle it here.\n");
1436 	
1437 	      *success = FALSE;
1438 	      goto TERMINATE;
1439 	   }
1440 	   assert(capacity < INT_MAX);
1441 	
1442 	   intcap = (int)capacity;
1443 	   assert(intcap >= 0);
1444 	   assert(nmyitems > 0);
1445 	   assert(sizeof(size_t) >= sizeof(int)); /*lint !e506*/ /* no following conversion should be messed up */
1446 	
1447 	   /* this condition checks whether we will try to allocate a correct number of bytes and do not have an overflow, while
1448 	    * computing the size for the allocation
1449 	    */
1450 	   if( intcap < 0 || (intcap > 0 && (((size_t)nmyitems) > (SIZE_MAX / (size_t)intcap / sizeof(*optvalues)) || ((size_t)nmyitems) * ((size_t)intcap) * sizeof(*optvalues) > ((size_t)INT_MAX) )) ) /*lint !e571*/
1451 	   {
1452 	      SCIPdebugMsg(scip, "Too much memory (%lu) would be consumed.\n", (unsigned long) (((size_t)nmyitems) * ((size_t)intcap) * sizeof(*optvalues))); /*lint !e571*/
1453 	
1454 	      *success = FALSE;
1455 	      goto TERMINATE;
1456 	   }
1457 	
1458 	   /* allocate temporary memory and check for memory exceedance */
1459 	   retcode = SCIPallocBufferArray(scip, &optvalues, nmyitems * intcap);
1460 	   if( retcode == SCIP_NOMEMORY )
1461 	   {
1462 	      SCIPdebugMsg(scip, "Did not get enough memory.\n");
1463 	
1464 	      *success = FALSE;
1465 	      goto TERMINATE;
1466 	   }
1467 	   else
1468 	   {
1469 	      SCIP_CALL( retcode );
1470 	   }
1471 	
1472 	   SCIPdebugMsg(scip, "Start real exact algorithm.\n");
1473 	
1474 	   /* we memorize at each step the current minimal weight to later on know which value in our optvalues matrix is valid;
1475 	    * each value entries of the j-th row of optvalues is valid if the index is >= allcurrminweight[j], otherwise it is
1476 	    * invalid; a second possibility would be to clear the whole optvalues, which should be more expensive than storing
1477 	    * 'nmyitem' values
1478 	    */
1479 	   SCIP_CALL( SCIPallocBufferArray(scip, &allcurrminweight, nmyitems) );
1480 	   assert(myweights[0] - minweight < INT_MAX);
1481 	   currminweight = (int) (myweights[0] - minweight);
1482 	   allcurrminweight[0] = currminweight;
1483 	
1484 	   /* fills first row of dynamic programming table with optimal values */
1485 	   for( d = currminweight; d < intcap; ++d )
1486 	      optvalues[d] = myprofits[0];
1487 	
1488 	   /* fills dynamic programming table with optimal values */
1489 	   for( j = 1; j < nmyitems; ++j )
1490 	   {
1491 	      int intweight;
1492 	
1493 	      /* compute important part of weight, which will be represented in the table */
1494 	      intweight = (int)(myweights[j] - minweight);
1495 	      assert(0 <= intweight && intweight < intcap);
1496 	
1497 	      /* copy all nonzeros from row above */
1498 	      for( d = currminweight; d < intweight && d < intcap; ++d )
1499 	         optvalues[IDX(j,d)] = optvalues[IDX(j-1,d)];
1500 	
1501 	      /* update corresponding row */
1502 	      for( d = intweight; d < intcap; ++d )
1503 	      {
1504 	         /* if index d < current minweight then optvalues[IDX(j-1,d)] is not initialized, i.e. should be 0 */
1505 	         if( d < currminweight )
1506 	            optvalues[IDX(j,d)] = myprofits[j];
1507 	         else
1508 	         {
1509 	            SCIP_Real sumprofit;
1510 	
1511 	            if( d - myweights[j] < currminweight )
1512 	               sumprofit = myprofits[j];
1513 	            else
1514 	               sumprofit = optvalues[IDX(j-1,(int)(d-myweights[j]))] + myprofits[j];
1515 	
1516 	            optvalues[IDX(j,d)] = MAX(sumprofit, optvalues[IDX(j-1,d)]);
1517 	         }
1518 	      }
1519 	
1520 	      /* update currminweight */
1521 	      if( intweight < currminweight )
1522 	         currminweight = intweight;
1523 	
1524 	      allcurrminweight[j] = currminweight;
1525 	   }
1526 	
1527 	   /* update optimal solution by following the table */
1528 	   if( solitems != NULL )
1529 	   {
1530 	      assert(nsolitems != NULL && nonsolitems != NULL && nnonsolitems != NULL);
1531 	      d = intcap - 1;
1532 	
1533 	      SCIPdebugMsg(scip, "Fill the solution vector after solving exactly.\n");
1534 	
1535 	      /* insert all items in (non-) solution vector */
1536 	      for( j = nmyitems - 1; j > 0; --j )
1537 	      {
1538 	         /* if the following condition holds this means all remaining items does not fit anymore */
1539 	         if( d < allcurrminweight[j] )
1540 	         {
1541 	            /* we cannot have exceeded our capacity */
1542 	            assert((SCIP_Longint) d >= -minweight);
1543 	            break;
1544 	         }
1545 	
1546 	         /* collect solution items; the first condition means that no further item can fit anymore, but this does */
1547 	         if( d < allcurrminweight[j-1] || optvalues[IDX(j,d)] > optvalues[IDX(j-1,d)] )
1548 	         {
1549 	            solitems[(*nsolitems)++] = myitems[j];
1550 	
1551 	            /* check that we do not have an underflow */
1552 	            assert(myweights[j] <= (INT_MAX + (SCIP_Longint) d));
1553 	            d = (int)(d - myweights[j]);
1554 	         }
1555 	         /* collect non-solution items */
1556 	         else
1557 	            nonsolitems[(*nnonsolitems)++] = myitems[j];
1558 	      }
1559 	
1560 	      /* insert remaining items */
1561 	      if( d >= allcurrminweight[j] )
1562 	      {
1563 	         assert(j == 0);
1564 	         solitems[(*nsolitems)++] = myitems[j];
1565 	      }
1566 	      else
1567 	      {
1568 	         assert(j >= 0);
1569 	         assert(d < allcurrminweight[j]);
1570 	
1571 	         for( ; j >= 0; --j )
1572 	            nonsolitems[(*nnonsolitems)++] = myitems[j];
1573 	      }
1574 	
1575 	      assert(*nsolitems + *nnonsolitems == nitems);
1576 	   }
1577 	
1578 	   /* update solution value */
1579 	   if( solval != NULL )
1580 	      *solval += optvalues[IDX(nmyitems-1,intcap-1)];
1581 	   SCIPfreeBufferArray(scip, &allcurrminweight);
1582 	
1583 	   /* free all temporary memory */
1584 	   SCIPfreeBufferArray(scip, &optvalues);
1585 	
1586 	 TERMINATE:
1587 	   SCIPfreeBufferArray(scip, &myitems);
1588 	   SCIPfreeBufferArray(scip, &myprofits);
1589 	   SCIPfreeBufferArray(scip, &myweights);
1590 	
1591 	   return SCIP_OKAY;
1592 	}
1593 	
1594 	/** solves knapsack problem in maximization form approximately by solving the LP-relaxation of the problem using Dantzig's
1595 	 *  method and rounding down the solution; if needed, one can provide arrays to store all selected items and all not
1596 	 *  selected items
1597 	 */
1598 	SCIP_RETCODE SCIPsolveKnapsackApproximately(
1599 	   SCIP*                 scip,               /**< SCIP data structure */
1600 	   int                   nitems,             /**< number of available items */
1601 	   SCIP_Longint*         weights,            /**< item weights */
1602 	   SCIP_Real*            profits,            /**< item profits */
1603 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
1604 	   int*                  items,              /**< item numbers */
1605 	   int*                  solitems,           /**< array to store items in solution, or NULL */
1606 	   int*                  nonsolitems,        /**< array to store items not in solution, or NULL */
1607 	   int*                  nsolitems,          /**< pointer to store number of items in solution, or NULL */
1608 	   int*                  nnonsolitems,       /**< pointer to store number of items not in solution, or NULL */
1609 	   SCIP_Real*            solval              /**< pointer to store optimal solution value, or NULL */
1610 	   )
1611 	{
1612 	   SCIP_Real* tempsort;
1613 	   SCIP_Longint solitemsweight;
1614 	   SCIP_Real* realweights;
1615 	   int j;
1616 	   int criticalindex;
1617 	
1618 	   assert(weights != NULL);
1619 	   assert(profits != NULL);
1620 	   assert(capacity >= 0);
1621 	   assert(items != NULL);
1622 	   assert(nitems >= 0);
1623 	
1624 	   if( solitems != NULL )
1625 	   {
1626 	      *nsolitems = 0;
1627 	      *nnonsolitems = 0;
1628 	   }
1629 	   if( solval != NULL )
1630 	      *solval = 0.0;
1631 	
1632 	   /* initialize data for median search */
1633 	   SCIP_CALL( SCIPallocBufferArray(scip, &tempsort, nitems) );
1634 	   SCIP_CALL( SCIPallocBufferArray(scip, &realweights, nitems) );
1635 	   for( j = nitems - 1; j >= 0; --j )
1636 	   {
1637 	      tempsort[j] = profits[j]/((SCIP_Real) weights[j]);
1638 	      realweights[j] = (SCIP_Real)weights[j];
1639 	   }
1640 	
1641 	   /* partially sort indices such that all elements that are larger than the break item appear first */
1642 	   SCIPselectWeightedDownRealLongRealInt(tempsort, weights, profits, items, realweights, (SCIP_Real)capacity, nitems, &criticalindex);
1643 	
1644 	   /* selects items as long as they fit into the knapsack */
1645 	   solitemsweight = 0;
1646 	   for( j = 0; j < nitems && solitemsweight + weights[j] <= capacity; ++j )
1647 	   {
1648 	      if( solitems != NULL )
1649 	         solitems[(*nsolitems)++] = items[j];
1650 	
1651 	      if( solval != NULL )
1652 	         (*solval) += profits[j];
1653 	      solitemsweight += weights[j];
1654 	   }
1655 	   if ( solitems != NULL )
1656 	   {
1657 	      for( ; j < nitems; j++ )
1658 	         nonsolitems[(*nnonsolitems)++] = items[j];
1659 	   }
1660 	
1661 	   SCIPfreeBufferArray(scip, &realweights);
1662 	   SCIPfreeBufferArray(scip, &tempsort);
1663 	
1664 	   return SCIP_OKAY;
1665 	}
1666 	
1667 	#ifdef SCIP_DEBUG
1668 	/** prints all nontrivial GUB constraints and their LP solution values */
1669 	static
1670 	void GUBsetPrint(
1671 	   SCIP*                 scip,               /**< SCIP data structure */
1672 	   SCIP_GUBSET*          gubset,             /**< GUB set data structure */
1673 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
1674 	   SCIP_Real*            solvals             /**< solution values of variables in knapsack constraint; or NULL */
1675 	   )
1676 	{
1677 	   int nnontrivialgubconss;
1678 	   int c;
1679 	
1680 	   nnontrivialgubconss = 0;
1681 	
1682 	   SCIPdebugMsg(scip, "   Nontrivial GUBs of current GUB set:\n");
1683 	
1684 	   /* print out all nontrivial GUB constraints, i.e., with more than one variable */
1685 	   for( c = 0; c < gubset->ngubconss; c++ )
1686 	   {
1687 	      SCIP_Real gubsolval;
1688 	
1689 	      assert(gubset->gubconss[c]->ngubvars >= 0);
1690 	
1691 	      /* nontrivial GUB */
1692 	      if( gubset->gubconss[c]->ngubvars > 1 )
1693 	      {
1694 	         int v;
1695 	
1696 	         gubsolval = 0.0;
1697 	         SCIPdebugMsg(scip, "   GUB<%d>:\n", c);
1698 	
1699 	         /* print GUB var */
1700 	         for( v = 0; v < gubset->gubconss[c]->ngubvars; v++ )
1701 	         {
1702 	            int currentvar;
1703 	
1704 	            currentvar = gubset->gubconss[c]->gubvars[v];
1705 	            if( solvals != NULL )
1706 	            {
1707 	               gubsolval += solvals[currentvar];
1708 	               SCIPdebugMsg(scip, "      +<%s>(%4.2f)\n", SCIPvarGetName(vars[currentvar]), solvals[currentvar]);
1709 	            }
1710 	            else
1711 	            {
1712 	               SCIPdebugMsg(scip, "      +<%s>\n", SCIPvarGetName(vars[currentvar]));
1713 	            }
1714 	         }
1715 	
1716 		 /* check whether LP solution satisfies the GUB constraint */
1717 	         if( solvals != NULL )
1718 	         {
1719 	            SCIPdebugMsg(scip, "      =%4.2f <= 1 %s\n", gubsolval,
1720 	               SCIPisFeasGT(scip, gubsolval, 1.0) ? "--> violated" : "");
1721 	         }
1722 	         else
1723 	         {
1724 	            SCIPdebugMsg(scip, "      <= 1 %s\n", SCIPisFeasGT(scip, gubsolval, 1.0) ? "--> violated" : "");
1725 	         }
1726 	         nnontrivialgubconss++;
1727 	      }
1728 	   }
1729 	
1730 	   SCIPdebugMsg(scip, "   --> %d/%d nontrivial GUBs\n", nnontrivialgubconss, gubset->ngubconss);
1731 	}
1732 	#endif
1733 	
1734 	/** creates an empty GUB constraint */
1735 	static
1736 	SCIP_RETCODE GUBconsCreate(
1737 	   SCIP*                 scip,               /**< SCIP data structure */
1738 	   SCIP_GUBCONS**        gubcons             /**< pointer to store GUB constraint data */
1739 	   )
1740 	{
1741 	   assert(scip != NULL);
1742 	   assert(gubcons != NULL);
1743 	
1744 	   /* allocate memory for GUB constraint data structures */
1745 	   SCIP_CALL( SCIPallocBuffer(scip, gubcons) );
1746 	   (*gubcons)->gubvarssize = GUBCONSGROWVALUE;
1747 	   SCIP_CALL( SCIPallocBufferArray(scip, &(*gubcons)->gubvars, (*gubcons)->gubvarssize) );
1748 	   SCIP_CALL( SCIPallocBufferArray(scip, &(*gubcons)->gubvarsstatus, (*gubcons)->gubvarssize) );
1749 	
1750 	   (*gubcons)->ngubvars = 0;
1751 	
1752 	   return SCIP_OKAY;
1753 	}
1754 	
1755 	/** frees GUB constraint */
1756 	static
1757 	void GUBconsFree(
1758 	   SCIP*                 scip,               /**< SCIP data structure */
1759 	   SCIP_GUBCONS**        gubcons             /**< pointer to GUB constraint data structure */
1760 	   )
1761 	{
1762 	   assert(scip != NULL);
1763 	   assert(gubcons != NULL);
1764 	   assert((*gubcons)->gubvars != NULL);
1765 	   assert((*gubcons)->gubvarsstatus != NULL);
1766 	
1767 	   /* free allocated memory */
1768 	   SCIPfreeBufferArray(scip, &(*gubcons)->gubvarsstatus);
1769 	   SCIPfreeBufferArray(scip, &(*gubcons)->gubvars);
1770 	   SCIPfreeBuffer(scip, gubcons);
1771 	}
1772 	
1773 	/** adds variable to given GUB constraint */
1774 	static
1775 	SCIP_RETCODE GUBconsAddVar(
1776 	   SCIP*                 scip,               /**< SCIP data structure */
1777 	   SCIP_GUBCONS*         gubcons,            /**< GUB constraint data */
1778 	   int                   var                 /**< index of given variable in knapsack constraint */
1779 	   )
1780 	{
1781 	   assert(scip != NULL);
1782 	   assert(gubcons != NULL);
1783 	   assert(gubcons->ngubvars >= 0 && gubcons->ngubvars < gubcons->gubvarssize);
1784 	   assert(gubcons->gubvars != NULL);
1785 	   assert(gubcons->gubvarsstatus != NULL);
1786 	   assert(var >= 0);
1787 	
1788 	   /* add variable to GUB constraint */
1789 	   gubcons->gubvars[gubcons->ngubvars] = var;
1790 	   gubcons->gubvarsstatus[gubcons->ngubvars] = GUBVARSTATUS_UNINITIAL;
1791 	   gubcons->ngubvars++;
1792 	
1793 	   /* increase space allocated to GUB constraint if the number of variables reaches the size */
1794 	   if( gubcons->ngubvars == gubcons->gubvarssize )
1795 	   {
1796 	      int newlen;
1797 	
1798 	      newlen = gubcons->gubvarssize + GUBCONSGROWVALUE;
1799 	      SCIP_CALL( SCIPreallocBufferArray(scip, &gubcons->gubvars, newlen) );
1800 	      SCIP_CALL( SCIPreallocBufferArray(scip, &gubcons->gubvarsstatus, newlen) );
1801 	
1802 	      gubcons->gubvarssize = newlen;
1803 	   }
1804 	
1805 	   return SCIP_OKAY;
1806 	}
1807 	
1808 	/** deletes variable from its current GUB constraint */
1809 	static
1810 	SCIP_RETCODE GUBconsDelVar(
1811 	   SCIP*                 scip,               /**< SCIP data structure */
1812 	   SCIP_GUBCONS*         gubcons,            /**< GUB constraint data */
1813 	   int                   var,                /**< index of given variable in knapsack constraint */
1814 	   int                   gubvarsidx          /**< index of the variable in its current GUB constraint */
1815 	   )
1816 	{
1817 	   assert(scip != NULL);
1818 	   assert(gubcons != NULL);
1819 	   assert(var >= 0);
1820 	   assert(gubvarsidx >= 0 && gubvarsidx < gubcons->ngubvars);
1821 	   assert(gubcons->ngubvars >= gubvarsidx+1);
1822 	   assert(gubcons->gubvars[gubvarsidx] == var);
1823 	
1824 	   /* delete variable from GUB by swapping it replacing in by the last variable in the GUB constraint */
1825 	   gubcons->gubvars[gubvarsidx] = gubcons->gubvars[gubcons->ngubvars-1];
1826 	   gubcons->gubvarsstatus[gubvarsidx] = gubcons->gubvarsstatus[gubcons->ngubvars-1];
1827 	   gubcons->ngubvars--;
1828 	
1829 	   /* decrease space allocated for the GUB constraint, if the last GUBCONSGROWVALUE+1 array entries are now empty */
1830 	   if( gubcons->ngubvars < gubcons->gubvarssize - GUBCONSGROWVALUE && gubcons->ngubvars > 0 )
1831 	   {
1832 	      int newlen;
1833 	
1834 	      newlen = gubcons->gubvarssize - GUBCONSGROWVALUE;
1835 	
1836 	      SCIP_CALL( SCIPreallocBufferArray(scip, &gubcons->gubvars, newlen) );
1837 	      SCIP_CALL( SCIPreallocBufferArray(scip, &gubcons->gubvarsstatus, newlen) );
1838 	
1839 	      gubcons->gubvarssize = newlen;
1840 	   }
1841 	
1842 	   return SCIP_OKAY;
1843 	}
1844 	
1845 	/** moves variable from current GUB constraint to a different existing (nonempty) GUB constraint */
1846 	static
1847 	SCIP_RETCODE GUBsetMoveVar(
1848 	   SCIP*                 scip,               /**< SCIP data structure */
1849 	   SCIP_GUBSET*          gubset,             /**< GUB set data structure */
1850 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
1851 	   int                   var,                /**< index of given variable in knapsack constraint */
1852 	   int                   oldgubcons,         /**< index of old GUB constraint of given variable */
1853 	   int                   newgubcons          /**< index of new GUB constraint of given variable */
1854 	   )
1855 	{
1856 	   int oldgubvaridx;
1857 	   int replacevar;
1858 	   int j;
1859 	
1860 	   assert(scip != NULL);
1861 	   assert(gubset != NULL);
1862 	   assert(var >= 0);
1863 	   assert(oldgubcons >= 0 && oldgubcons < gubset->ngubconss);
1864 	   assert(newgubcons >= 0 && newgubcons < gubset->ngubconss);
1865 	   assert(oldgubcons != newgubcons);
1866 	   assert(gubset->gubconssidx[var] == oldgubcons);
1867 	   assert(gubset->gubconss[oldgubcons]->ngubvars > 0);
1868 	   assert(gubset->gubconss[newgubcons]->ngubvars >= 0);
1869 	
1870 	   SCIPdebugMsg(scip, "   moving variable<%s> from GUB<%d> to GUB<%d>\n", SCIPvarGetName(vars[var]), oldgubcons, newgubcons);
1871 	
1872 	   oldgubvaridx = gubset->gubvarsidx[var];
1873 	
1874 	   /* delete variable from old GUB constraint by replacing it by the last variable of the GUB constraint */
1875 	   SCIP_CALL( GUBconsDelVar(scip, gubset->gubconss[oldgubcons], var, oldgubvaridx) );
1876 	
1877 	   /* in GUB set, update stored index of variable in old GUB constraint for the variable used for replacement;
1878 	    * replacement variable is given by old position of the deleted variable
1879 	    */
1880 	   replacevar = gubset->gubconss[oldgubcons]->gubvars[oldgubvaridx];
1881 	   assert(gubset->gubvarsidx[replacevar] == gubset->gubconss[oldgubcons]->ngubvars);
1882 	   gubset->gubvarsidx[replacevar] = oldgubvaridx;
1883 	
1884 	   /* add variable to the end of new GUB constraint */
1885 	   SCIP_CALL( GUBconsAddVar(scip, gubset->gubconss[newgubcons], var) );
1886 	   assert(gubset->gubconss[newgubcons]->gubvars[gubset->gubconss[newgubcons]->ngubvars-1] == var);
1887 	
1888 	   /* in GUB set, update stored index of GUB of moved variable and stored index of variable in this GUB constraint */
1889 	   gubset->gubconssidx[var] = newgubcons;
1890 	   gubset->gubvarsidx[var] = gubset->gubconss[newgubcons]->ngubvars-1;
1891 	
1892 	   /* delete old GUB constraint if it became empty */
1893 	   if( gubset->gubconss[oldgubcons]->ngubvars == 0 )
1894 	   {
1895 	      SCIPdebugMsg(scip, "deleting empty GUB cons<%d> from current GUB set\n", oldgubcons);
1896 	#ifdef SCIP_DEBUG
1897 	      GUBsetPrint(scip, gubset, vars, NULL);
1898 	#endif
1899 	
1900 	      /* free old GUB constraint */
1901 	      GUBconsFree(scip, &gubset->gubconss[oldgubcons]);
1902 	
1903 	      /* if empty GUB was not the last one in GUB set data structure, replace it by last GUB constraint */
1904 	      if( oldgubcons != gubset->ngubconss-1 )
1905 	      {
1906 	         gubset->gubconss[oldgubcons] = gubset->gubconss[gubset->ngubconss-1];
1907 	         gubset->gubconsstatus[oldgubcons] = gubset->gubconsstatus[gubset->ngubconss-1];
1908 	
1909 	         /* in GUB set, update stored index of GUB constraint for all variable of the GUB constraint used for replacement;
1910 	          * replacement GUB is given by old position of the deleted GUB
1911 	          */
1912 	         for( j = 0; j < gubset->gubconss[oldgubcons]->ngubvars; j++ )
1913 	         {
1914 	            assert(gubset->gubconssidx[gubset->gubconss[oldgubcons]->gubvars[j]] == gubset->ngubconss-1);
1915 	            gubset->gubconssidx[gubset->gubconss[oldgubcons]->gubvars[j]] = oldgubcons;
1916 	         }
1917 	      }
1918 	
1919 	      /* update number of GUB constraints */
1920 	      gubset->ngubconss--;
1921 	
1922 	      /* variable should be at given new position, unless new GUB constraint replaced empty old GUB constraint
1923 	       * (because it was at the end of the GUB constraint array)
1924 	       */
1925 	      assert(gubset->gubconssidx[var] == newgubcons
1926 	         || (newgubcons == gubset->ngubconss && gubset->gubconssidx[var] == oldgubcons));
1927 	   }
1928 	#ifndef NDEBUG
1929 	   else
1930 	      assert(gubset->gubconssidx[var] == newgubcons);
1931 	#endif
1932 	
1933 	   return SCIP_OKAY;
1934 	}
1935 	
1936 	/** swaps two variables in the same GUB constraint */
1937 	static
1938 	void GUBsetSwapVars(
1939 	   SCIP*                 scip,               /**< SCIP data structure */
1940 	   SCIP_GUBSET*          gubset,             /**< GUB set data structure */
1941 	   int                   var1,               /**< first variable to be swapped */
1942 	   int                   var2                /**< second variable to be swapped */
1943 	   )
1944 	{
1945 	   int gubcons;
1946 	   int var1idx;
1947 	   GUBVARSTATUS var1status;
1948 	   int var2idx;
1949 	   GUBVARSTATUS var2status;
1950 	
1951 	   assert(scip != NULL);
1952 	   assert(gubset != NULL);
1953 	
1954 	   gubcons = gubset->gubconssidx[var1];
1955 	   assert(gubcons == gubset->gubconssidx[var2]);
1956 	
1957 	   /* nothing to be done if both variables are the same */
1958 	   if( var1 == var2 )
1959 	      return;
1960 	
1961 	   /* swap index and status of variables in GUB constraint */
1962 	   var1idx = gubset->gubvarsidx[var1];
1963 	   var1status = gubset->gubconss[gubcons]->gubvarsstatus[var1idx];
1964 	   var2idx = gubset->gubvarsidx[var2];
1965 	   var2status = gubset->gubconss[gubcons]->gubvarsstatus[var2idx];
1966 	
1967 	   gubset->gubvarsidx[var1] = var2idx;
1968 	   gubset->gubconss[gubcons]->gubvars[var1idx] = var2;
1969 	   gubset->gubconss[gubcons]->gubvarsstatus[var1idx] = var2status;
1970 	
1971 	   gubset->gubvarsidx[var2] = var1idx;
1972 	   gubset->gubconss[gubcons]->gubvars[var2idx] = var1;
1973 	   gubset->gubconss[gubcons]->gubvarsstatus[var2idx] = var1status;
1974 	}
1975 	
1976 	/** initializes partition of knapsack variables into nonoverlapping trivial GUB constraints (GUB with one variable) */
1977 	static
1978 	SCIP_RETCODE GUBsetCreate(
1979 	   SCIP*                 scip,               /**< SCIP data structure */
1980 	   SCIP_GUBSET**         gubset,             /**< pointer to store GUB set data structure */
1981 	   int                   nvars,              /**< number of variables in the knapsack constraint */
1982 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
1983 	   SCIP_Longint          capacity            /**< capacity of knapsack */
1984 	   )
1985 	{
1986 	   int i;
1987 	
1988 	   assert(scip != NULL);
1989 	   assert(gubset != NULL);
1990 	   assert(nvars > 0);
1991 	   assert(weights != NULL);
1992 	   assert(capacity >= 0);
1993 	
1994 	   /* allocate memory for GUB set data structures */
1995 	   SCIP_CALL( SCIPallocBuffer(scip, gubset) );
1996 	   SCIP_CALL( SCIPallocBufferArray(scip, &(*gubset)->gubconss, nvars) );
1997 	   SCIP_CALL( SCIPallocBufferArray(scip, &(*gubset)->gubconsstatus, nvars) );
1998 	   SCIP_CALL( SCIPallocBufferArray(scip, &(*gubset)->gubconssidx, nvars) );
1999 	   SCIP_CALL( SCIPallocBufferArray(scip, &(*gubset)->gubvarsidx, nvars) );
2000 	   (*gubset)->ngubconss = nvars;
2001 	   (*gubset)->nvars = nvars;
2002 	
2003 	   /* initialize the set of GUB constraints */
2004 	   for( i = 0; i < nvars; i++ )
2005 	   {
2006 	      /* assign each variable to a new (trivial) GUB constraint */
2007 	      SCIP_CALL( GUBconsCreate(scip, &(*gubset)->gubconss[i]) );
2008 	      SCIP_CALL( GUBconsAddVar(scip, (*gubset)->gubconss[i], i) );
2009 	
2010 	      /* set status of GUB constraint to initial */
2011 	      (*gubset)->gubconsstatus[i] = GUBCONSSTATUS_UNINITIAL;
2012 	
2013 	      (*gubset)->gubconssidx[i] = i;
2014 	      (*gubset)->gubvarsidx[i] = 0;
2015 	      assert((*gubset)->gubconss[i]->ngubvars == 1);
2016 	
2017 	      /* already updated status of variable in GUB constraint if it exceeds the capacity of the knapsack */
2018 	      if( weights[i] > capacity )
2019 	         (*gubset)->gubconss[(*gubset)->gubconssidx[i]]->gubvarsstatus[(*gubset)->gubvarsidx[i]] = GUBVARSTATUS_CAPACITYEXCEEDED;
2020 	   }
2021 	
2022 	   return SCIP_OKAY;
2023 	}
2024 	
2025 	/** frees GUB set data structure */
2026 	static
2027 	void GUBsetFree(
2028 	   SCIP*                 scip,               /**< SCIP data structure */
2029 	   SCIP_GUBSET**         gubset              /**< pointer to GUB set data structure */
2030 	   )
2031 	{
2032 	   int i;
2033 	
2034 	   assert(scip != NULL);
2035 	   assert(gubset != NULL);
2036 	   assert((*gubset)->gubconss != NULL);
2037 	   assert((*gubset)->gubconsstatus != NULL);
2038 	   assert((*gubset)->gubconssidx != NULL);
2039 	   assert((*gubset)->gubvarsidx != NULL);
2040 	
2041 	   /* free all GUB constraints */
2042 	   for( i = (*gubset)->ngubconss-1; i >= 0; --i )
2043 	   {
2044 	      assert((*gubset)->gubconss[i] != NULL);
2045 	      GUBconsFree(scip, &(*gubset)->gubconss[i]);
2046 	   }
2047 	
2048 	   /* free allocated memory */
2049 	   SCIPfreeBufferArray( scip, &(*gubset)->gubvarsidx );
2050 	   SCIPfreeBufferArray( scip, &(*gubset)->gubconssidx );
2051 	   SCIPfreeBufferArray( scip, &(*gubset)->gubconsstatus );
2052 	   SCIPfreeBufferArray( scip, &(*gubset)->gubconss );
2053 	   SCIPfreeBuffer(scip, gubset);
2054 	}
2055 	
2056 	#ifndef NDEBUG
2057 	/** checks whether GUB set data structure is consistent */
2058 	static
2059 	SCIP_RETCODE GUBsetCheck(
2060 	   SCIP*                 scip,               /**< SCIP data structure */
2061 	   SCIP_GUBSET*          gubset,             /**< GUB set data structure */
2062 	   SCIP_VAR**            vars                /**< variables in the knapsack constraint */
2063 	   )
2064 	{
2065 	   int i;
2066 	   int gubconsidx;
2067 	   int gubvaridx;
2068 	   SCIP_VAR* var1;
2069 	   SCIP_VAR* var2;
2070 	   SCIP_Bool var1negated;
2071 	   SCIP_Bool var2negated;
2072 	
2073 	   assert(scip != NULL);
2074 	   assert(gubset != NULL);
2075 	
2076 	   SCIPdebugMsg(scip, "   GUB set consistency check:\n");
2077 	
2078 	   /* checks for all knapsack vars consistency of stored index of associated gubcons and corresponding index in gubvars */
2079 	   for( i = 0; i < gubset->nvars; i++ )
2080 	   {
2081 	      gubconsidx = gubset->gubconssidx[i];
2082 	      gubvaridx = gubset->gubvarsidx[i];
2083 	
2084 	      if( gubset->gubconss[gubconsidx]->gubvars[gubvaridx] != i )
2085 	      {
2086 		 SCIPdebugMsg(scip, "   var<%d> should be in GUB<%d> at position<%d>, but stored is var<%d> instead\n", i,
2087 	            gubconsidx, gubvaridx, gubset->gubconss[gubconsidx]->gubvars[gubvaridx] );
2088 	      }
2089 	      assert(gubset->gubconss[gubconsidx]->gubvars[gubvaridx] == i);
2090 	   }
2091 	
2092 	   /* checks for each GUB whether all pairs of its variables have a common clique */
2093 	   for( i = 0; i < gubset->ngubconss; i++ )
2094 	   {
2095 	      int j;
2096 	
2097 	      for( j = 0; j < gubset->gubconss[i]->ngubvars; j++ )
2098 	      {
2099 	         int k;
2100 	
2101 	         /* get corresponding active problem variable */
2102 	         var1 = vars[gubset->gubconss[i]->gubvars[j]];
2103 	         var1negated = FALSE;
2104 	         SCIP_CALL( SCIPvarGetProbvarBinary(&var1, &var1negated) );
2105 	
2106 	         for( k = j+1; k < gubset->gubconss[i]->ngubvars; k++ )
2107 	         {
2108 	            /* get corresponding active problem variable */
2109 	            var2 = vars[gubset->gubconss[i]->gubvars[k]];
2110 	            var2negated = FALSE;
2111 	            SCIP_CALL( SCIPvarGetProbvarBinary(&var2, &var2negated) );
2112 	
2113 	            if( !SCIPvarsHaveCommonClique(var1, !var1negated, var2, !var2negated, TRUE) )
2114 	            {
2115 	               SCIPdebugMsg(scip, "   GUB<%d>: var<%d,%s> and var<%d,%s> do not share a clique\n", i, j,
2116 	                  SCIPvarGetName(vars[gubset->gubconss[i]->gubvars[j]]), k,
2117 	                  SCIPvarGetName(vars[gubset->gubconss[i]->gubvars[k]]));
2118 	               SCIPdebugMsg(scip, "   GUB<%d>: var<%d,%s> and var<%d,%s> do not share a clique\n", i, j,
2119 	                  SCIPvarGetName(var1), k,
2120 	                  SCIPvarGetName(var2));
2121 	            }
2122 	
2123 	            /* @todo: in case we used also negated cliques for the GUB partition, this assert has to be changed */
2124 	            assert(SCIPvarsHaveCommonClique(var1, !var1negated, var2, !var2negated, TRUE));
2125 	         }
2126 	      }
2127 	   }
2128 	   SCIPdebugMsg(scip, "   --> successful\n");
2129 	
2130 	   return SCIP_OKAY;
2131 	}
2132 	#endif
2133 	
2134 	/** calculates a partition of the given set of binary variables into cliques;
2135 	 *  afterwards the output array contains one value for each variable, such that two variables got the same value iff they
2136 	 *  were assigned to the same clique;
2137 	 *  the first variable is always assigned to clique 0, and a variable can only be assigned to clique i if at least one of
2138 	 *  the preceding variables was assigned to clique i-1;
2139 	 *  note: in contrast to SCIPcalcCliquePartition(), variables with LP value 1 are put into trivial cliques (with one
2140 	 *  variable) and for the remaining variables, a partition with a small number of cliques is constructed
2141 	 */
2142 	
2143 	static
2144 	SCIP_RETCODE GUBsetCalcCliquePartition(
2145 	   SCIP*const            scip,               /**< SCIP data structure */
2146 	   SCIP_VAR**const       vars,               /**< binary variables in the clique from which at most one can be set to 1 */
2147 	   int const             nvars,              /**< number of variables in the clique */
2148 	   int*const             cliquepartition,    /**< array of length nvars to store the clique partition */
2149 	   int*const             ncliques,           /**< pointer to store number of cliques actually contained in the partition */
2150 	   SCIP_Real*            solvals             /**< solution values of all given binary variables */
2151 	   )
2152 	{
2153 	   SCIP_VAR** tmpvars;
2154 	   SCIP_VAR** cliquevars;
2155 	   SCIP_Bool* cliquevalues;
2156 	   SCIP_Bool* tmpvalues;
2157 	   int* varseq;
2158 	   int* sortkeys;
2159 	   int ncliquevars;
2160 	   int maxncliquevarscomp;
2161 	   int nignorevars;
2162 	   int nvarsused;
2163 	   int i;
2164 	
2165 	   assert(scip != NULL);
2166 	   assert(nvars == 0 || vars != NULL);
2167 	   assert(nvars == 0 || cliquepartition != NULL);
2168 	   assert(ncliques != NULL);
2169 	
2170 	   if( nvars == 0 )
2171 	   {
2172 	      *ncliques = 0;
2173 	      return SCIP_OKAY;
2174 	   }
2175 	
2176 	   /* allocate temporary memory for storing the variables of the current clique */
2177 	   SCIP_CALL( SCIPallocBufferArray(scip, &cliquevars, nvars) );
2178 	   SCIP_CALL( SCIPallocBufferArray(scip, &cliquevalues, nvars) );
2179 	   SCIP_CALL( SCIPallocBufferArray(scip, &tmpvalues, nvars) );
2180 	   SCIP_CALL( SCIPduplicateBufferArray(scip, &tmpvars, vars, nvars) );
2181 	   SCIP_CALL( SCIPallocBufferArray(scip, &varseq, nvars) );
2182 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeys, nvars) );
2183 	
2184 	   /* initialize the cliquepartition array with -1 */
2185 	   /* initialize the tmpvalues array */
2186 	   for( i = nvars - 1; i >= 0; --i )
2187 	   {
2188 	      tmpvalues[i] = TRUE;
2189 	      cliquepartition[i] = -1;
2190 	   }
2191 	
2192 	   /* get corresponding active problem variables */
2193 	   SCIP_CALL( SCIPvarsGetProbvarBinary(&tmpvars, &tmpvalues, nvars) );
2194 	
2195 	   /* ignore variables with LP value 1 (will be assigned to trivial GUBs at the end) and sort remaining variables
2196 	    * by nondecreasing number of cliques the variables are in
2197 	    */
2198 	   nignorevars = 0;
2199 	   nvarsused = 0;
2200 	   for( i = 0; i < nvars; i++ )
2201 	   {
2202 	      if( SCIPisFeasEQ(scip, solvals[i], 1.0) )
2203 	      {
2204 	         /* variables with LP value 1 are put to the end of varseq array and will not be sorted */
2205 	         varseq[nvars-1-nignorevars] = i;
2206 	         nignorevars++;
2207 	      }
2208 	      else
2209 	      {
2210 	         /* remaining variables are put to the front of varseq array and will be sorted by their number of cliques */
2211 	         varseq[nvarsused] = i;
2212 	         sortkeys[nvarsused] = SCIPvarGetNCliques(tmpvars[i], tmpvalues[i]);
2213 	         nvarsused++;
2214 	      }
2215 	   }
2216 	   assert(nvarsused + nignorevars == nvars);
2217 	
2218 	   /* sort variables with LP value less than 1 by nondecreasing order of the number of cliques they are in */
2219 	   SCIPsortIntInt(sortkeys, varseq, nvarsused);
2220 	
2221 	   maxncliquevarscomp = MIN(nvars*nvars, MAXNCLIQUEVARSCOMP);
2222 	
2223 	   /* calculate the clique partition */
2224 	   *ncliques = 0;
2225 	   for( i = 0; i < nvars; ++i )
2226 	   {
2227 	      if( cliquepartition[varseq[i]] == -1 )
2228 	      {
2229 	         int j;
2230 	
2231 	         /* variable starts a new clique */
2232 	         cliquepartition[varseq[i]] = *ncliques;
2233 	         cliquevars[0] = tmpvars[varseq[i]];
2234 	         cliquevalues[0] = tmpvalues[varseq[i]];
2235 	         ncliquevars = 1;
2236 	
2237 	         /* if variable is not active (multi-aggregated or fixed), it cannot be in any clique and
2238 	          * if the variable has LP value 1 we do not want it to be in nontrivial cliques
2239 	          */
2240 	         if( SCIPvarIsActive(tmpvars[varseq[i]]) && i < nvarsused )
2241 	         {
2242 	            /* greedily fill up the clique */
2243 	            for( j = i + 1; j < nvarsused; ++j )
2244 	            {
2245 	               /* if variable is not active (multi-aggregated or fixed), it cannot be in any clique */
2246 	               if( cliquepartition[varseq[j]] == -1 && SCIPvarIsActive(tmpvars[varseq[j]]) )
2247 	               {
2248 	                  int k;
2249 	
2250 	                  /* check if every variable in the actual clique is in clique with the new variable */
2251 	                  for( k = ncliquevars - 1; k >= 0; --k )
2252 	                  {
2253 	                     if( !SCIPvarsHaveCommonClique(tmpvars[varseq[j]], tmpvalues[varseq[j]], cliquevars[k],
2254 	                           cliquevalues[k], TRUE) )
2255 	                        break;
2256 	                  }
2257 	
2258 	                  if( k == -1 )
2259 	                  {
2260 	                     /* put the variable into the same clique */
2261 	                     cliquepartition[varseq[j]] = cliquepartition[varseq[i]];
2262 	                     cliquevars[ncliquevars] = tmpvars[varseq[j]];
2263 	                     cliquevalues[ncliquevars] = tmpvalues[varseq[j]];
2264 	                     ++ncliquevars;
2265 	                  }
2266 	               }
2267 	            }
2268 	         }
2269 	
2270 	         /* this clique is finished */
2271 	         ++(*ncliques);
2272 	      }
2273 	      assert(cliquepartition[varseq[i]] >= 0 && cliquepartition[varseq[i]] < i + 1);
2274 	
2275 	      /* break if we reached the maximal number of comparisons */
2276 	      if( i * nvars > maxncliquevarscomp )
2277 	         break;
2278 	   }
2279 	   /* if we had too many variables fill up the cliquepartition and put each variable in a separate clique */
2280 	   for( ; i < nvars; ++i )
2281 	   {
2282 	      if( cliquepartition[varseq[i]] == -1 )
2283 	      {
2284 	         cliquepartition[varseq[i]] = *ncliques;
2285 	         ++(*ncliques);
2286 	      }
2287 	   }
2288 	
2289 	   /* free temporary memory */
2290 	   SCIPfreeBufferArray(scip, &sortkeys);
2291 	   SCIPfreeBufferArray(scip, &varseq);
2292 	   SCIPfreeBufferArray(scip, &tmpvars);
2293 	   SCIPfreeBufferArray(scip, &tmpvalues);
2294 	   SCIPfreeBufferArray(scip, &cliquevalues);
2295 	   SCIPfreeBufferArray(scip, &cliquevars);
2296 	
2297 	   return SCIP_OKAY;
2298 	}
2299 	
2300 	/** constructs sophisticated partition of knapsack variables into non-overlapping GUBs; current partition uses trivial GUBs */
2301 	static
2302 	SCIP_RETCODE GUBsetGetCliquePartition(
2303 	   SCIP*                 scip,               /**< SCIP data structure */
2304 	   SCIP_GUBSET*          gubset,             /**< GUB set data structure */
2305 	   SCIP_VAR**            vars,               /**< variables in the knapsack constraint */
2306 	   SCIP_Real*            solvals             /**< solution values of all knapsack variables */
2307 	   )
2308 	{
2309 	   int* cliquepartition;
2310 	   int* gubfirstvar;
2311 	   int ncliques;
2312 	   int currentgubconsidx;
2313 	   int newgubconsidx;
2314 	   int cliqueidx;
2315 	   int nvars;
2316 	   int i;
2317 	
2318 	   assert(scip != NULL);
2319 	   assert(gubset != NULL);
2320 	   assert(vars != NULL);
2321 	
2322 	   nvars = gubset->nvars;
2323 	   assert(nvars >= 0);
2324 	
2325 	   /* allocate temporary memory for clique partition */
2326 	   SCIP_CALL( SCIPallocBufferArray(scip, &cliquepartition, nvars) );
2327 	
2328 	   /* compute sophisticated clique partition */
2329 	   SCIP_CALL( GUBsetCalcCliquePartition(scip, vars, nvars, cliquepartition, &ncliques, solvals) );
2330 	
2331 	   /* allocate temporary memory for GUB set data structure */
2332 	   SCIP_CALL( SCIPallocBufferArray(scip, &gubfirstvar, ncliques) );
2333 	
2334 	   /* translate GUB partition into GUB set data structure */
2335 	   for( i = 0; i < ncliques; i++ )
2336 	   {
2337 	      /* initialize first variable for every GUB */
2338 	      gubfirstvar[i] = -1;
2339 	   }
2340 	   /* move every knapsack variable into GUB defined by clique partition */
2341 	   for( i = 0; i < nvars; i++ )
2342 	   {
2343 	      assert(cliquepartition[i] >= 0);
2344 	
2345 	      cliqueidx = cliquepartition[i];
2346 	      currentgubconsidx = gubset->gubconssidx[i];
2347 	      assert(gubset->gubconss[currentgubconsidx]->ngubvars == 1 );
2348 	
2349 	      /* variable is first element in GUB constraint defined by clique partition */
2350 	      if( gubfirstvar[cliqueidx] == -1 )
2351 	      {
2352 	         /* corresponding GUB constraint in GUB set data structure was already constructed (as initial trivial GUB);
2353 	          * note: no assert for gubconssidx, because it can changed due to deleting empty GUBs in GUBsetMoveVar()
2354 	          */
2355 	         assert(gubset->gubvarsidx[i] == 0);
2356 	         assert(gubset->gubconss[gubset->gubconssidx[i]]->gubvars[gubset->gubvarsidx[i]] == i);
2357 	
2358 	         /* remember the first variable found for the current GUB */
2359 	         gubfirstvar[cliqueidx] = i;
2360 	      }
2361 	      /* variable is additional element of GUB constraint defined by clique partition */
2362 	      else
2363 	      {
2364 	         assert(gubfirstvar[cliqueidx] >= 0 && gubfirstvar[cliqueidx] < i);
2365 	
2366 	         /* move variable to GUB constraint defined by clique partition; index of this GUB constraint is given by the
2367 	          * first variable of this GUB constraint
2368 	          */
2369 	         newgubconsidx = gubset->gubconssidx[gubfirstvar[cliqueidx]];
2370 	         assert(newgubconsidx != currentgubconsidx); /* because initially every variable is in a different GUB */
2371 	         SCIP_CALL( GUBsetMoveVar(scip, gubset, vars, i, currentgubconsidx, newgubconsidx) );
2372 	
2373 	         assert(gubset->gubconss[gubset->gubconssidx[i]]->gubvars[gubset->gubvarsidx[i]] == i);
2374 	      }
2375 	   }
2376 	
2377 	#ifdef SCIP_DEBUG
2378 	   /* prints GUB set data structure */
2379 	   GUBsetPrint(scip, gubset, vars, solvals);
2380 	#endif
2381 	
2382 	#ifndef NDEBUG
2383 	   /* checks consistency of GUB set data structure */
2384 	   SCIP_CALL( GUBsetCheck(scip, gubset, vars) );
2385 	#endif
2386 	
2387 	   /* free temporary memory */
2388 	   SCIPfreeBufferArray(scip, &gubfirstvar);
2389 	   SCIPfreeBufferArray(scip, &cliquepartition);
2390 	
2391 	   return SCIP_OKAY;
2392 	}
2393 	
2394 	/** gets a most violated cover C (\f$\sum_{j \in C} a_j > a_0\f$) for a given knapsack constraint \f$\sum_{j \in N} a_j x_j \leq a_0\f$
2395 	 *  taking into consideration the following fixing: \f$j \in C\f$, if \f$j \in N_1 = \{j \in N : x^*_j = 1\}\f$ and
2396 	 *  \f$j \in N \setminus C\f$, if \f$j \in N_0 = \{j \in N : x^*_j = 0\}\f$, if one exists.
2397 	 */
2398 	static
2399 	SCIP_RETCODE getCover(
2400 	   SCIP*                 scip,               /**< SCIP data structure */
2401 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
2402 	   int                   nvars,              /**< number of variables in knapsack constraint */
2403 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
2404 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
2405 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
2406 	   int*                  covervars,          /**< pointer to store cover variables */
2407 	   int*                  noncovervars,       /**< pointer to store noncover variables */
2408 	   int*                  ncovervars,         /**< pointer to store number of cover variables */
2409 	   int*                  nnoncovervars,      /**< pointer to store number of noncover variables */
2410 	   SCIP_Longint*         coverweight,        /**< pointer to store weight of cover */
2411 	   SCIP_Bool*            found,              /**< pointer to store whether a cover was found */
2412 	   SCIP_Bool             modtransused,       /**< should modified transformed separation problem be used to find cover */
2413 	   int*                  ntightened,         /**< pointer to store number of variables with tightened upper bound */
2414 	   SCIP_Bool*            fractional          /**< pointer to store whether the LP sol for knapsack vars is fractional */
2415 	   )
2416 	{
2417 	   SCIP_Longint* transweights;
2418 	   SCIP_Real* transprofits;
2419 	   SCIP_Longint transcapacity;
2420 	   SCIP_Longint fixedonesweight;
2421 	   SCIP_Longint itemsweight;
2422 	   SCIP_Bool infeasible;
2423 	   int* fixedones;
2424 	   int* fixedzeros;
2425 	   int* items;
2426 	   int nfixedones;
2427 	   int nfixedzeros;
2428 	   int nitems;
2429 	   int j;
2430 	
2431 	   assert(scip != NULL);
2432 	   assert(vars != NULL);
2433 	   assert(nvars > 0);
2434 	   assert(weights != NULL);
2435 	   assert(capacity >= 0);
2436 	   assert(solvals != NULL);
2437 	   assert(covervars != NULL);
2438 	   assert(noncovervars != NULL);
2439 	   assert(ncovervars != NULL);
2440 	   assert(nnoncovervars != NULL);
2441 	   assert(coverweight != NULL);
2442 	   assert(found != NULL);
2443 	   assert(ntightened != NULL);
2444 	   assert(fractional != NULL);
2445 	
2446 	   SCIPdebugMsg(scip, "   get cover for knapsack constraint\n");
2447 	
2448 	   /* allocates temporary memory */
2449 	   SCIP_CALL( SCIPallocBufferArray(scip, &transweights, nvars) );
2450 	   SCIP_CALL( SCIPallocBufferArray(scip, &transprofits, nvars) );
2451 	   SCIP_CALL( SCIPallocBufferArray(scip, &fixedones, nvars) );
2452 	   SCIP_CALL( SCIPallocBufferArray(scip, &fixedzeros, nvars) );
2453 	   SCIP_CALL( SCIPallocBufferArray(scip, &items, nvars) );
2454 	
2455 	   *found = FALSE;
2456 	   *ncovervars = 0;
2457 	   *nnoncovervars = 0;
2458 	   *coverweight = 0;
2459 	   *fractional = TRUE;
2460 	
2461 	   /* gets the following sets
2462 	    *  N_1 = {j in N : x*_j = 1} (fixedones),
2463 	    *  N_0 = {j in N : x*_j = 0} (fixedzeros) and
2464 	    *  N\(N_0 & N_1) (items),
2465 	    * where x*_j is the solution value of variable x_j
2466 	    */
2467 	   nfixedones = 0;
2468 	   nfixedzeros = 0;
2469 	   nitems = 0;
2470 	   fixedonesweight = 0;
2471 	   itemsweight = 0;
2472 	   *ntightened = 0;
2473 	   for( j = 0; j < nvars; j++ )
2474 	   {
2475 	      assert(SCIPvarIsBinary(vars[j]));
2476 	
2477 	      /* tightens upper bound of x_j if weight of x_j is greater than capacity of knapsack */
2478 	      if( weights[j] > capacity )
2479 	      {
2480 	         SCIP_CALL( SCIPtightenVarUb(scip, vars[j], 0.0, FALSE, &infeasible, NULL) );
2481 	         assert(!infeasible);
2482 	         (*ntightened)++;
2483 	         continue;
2484 	      }
2485 	
2486 	      /* variable x_j has solution value one */
2487 	      if( SCIPisFeasEQ(scip, solvals[j], 1.0) )
2488 	      {
2489 	         fixedones[nfixedones] = j;
2490 	         nfixedones++;
2491 	         fixedonesweight += weights[j];
2492 	      }
2493 	      /* variable x_j has solution value zero */
2494 	      else if( SCIPisFeasEQ(scip, solvals[j], 0.0) )
2495 	      {
2496 	         fixedzeros[nfixedzeros] = j;
2497 	         nfixedzeros++;
2498 	      }
2499 	      /* variable x_j has fractional solution value */
2500 	      else
2501 	      {
2502 	         assert( SCIPisFeasGT(scip, solvals[j], 0.0) && SCIPisFeasLT(scip, solvals[j], 1.0) );
2503 	         items[nitems] = j;
2504 	         nitems++;
2505 	         itemsweight += weights[j];
2506 	      }
2507 	   }
2508 	   assert(nfixedones + nfixedzeros + nitems == nvars - (*ntightened));
2509 	
2510 	   /* sets whether the LP solution x* for the knapsack variables is fractional; if it is not fractional we stop
2511 	    * the separation routine
2512 	    */
2513 	   assert(nitems >= 0);
2514 	   if( nitems == 0 )
2515 	   {
2516 	      *fractional = FALSE;
2517 	      goto TERMINATE;
2518 	   }
2519 	   assert(*fractional);
2520 	
2521 	   /* transforms the traditional separation problem (under consideration of the following fixing:
2522 	    * z_j = 1 for all j in N_1, z_j = 0 for all j in N_0)
2523 	    *
2524 	    *   min sum_{j in N\(N_0 & N_1)} (1 - x*_j) z_j
2525 	    *       sum_{j in N\(N_0 & N_1)} a_j z_j >= (a_0 + 1) - sum_{j in N_1} a_j
2526 	    *                                    z_j in {0,1}, j in N\(N_0 & N_1)
2527 	    *
2528 	    * to a knapsack problem in maximization form by complementing the variables
2529 	    *
2530 	    * sum_{j in N\(N_0 & N_1)} (1 - x*_j) -
2531 	    *   max sum_{j in N\(N_0 & N_1)} (1 - x*_j) z_j
2532 	    *       sum_{j in N\(N_0 & N_1)} a_j z_j <= sum_{j in N\N_0} a_j - (a_0 + 1)
2533 	    *                                    z_j in {0,1}, j in N\(N_0 & N_1)
2534 	    */
2535 	
2536 	   /* gets weight and profit of variables in transformed knapsack problem */
2537 	   for( j = 0; j < nitems; j++ )
2538 	   {
2539 	      transweights[j] = weights[items[j]];
2540 	      transprofits[j] = 1.0 - solvals[items[j]];
2541 	   }
2542 	   /* gets capacity of transformed knapsack problem */
2543 	   transcapacity = fixedonesweight + itemsweight - capacity - 1;
2544 	
2545 	   /* if capacity of transformed knapsack problem is less than zero, there is no cover
2546 	    * (when variables fixed to zero are not used)
2547 	    */
2548 	   if( transcapacity < 0 )
2549 	   {
2550 	      assert(!(*found));
2551 	      goto TERMINATE;
2552 	   }
2553 	
2554 	   if( modtransused )
2555 	   {
2556 	      /* transforms the modified separation problem (under consideration of the following fixing:
2557 	       * z_j = 1 for all j in N_1, z_j = 0 for all j in N_0)
2558 	       *
2559 	       *   min sum_{j in N\(N_0 & N_1)} (1 - x*_j) a_j z_j
2560 	       *       sum_{j in N\(N_0 & N_1)} a_j z_j >= (a_0 + 1) - sum_{j in N_1} a_j
2561 	       *                                    z_j in {0,1}, j in N\(N_0 & N_1)
2562 	       *
2563 	       * to a knapsack problem in maximization form by complementing the variables
2564 	       *
2565 	       * sum_{j in N\(N_0 & N_1)} (1 - x*_j) a_j -
2566 	       *   max sum_{j in N\(N_0 & N_1)} (1 - x*_j) a_j z_j
2567 	       *       sum_{j in N\(N_0 & N_1)} a_j z_j <= sum_{j in N\N_0} a_j - (a_0 + 1)
2568 	       *                                    z_j in {0,1}, j in N\(N_0 & N_1)
2569 	       */
2570 	
2571 	      /* gets weight and profit of variables in modified transformed knapsack problem */
2572 	      for( j = 0; j < nitems; j++ )
2573 	      {
2574 	         transprofits[j] *= weights[items[j]];
2575 	         assert(SCIPisFeasPositive(scip, transprofits[j]));
2576 	      }
2577 	   }
2578 	
2579 	   /* solves (modified) transformed knapsack problem approximately by solving the LP-relaxation of the (modified)
2580 	    * transformed knapsack problem using Dantzig's method and rounding down the solution.
2581 	    * let z* be the solution, then
2582 	    *   j in C,          if z*_j = 0 and
2583 	    *   i in N\C,        if z*_j = 1.
2584 	    */
2585 	   SCIP_CALL( SCIPsolveKnapsackApproximately(scip, nitems, transweights, transprofits, transcapacity, items,
2586 	         noncovervars, covervars, nnoncovervars, ncovervars, NULL) );
2587 	   /*assert(checkSolveKnapsack(scip, nitems, transweights, transprofits, items, weights, solvals, modtransused));*/
2588 	
2589 	   /* constructs cover C (sum_{j in C} a_j > a_0) */
2590 	   for( j = 0; j < *ncovervars; j++ )
2591 	   {
2592 	      (*coverweight) += weights[covervars[j]];
2593 	   }
2594 	
2595 	   /* adds all variables from N_1 to C */
2596 	   for( j = 0; j < nfixedones; j++ )
2597 	   {
2598 	      covervars[*ncovervars] = fixedones[j];
2599 	      (*ncovervars)++;
2600 	      (*coverweight) += weights[fixedones[j]];
2601 	   }
2602 	
2603 	   /* adds all variables from N_0 to N\C */
2604 	   for( j = 0; j < nfixedzeros; j++ )
2605 	   {
2606 	      noncovervars[*nnoncovervars] = fixedzeros[j];
2607 	      (*nnoncovervars)++;
2608 	   }
2609 	   assert((*ncovervars) + (*nnoncovervars) == nvars - (*ntightened));
2610 	   assert((*coverweight) > capacity);
2611 	   *found = TRUE;
2612 	
2613 	 TERMINATE:
2614 	   /* frees temporary memory */
2615 	   SCIPfreeBufferArray(scip, &items);
2616 	   SCIPfreeBufferArray(scip, &fixedzeros);
2617 	   SCIPfreeBufferArray(scip, &fixedones);
2618 	   SCIPfreeBufferArray(scip, &transprofits);
2619 	   SCIPfreeBufferArray(scip, &transweights);
2620 	
2621 	   SCIPdebugMsg(scip, "   get cover for knapsack constraint -- end\n");
2622 	
2623 	   return SCIP_OKAY;
2624 	}
2625 	
2626 	#ifndef NDEBUG
2627 	/** checks if minweightidx is set correctly
2628 	 */
2629 	static
2630 	SCIP_Bool checkMinweightidx(
2631 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
2632 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
2633 	   int*                  covervars,          /**< pointer to store cover variables */
2634 	   int                   ncovervars,         /**< pointer to store number of cover variables */
2635 	   SCIP_Longint          coverweight,        /**< pointer to store weight of cover */
2636 	   int                   minweightidx,       /**< index of variable in cover variables with minimum weight */
2637 	   int                   j                   /**< current index in cover variables */
2638 	   )
2639 	{
2640 	   SCIP_Longint minweight;
2641 	   int i;
2642 	
2643 	   assert(weights != NULL);
2644 	   assert(covervars != NULL);
2645 	   assert(ncovervars > 0);
2646 	
2647 	   minweight = weights[covervars[minweightidx]];
2648 	
2649 	   /* checks if all cover variables before index j have weight greater than minweight */
2650 	   for( i = 0; i < j; i++ )
2651 	   {
2652 	      assert(weights[covervars[i]] > minweight);
2653 	      if( weights[covervars[i]] <= minweight )
2654 	         return FALSE;
2655 	   }
2656 	
2657 	   /* checks if all variables before index j cannot be removed, i.e. i cannot be the next minweightidx */
2658 	   for( i = 0; i < j; i++ )
2659 	   {
2660 	      assert(coverweight - weights[covervars[i]] <= capacity);
2661 	      if( coverweight - weights[covervars[i]] > capacity )
2662 	         return FALSE;
2663 	   }
2664 	   return TRUE;
2665 	}
2666 	#endif
2667 	
2668 	
2669 	/** gets partition \f$(C_1,C_2)\f$ of minimal cover \f$C\f$, i.e. \f$C_1 \cup C_2 = C\f$ and \f$C_1 \cap C_2 = \emptyset\f$,
2670 	 *  with \f$C_1\f$ not empty; chooses partition as follows \f$C_2 = \{ j \in C : x^*_j = 1 \}\f$ and \f$C_1 = C \setminus C_2\f$
2671 	 */
2672 	static
2673 	void getPartitionCovervars(
2674 	   SCIP*                 scip,               /**< SCIP data structure */
2675 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
2676 	   int*                  covervars,          /**< cover variables */
2677 	   int                   ncovervars,         /**< number of cover variables */
2678 	   int*                  varsC1,             /**< pointer to store variables in C1 */
2679 	   int*                  varsC2,             /**< pointer to store variables in C2 */
2680 	   int*                  nvarsC1,            /**< pointer to store number of variables in C1 */
2681 	   int*                  nvarsC2             /**< pointer to store number of variables in C2 */
2682 	   )
2683 	{
2684 	   int j;
2685 	
2686 	   assert(scip != NULL);
2687 	   assert(ncovervars >= 0);
2688 	   assert(solvals != NULL);
2689 	   assert(covervars != NULL);
2690 	   assert(varsC1 != NULL);
2691 	   assert(varsC2 != NULL);
2692 	   assert(nvarsC1 != NULL);
2693 	   assert(nvarsC2 != NULL);
2694 	
2695 	   *nvarsC1 = 0;
2696 	   *nvarsC2 = 0;
2697 	   for( j = 0; j < ncovervars; j++ )
2698 	   {
2699 	      assert(SCIPisFeasGT(scip, solvals[covervars[j]], 0.0));
2700 	
2701 	      /* variable has solution value one */
2702 	      if( SCIPisGE(scip, solvals[covervars[j]], 1.0) )
2703 	      {
2704 	         varsC2[*nvarsC2] = covervars[j];
2705 	         (*nvarsC2)++;
2706 	      }
2707 	      /* variable has solution value less than one */
2708 	      else
2709 	      {
2710 	         assert(SCIPisLT(scip, solvals[covervars[j]], 1.0));
2711 	         varsC1[*nvarsC1] = covervars[j];
2712 	         (*nvarsC1)++;
2713 	      }
2714 	   }
2715 	   assert((*nvarsC1) + (*nvarsC2) == ncovervars);
2716 	}
2717 	
2718 	/** changes given partition (C_1,C_2) of minimal cover C, if |C1| = 1, by moving one and two (if possible) variables from
2719 	 *  C2 to C1 if |C1| = 1 and |C1| = 0, respectively.
2720 	 */
2721 	static
2722 	SCIP_RETCODE changePartitionCovervars(
2723 	   SCIP*                 scip,               /**< SCIP data structure */
2724 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
2725 	   int*                  varsC1,             /**< pointer to store variables in C1 */
2726 	   int*                  varsC2,             /**< pointer to store variables in C2 */
2727 	   int*                  nvarsC1,            /**< pointer to store number of variables in C1 */
2728 	   int*                  nvarsC2             /**< pointer to store number of variables in C2 */
2729 	   )
2730 	{
2731 	   SCIP_Real* sortkeysC2;
2732 	   int j;
2733 	
2734 	   assert(*nvarsC1 >= 0 && *nvarsC1 <= 1);
2735 	   assert(*nvarsC2 > 0);
2736 	
2737 	   /* allocates temporary memory */
2738 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeysC2, *nvarsC2) );
2739 	
2740 	   /* sorts variables in C2 such that a_1 >= .... >= a_|C2| */
2741 	   for( j = 0; j < *nvarsC2; j++ )
2742 	      sortkeysC2[j] = (SCIP_Real) weights[varsC2[j]];
2743 	   SCIPsortDownRealInt(sortkeysC2, varsC2, *nvarsC2);
2744 	
2745 	   /* adds one or two variable from C2 with smallest weight to C1 and removes them from C2 */
2746 	   assert(*nvarsC2 == 1 || weights[varsC2[(*nvarsC2)-1]] <= weights[varsC2[(*nvarsC2)-2]]);
2747 	   while( *nvarsC1 < 2 && *nvarsC2 > 0 )
2748 	   {
2749 	      varsC1[*nvarsC1] = varsC2[(*nvarsC2)-1];
2750 	      (*nvarsC1)++;
2751 	      (*nvarsC2)--;
2752 	   }
2753 	
2754 	   /* frees temporary memory */
2755 	   SCIPfreeBufferArray(scip, &sortkeysC2);
2756 	
2757 	   return SCIP_OKAY;
2758 	}
2759 	
2760 	/** changes given partition (C_1,C_2) of feasible set C, if |C1| = 1, by moving one variable from C2 to C1 */
2761 	static
2762 	SCIP_RETCODE changePartitionFeasiblesetvars(
2763 	   SCIP*                 scip,               /**< SCIP data structure */
2764 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
2765 	   int*                  varsC1,             /**< pointer to store variables in C1 */
2766 	   int*                  varsC2,             /**< pointer to store variables in C2 */
2767 	   int*                  nvarsC1,            /**< pointer to store number of variables in C1 */
2768 	   int*                  nvarsC2             /**< pointer to store number of variables in C2 */
2769 	   )
2770 	{
2771 	   SCIP_Real* sortkeysC2;
2772 	   int j;
2773 	
2774 	   assert(*nvarsC1 >= 0 && *nvarsC1 <= 1);
2775 	   assert(*nvarsC2 > 0);
2776 	
2777 	   /* allocates temporary memory */
2778 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeysC2, *nvarsC2) );
2779 	
2780 	   /* sorts variables in C2 such that a_1 >= .... >= a_|C2| */
2781 	   for( j = 0; j < *nvarsC2; j++ )
2782 	      sortkeysC2[j] = (SCIP_Real) weights[varsC2[j]];
2783 	   SCIPsortDownRealInt(sortkeysC2, varsC2, *nvarsC2);
2784 	
2785 	   /* adds variable from C2 with smallest weight to C1 and removes it from C2 */
2786 	   assert(*nvarsC2 == 1 || weights[varsC2[(*nvarsC2)-1]] <= weights[varsC2[(*nvarsC2)-2]]);
2787 	   varsC1[*nvarsC1] = varsC2[(*nvarsC2)-1];
2788 	   (*nvarsC1)++;
2789 	   (*nvarsC2)--;
2790 	
2791 	   /* frees temporary memory */
2792 	   SCIPfreeBufferArray(scip, &sortkeysC2);
2793 	
2794 	   return SCIP_OKAY;
2795 	}
2796 	
2797 	
2798 	/** gets partition \f$(F,R)\f$ of \f$N \setminus C\f$ where \f$C\f$ is a minimal cover, i.e. \f$F \cup R = N \setminus C\f$
2799 	 *  and \f$F \cap R = \emptyset\f$; chooses partition as follows \f$R = \{ j \in N \setminus C : x^*_j = 0 \}\f$ and
2800 	 *  \f$F = (N \setminus C) \setminus F\f$
2801 	 */
2802 	static
2803 	void getPartitionNoncovervars(
2804 	   SCIP*                 scip,               /**< SCIP data structure */
2805 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
2806 	   int*                  noncovervars,       /**< noncover variables */
2807 	   int                   nnoncovervars,      /**< number of noncover variables */
2808 	   int*                  varsF,              /**< pointer to store variables in F */
2809 	   int*                  varsR,              /**< pointer to store variables in R */
2810 	   int*                  nvarsF,             /**< pointer to store number of variables in F */
2811 	   int*                  nvarsR              /**< pointer to store number of variables in R */
2812 	   )
2813 	{
2814 	   int j;
2815 	
2816 	   assert(scip != NULL);
2817 	   assert(nnoncovervars >= 0);
2818 	   assert(solvals != NULL);
2819 	   assert(noncovervars != NULL);
2820 	   assert(varsF != NULL);
2821 	   assert(varsR != NULL);
2822 	   assert(nvarsF != NULL);
2823 	   assert(nvarsR != NULL);
2824 	
2825 	   *nvarsF = 0;
2826 	   *nvarsR = 0;
2827 	
2828 	   for( j = 0; j < nnoncovervars; j++ )
2829 	   {
2830 	      /* variable has solution value zero */
2831 	      if( SCIPisFeasEQ(scip, solvals[noncovervars[j]], 0.0) )
2832 	      {
2833 	         varsR[*nvarsR] = noncovervars[j];
2834 	         (*nvarsR)++;
2835 	      }
2836 	      /* variable has solution value greater than zero */
2837 	      else
2838 	      {
2839 	         assert(SCIPisFeasGT(scip, solvals[noncovervars[j]], 0.0));
2840 	         varsF[*nvarsF] = noncovervars[j];
2841 	         (*nvarsF)++;
2842 	      }
2843 	   }
2844 	   assert((*nvarsF) + (*nvarsR) == nnoncovervars);
2845 	}
2846 	
2847 	/** sorts variables in F, C_2, and R according to the second level lifting sequence that will be used in the sequential
2848 	 *  lifting procedure
2849 	 */
2850 	static
2851 	SCIP_RETCODE getLiftingSequence(
2852 	   SCIP*                 scip,               /**< SCIP data structure */
2853 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
2854 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
2855 	   int*                  varsF,              /**< pointer to store variables in F */
2856 	   int*                  varsC2,             /**< pointer to store variables in C2 */
2857 	   int*                  varsR,              /**< pointer to store variables in R */
2858 	   int                   nvarsF,             /**< number of variables in F */
2859 	   int                   nvarsC2,            /**< number of variables in C2 */
2860 	   int                   nvarsR              /**< number of variables in R */
2861 	   )
2862 	{
2863 	   SORTKEYPAIR** sortkeypairsF;
2864 	   SORTKEYPAIR* sortkeypairsFstore;
2865 	   SCIP_Real* sortkeysC2;
2866 	   SCIP_Real* sortkeysR;
2867 	   int j;
2868 	
2869 	   assert(scip != NULL);
2870 	   assert(solvals != NULL);
2871 	   assert(weights != NULL);
2872 	   assert(varsF != NULL);
2873 	   assert(varsC2 != NULL);
2874 	   assert(varsR != NULL);
2875 	   assert(nvarsF >= 0);
2876 	   assert(nvarsC2 >= 0);
2877 	   assert(nvarsR >= 0);
2878 	
2879 	   /* allocates temporary memory */
2880 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeypairsF, nvarsF) );
2881 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeypairsFstore, nvarsF) );
2882 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeysC2, nvarsC2) );
2883 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeysR, nvarsR) );
2884 	
2885 	   /* gets sorting key for variables in F corresponding to the following lifting sequence
2886 	    *  sequence 1: non-increasing absolute difference between x*_j and the value the variable is fixed to, i.e.
2887 	    *              x*_1 >= x*_2 >= ... >= x*_|F|
2888 	    * in case of equality uses
2889 	    *  sequence 4: non-increasing a_j, i.e. a_1 >= a_2 >= ... >= a_|C_2|
2890 	    */
2891 	   for( j = 0; j < nvarsF; j++ )
2892 	   {
2893 	      sortkeypairsF[j] = &(sortkeypairsFstore[j]);
2894 	      sortkeypairsF[j]->key1 = solvals[varsF[j]];
2895 	      sortkeypairsF[j]->key2 = (SCIP_Real) weights[varsF[j]];
2896 	   }
2897 	
2898 	   /* gets sorting key for variables in C_2 corresponding to the following lifting sequence
2899 	    *  sequence 4: non-increasing a_j, i.e. a_1 >= a_2 >= ... >= a_|C_2|
2900 	    */
2901 	   for( j = 0; j < nvarsC2; j++ )
2902 	      sortkeysC2[j] = (SCIP_Real) weights[varsC2[j]];
2903 	
2904 	   /* gets sorting key for variables in R corresponding to the following lifting sequence
2905 	    *  sequence 4: non-increasing a_j, i.e. a_1 >= a_2 >= ... >= a_|R|
2906 	    */
2907 	   for( j = 0; j < nvarsR; j++ )
2908 	      sortkeysR[j] = (SCIP_Real) weights[varsR[j]];
2909 	
2910 	   /* sorts F, C2 and R */
2911 	   if( nvarsF > 0 )
2912 	   {
2913 	      SCIPsortDownPtrInt((void**)sortkeypairsF, varsF, compSortkeypairs, nvarsF);
2914 	   }
2915 	   if( nvarsC2 > 0 )
2916 	   {
2917 	      SCIPsortDownRealInt(sortkeysC2, varsC2, nvarsC2);
2918 	   }
2919 	   if( nvarsR > 0)
2920 	   {
2921 	      SCIPsortDownRealInt(sortkeysR, varsR, nvarsR);
2922 	   }
2923 	
2924 	   /* frees temporary memory */
2925 	   SCIPfreeBufferArray(scip, &sortkeysR);
2926 	   SCIPfreeBufferArray(scip, &sortkeysC2);
2927 	   SCIPfreeBufferArray(scip, &sortkeypairsFstore);
2928 	   SCIPfreeBufferArray(scip, &sortkeypairsF);
2929 	
2930 	   return SCIP_OKAY;
2931 	}
2932 	
2933 	/** categorizes GUBs of knapsack GUB partion into GOC1, GNC1, GF, GC2, and GR and computes a lifting sequence of the GUBs
2934 	 *  for the sequential GUB wise lifting procedure
2935 	 */
2936 	static
2937 	SCIP_RETCODE getLiftingSequenceGUB(
2938 	   SCIP*                 scip,               /**< SCIP data structure */
2939 	   SCIP_GUBSET*          gubset,             /**< GUB set data structure */
2940 	   SCIP_Real*            solvals,            /**< solution values of variables in knapsack constraint */
2941 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
2942 	   int*                  varsC1,             /**< variables in C1 */
2943 	   int*                  varsC2,             /**< variables in C2 */
2944 	   int*                  varsF,              /**< variables in F */
2945 	   int*                  varsR,              /**< variables in R */
2946 	   int                   nvarsC1,            /**< number of variables in C1 */
2947 	   int                   nvarsC2,            /**< number of variables in C2 */
2948 	   int                   nvarsF,             /**< number of variables in F */
2949 	   int                   nvarsR,             /**< number of variables in R */
2950 	   int*                  gubconsGC1,         /**< pointer to store GUBs in GC1(GNC1+GOC1) */
2951 	   int*                  gubconsGC2,         /**< pointer to store GUBs in GC2 */
2952 	   int*                  gubconsGFC1,        /**< pointer to store GUBs in GFC1(GNC1+GF) */
2953 	   int*                  gubconsGR,          /**< pointer to store GUBs in GR */
2954 	   int*                  ngubconsGC1,        /**< pointer to store number of GUBs in GC1(GNC1+GOC1) */
2955 	   int*                  ngubconsGC2,        /**< pointer to store number of GUBs in GC2 */
2956 	   int*                  ngubconsGFC1,       /**< pointer to store number of GUBs in GFC1(GNC1+GF) */
2957 	   int*                  ngubconsGR,         /**< pointer to store number of GUBs in GR */
2958 	   int*                  ngubconscapexceed,  /**< pointer to store number of GUBs with only capacity exceeding variables */
2959 	   int*                  maxgubvarssize      /**< pointer to store the maximal size of GUB constraints */
2960 	   )
2961 	{
2962 	   SORTKEYPAIR** sortkeypairsGFC1;
2963 	   SORTKEYPAIR* sortkeypairsGFC1store;
2964 	   SCIP_Real* sortkeysC1;
2965 	   SCIP_Real* sortkeysC2;
2966 	   SCIP_Real* sortkeysR;
2967 	   int* nC1varsingubcons;
2968 	   int var;
2969 	   int gubconsidx;
2970 	   int varidx;
2971 	   int ngubconss;
2972 	   int ngubconsGOC1;
2973 	   int targetvar;
2974 	#ifndef NDEBUG
2975 	   int nvarsprocessed = 0;
2976 	#endif
2977 	   int i;
2978 	   int j;
2979 	
2980 	#if GUBSPLITGNC1GUBS
2981 	   SCIP_Bool gubconswithF;
2982 	   int origngubconss;
2983 	   origngubconss = gubset->ngubconss;
2984 	#endif
2985 	
2986 	   assert(scip != NULL);
2987 	   assert(gubset != NULL);
2988 	   assert(solvals != NULL);
2989 	   assert(weights != NULL);
2990 	   assert(varsC1 != NULL);
2991 	   assert(varsC2 != NULL);
2992 	   assert(varsF != NULL);
2993 	   assert(varsR != NULL);
2994 	   assert(nvarsC1 > 0);
2995 	   assert(nvarsC2 >= 0);
2996 	   assert(nvarsF >= 0);
2997 	   assert(nvarsR >= 0);
2998 	   assert(gubconsGC1 != NULL);
2999 	   assert(gubconsGC2 != NULL);
3000 	   assert(gubconsGFC1 != NULL);
3001 	   assert(gubconsGR != NULL);
3002 	   assert(ngubconsGC1 != NULL);
3003 	   assert(ngubconsGC2 != NULL);
3004 	   assert(ngubconsGFC1 != NULL);
3005 	   assert(ngubconsGR != NULL);
3006 	   assert(maxgubvarssize != NULL);
3007 	
3008 	   ngubconss = gubset->ngubconss;
3009 	   ngubconsGOC1 = 0;
3010 	
3011 	   /* GUBs are categorized into different types according to the variables in volved
3012 	    * - GOC1:  involves variables in C1 only           -- no C2, R, F
3013 	    * - GNC1:  involves variables in C1 and F (and R)  -- no C2
3014 	    * - GF:    involves variables in F  (and R) only   -- no C1, C2
3015 	    * - GC2:   involves variables in C2 only           -- no C1, R, F
3016 	    * - GR:    involves variables in R  only           -- no C1, C2, F
3017 	    * which requires splitting GUBs in case they include variable in F and R.
3018 	    *
3019 	    * afterwards all GUBs (except GOC1 GUBs, which we do not need to lift) are sorted by a two level lifting sequence.
3020 	    * - first  ordering level is: GFC1 (GNC1+GF), GC2, and GR.
3021 	    * - second ordering level is
3022 	    *    GFC1:   non-increasing number of variables in F and non-increasing max{x*_k : k in GFC1_j} in case of equality
3023 	    *    GC2:    non-increasing max{ a_k : k in GC2_j}; note that |GFC2_j| = 1
3024 	    *    GR:     non-increasing max{ a_k : k in GR_j}
3025 	    *
3026 	    * in additon, another GUB union, which is helpful for the lifting procedure, is formed
3027 	    * - GC1:   GUBs of category GOC1 and GNC1
3028 	    * with second ordering level non-decreasing min{ a_k : k in GC1_j };
3029 	    * note that min{ a_k : k in GC1_j } always comes from the first variable in the GUB
3030 	    */
3031 	
3032 	   /* allocates temporary memory */
3033 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeysC1, nvarsC1) );
3034 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeysC2, nvarsC2) );
3035 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeysR, nvarsR) );
3036 	
3037 	   /* to get the GUB lifting sequence, we first sort all variables in F, C2, and R
3038 	    * - F:      non-increasing x*_j and non-increasing a_j in case of equality
3039 	    * - C2:     non-increasing a_j
3040 	    * - R:      non-increasing a_j
3041 	    * furthermore, sort C1 variables as needed for initializing the minweight table (non-increasing a_j).
3042 	    */
3043 	
3044 	   /* gets sorting key for variables in C1 corresponding to the following ordering
3045 	    *  non-decreasing a_j, i.e. a_1 <= a_2 <= ... <= a_|C_1|
3046 	    */
3047 	   for( j = 0; j < nvarsC1; j++ )
3048 	   {
3049 	      /* gets sortkeys */
3050 	      sortkeysC1[j] = (SCIP_Real) weights[varsC1[j]];
3051 	
3052 	      /* update status of variable in its gub constraint */
3053 	      gubconsidx = gubset->gubconssidx[varsC1[j]];
3054 	      varidx = gubset->gubvarsidx[varsC1[j]];
3055 	      gubset->gubconss[gubconsidx]->gubvarsstatus[varidx] = GUBVARSTATUS_BELONGSTOSET_C1;
3056 	   }
3057 	
3058 	   /* gets sorting key for variables in F corresponding to the following ordering
3059 	    *  non-increasing x*_j, i.e., x*_1 >= x*_2 >= ... >= x*_|F|, and
3060 	    *  non-increasing a_j,  i.e., a_1  >= a_2  >= ... >= a_|F| in case of equality
3061 	    * and updates status of each variable in F in GUB set data structure
3062 	    */
3063 	   for( j = 0; j < nvarsF; j++ )
3064 	   {
3065 	      /* update status of variable in its gub constraint */
3066 	      gubconsidx = gubset->gubconssidx[varsF[j]];
3067 	      varidx = gubset->gubvarsidx[varsF[j]];
3068 	      gubset->gubconss[gubconsidx]->gubvarsstatus[varidx] = GUBVARSTATUS_BELONGSTOSET_F;
3069 	   }
3070 	
3071 	   /* gets sorting key for variables in C2 corresponding to the following ordering
3072 	    *  non-increasing a_j,  i.e., a_1  >= a_2  >= ... >= a_|C2|
3073 	    * and updates status of each variable in F in GUB set data structure
3074 	    */
3075 	   for( j = 0; j < nvarsC2; j++ )
3076 	   {
3077 	      /* gets sortkeys */
3078 	      sortkeysC2[j] = (SCIP_Real) weights[varsC2[j]];
3079 	
3080 	      /* update status of variable in its gub constraint */
3081 	      gubconsidx = gubset->gubconssidx[varsC2[j]];
3082 	      varidx = gubset->gubvarsidx[varsC2[j]];
3083 	      gubset->gubconss[gubconsidx]->gubvarsstatus[varidx] = GUBVARSTATUS_BELONGSTOSET_C2;
3084 	   }
3085 	
3086 	   /* gets sorting key for variables in R corresponding to the following ordering
3087 	    *  non-increasing a_j,  i.e., a_1  >= a_2  >= ... >= a_|R|
3088 	    * and updates status of each variable in F in GUB set data structure
3089 	    */
3090 	   for( j = 0; j < nvarsR; j++ )
3091 	   {
3092 	      /* gets sortkeys */
3093 	      sortkeysR[j] = (SCIP_Real) weights[varsR[j]];
3094 	
3095 	      /* update status of variable in its gub constraint */
3096 	      gubconsidx = gubset->gubconssidx[varsR[j]];
3097 	      varidx = gubset->gubvarsidx[varsR[j]];
3098 	      gubset->gubconss[gubconsidx]->gubvarsstatus[varidx] = GUBVARSTATUS_BELONGSTOSET_R;
3099 	   }
3100 	
3101 	   /* sorts C1, F, C2 and R */
3102 	   assert(nvarsC1 > 0);
3103 	   SCIPsortRealInt(sortkeysC1, varsC1, nvarsC1);
3104 	
3105 	   if( nvarsC2 > 0 )
3106 	   {
3107 	      SCIPsortDownRealInt(sortkeysC2, varsC2, nvarsC2);
3108 	   }
3109 	   if( nvarsR > 0)
3110 	   {
3111 	      SCIPsortDownRealInt(sortkeysR, varsR, nvarsR);
3112 	   }
3113 	
3114 	   /* frees temporary memory */
3115 	   SCIPfreeBufferArray(scip, &sortkeysR);
3116 	   SCIPfreeBufferArray(scip, &sortkeysC2);
3117 	   SCIPfreeBufferArray(scip, &sortkeysC1);
3118 	
3119 	   /* allocate and initialize temporary memory for sorting GUB constraints */
3120 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeypairsGFC1, ngubconss) );
3121 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeypairsGFC1store, ngubconss) );
3122 	   SCIP_CALL( SCIPallocBufferArray(scip, &nC1varsingubcons, ngubconss) );
3123 	   BMSclearMemoryArray(nC1varsingubcons, ngubconss);
3124 	   for( i = 0; i < ngubconss; i++)
3125 	   {
3126 	      sortkeypairsGFC1[i] = &(sortkeypairsGFC1store[i]);
3127 	      sortkeypairsGFC1[i]->key1 = 0.0;
3128 	      sortkeypairsGFC1[i]->key2 = 0.0;
3129 	   }
3130 	   *ngubconsGC1 = 0;
3131 	   *ngubconsGC2 = 0;
3132 	   *ngubconsGFC1 = 0;
3133 	   *ngubconsGR = 0;
3134 	   *ngubconscapexceed = 0;
3135 	   *maxgubvarssize = 0;
3136 	
3137 	#ifndef NDEBUG
3138 	   for( i = 0; i < gubset->ngubconss; i++ )
3139 	      assert(gubset->gubconsstatus[i] == GUBCONSSTATUS_UNINITIAL);
3140 	#endif
3141 	
3142 	   /* stores GUBs of group GC1 (GOC1+GNC1) and part of the GUBs of group GFC1 (GNC1 GUBs) and sorts variables in these GUBs
3143 	    * s.t. C1 variables come first (will automatically be sorted by non-decreasing weight).
3144 	    * gets sorting keys for GUBs of type GFC1 corresponding to the following ordering
3145 	    *    non-increasing number of variables in F, and
3146 	    *    non-increasing max{x*_k : k in GFC1_j} in case of equality
3147 	    */
3148 	   for( i = 0; i < nvarsC1; i++ )
3149 	   {
3150 	      int nvarsC1capexceed;
3151 	
3152 	      nvarsC1capexceed = 0;
3153 	
3154 	      var = varsC1[i];
3155 	      gubconsidx = gubset->gubconssidx[var];
3156 	      varidx = gubset->gubvarsidx[var];
3157 	
3158 	      assert(gubconsidx >= 0 && gubconsidx < ngubconss);
3159 	      assert(gubset->gubconss[gubconsidx]->gubvarsstatus[varidx] == GUBVARSTATUS_BELONGSTOSET_C1);
3160 	
3161 	      /* current C1 variable is put to the front of its GUB where C1 part is stored by non-decreasing weigth;
3162 	       * note that variables in C1 are already sorted by non-decreasing weigth
3163 	       */
3164 	      targetvar = gubset->gubconss[gubconsidx]->gubvars[nC1varsingubcons[gubconsidx]];
3165 	      GUBsetSwapVars(scip, gubset, var, targetvar);
3166 	      nC1varsingubcons[gubconsidx]++;
3167 	
3168 	      /* the GUB was already handled (status set and stored in its group) by another variable of the GUB */
3169 	      if( gubset->gubconsstatus[gubconsidx] != GUBCONSSTATUS_UNINITIAL )
3170 	      {
3171 	         assert(gubset->gubconsstatus[gubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GOC1
3172 	            || gubset->gubconsstatus[gubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GNC1);
3173 	         continue;
3174 	      }
3175 	
3176 	      /* determine the status of the current GUB constraint, GOC1 or GNC1; GUBs involving R variables are split into
3177 	       * GOC1/GNC1 and GF, if wanted. also update sorting key if GUB is of type GFC1 (GNC1)
3178 	       */
3179 	#if GUBSPLITGNC1GUBS
3180 	      gubconswithF = FALSE;
3181 	#endif
3182 	      for( j = 0; j < gubset->gubconss[gubconsidx]->ngubvars; j++ )
3183 	      {
3184 	         assert(gubset->gubconss[gubconsidx]->gubvarsstatus[j] != GUBVARSTATUS_BELONGSTOSET_C2);
3185 	
3186 	         /* C1-variable: update number of C1/capacity exceeding variables */
3187 	         if( gubset->gubconss[gubconsidx]->gubvarsstatus[j] == GUBVARSTATUS_BELONGSTOSET_C1 )
3188 	         {
3189 	            nvarsC1capexceed++;
3190 	#ifndef NDEBUG
3191 	            nvarsprocessed++;
3192 	#endif
3193 	         }
3194 	         /* F-variable: update sort key (number of F variables in GUB) of corresponding GFC1-GUB */
3195 	         else if( gubset->gubconss[gubconsidx]->gubvarsstatus[j] == GUBVARSTATUS_BELONGSTOSET_F )
3196 	         {
3197 	#if GUBSPLITGNC1GUBS
3198 		    gubconswithF = TRUE;
3199 	#endif
3200 		    sortkeypairsGFC1[*ngubconsGFC1]->key1 += 1.0;
3201 	
3202 	            if( solvals[gubset->gubconss[gubconsidx]->gubvars[j]] > sortkeypairsGFC1[*ngubconsGFC1]->key2 )
3203 	               sortkeypairsGFC1[*ngubconsGFC1]->key2 = solvals[gubset->gubconss[gubconsidx]->gubvars[j]];
3204 	         }
3205 	         else if( gubset->gubconss[gubconsidx]->gubvarsstatus[j] == GUBVARSTATUS_CAPACITYEXCEEDED )
3206 	         {
3207 	            nvarsC1capexceed++;
3208 	         }
3209 	         else
3210 	            assert(gubset->gubconss[gubconsidx]->gubvarsstatus[j] == GUBVARSTATUS_BELONGSTOSET_R);
3211 	      }
3212 	
3213 	      /* update set of GC1 GUBs */
3214 	      gubconsGC1[*ngubconsGC1] = gubconsidx;
3215 	      (*ngubconsGC1)++;
3216 	
3217 	      /* update maximum size of all GUB constraints */
3218 	      if( gubset->gubconss[gubconsidx]->gubvarssize > *maxgubvarssize )
3219 		 *maxgubvarssize = gubset->gubconss[gubconsidx]->gubvarssize;
3220 	
3221 	      /* set status of GC1-GUB (GOC1 or GNC1) and update set of GFC1 GUBs */
3222 	      if( nvarsC1capexceed == gubset->gubconss[gubconsidx]->ngubvars )
3223 	      {
3224 	         gubset->gubconsstatus[gubconsidx] = GUBCONSSTATUS_BELONGSTOSET_GOC1;
3225 		 ngubconsGOC1++;
3226 	      }
3227 	      else
3228 	      {
3229 	#if GUBSPLITGNC1GUBS
3230 	         /* only variables in C1 and R -- no in F: GUB will be split into GR and GOC1 GUBs */
3231 		 if( !gubconswithF )
3232 		 {
3233 		    GUBVARSTATUS movevarstatus;
3234 	
3235 		    assert(gubset->ngubconss < gubset->nvars);
3236 	
3237 	            /* create a new GUB for GR part of splitting */
3238 		    SCIP_CALL( GUBconsCreate(scip, &gubset->gubconss[gubset->ngubconss]) );
3239 		    gubset->ngubconss++;
3240 		    ngubconss = gubset->ngubconss;
3241 	
3242 	            /* fill GR with R variables in current GUB */
3243 		    for( j = gubset->gubconss[gubconsidx]->ngubvars-1; j >= 0; j-- )
3244 		    {
3245 		        movevarstatus = gubset->gubconss[gubconsidx]->gubvarsstatus[j];
3246 			if( movevarstatus != GUBVARSTATUS_BELONGSTOSET_C1 )
3247 			{
3248 			   assert(movevarstatus == GUBVARSTATUS_BELONGSTOSET_R || movevarstatus == GUBVARSTATUS_CAPACITYEXCEEDED);
3249 			   SCIP_CALL( GUBsetMoveVar(scip, gubset, vars, gubset->gubconss[gubconsidx]->gubvars[j],
3250 	                         gubconsidx, ngubconss-1) );
3251 			   gubset->gubconss[ngubconss-1]->gubvarsstatus[gubset->gubconss[ngubconss-1]->ngubvars-1] =
3252 	                      movevarstatus;
3253 			}
3254 		    }
3255 	
3256 		    gubset->gubconsstatus[gubconsidx] = GUBCONSSTATUS_BELONGSTOSET_GOC1;
3257 		    ngubconsGOC1++;
3258 	
3259 		    gubset->gubconsstatus[ngubconss-1] = GUBCONSSTATUS_BELONGSTOSET_GR;
3260 		    gubconsGR[*ngubconsGR] = ngubconss-1;
3261 		    (*ngubconsGR)++;
3262 		 }
3263 	         /* variables in C1, F, and maybe R: GNC1 GUB */
3264 		 else
3265 		 {
3266 		    assert(gubconswithF);
3267 	
3268 		    gubset->gubconsstatus[gubconsidx] = GUBCONSSTATUS_BELONGSTOSET_GNC1;
3269 		    gubconsGFC1[*ngubconsGFC1] = gubconsidx;
3270 		    (*ngubconsGFC1)++;
3271 		 }
3272 	#else
3273 		 gubset->gubconsstatus[gubconsidx] = GUBCONSSTATUS_BELONGSTOSET_GNC1;
3274 		 gubconsGFC1[*ngubconsGFC1] = gubconsidx;
3275 		 (*ngubconsGFC1)++;
3276 	#endif
3277 	      }
3278 	   }
3279 	
3280 	   /* stores GUBs of group GC2 (only trivial GUBs); sorting is not required because the C2 variables (which we loop over)
3281 	    * are already sorted correctly
3282 	    */
3283 	   for( i = 0; i < nvarsC2; i++ )
3284 	   {
3285 	      var = varsC2[i];
3286 	      gubconsidx = gubset->gubconssidx[var];
3287 	      varidx = gubset->gubvarsidx[var];
3288 	
3289 	      assert(gubconsidx >= 0 && gubconsidx < ngubconss);
3290 	      assert(gubset->gubconss[gubconsidx]->ngubvars == 1);
3291 	      assert(varidx == 0);
3292 	      assert(gubset->gubconss[gubconsidx]->gubvarsstatus[varidx] == GUBVARSTATUS_BELONGSTOSET_C2);
3293 	      assert(gubset->gubconsstatus[gubconsidx] == GUBCONSSTATUS_UNINITIAL);
3294 	
3295 	      /* set status of GC2 GUB */
3296 	      gubset->gubconsstatus[gubconsidx] = GUBCONSSTATUS_BELONGSTOSET_GC2;
3297 	
3298 	      /* update group of GC2 GUBs */
3299 	      gubconsGC2[*ngubconsGC2] = gubconsidx;
3300 	      (*ngubconsGC2)++;
3301 	
3302 	      /* update maximum size of all GUB constraints */
3303 	      if( gubset->gubconss[gubconsidx]->gubvarssize > *maxgubvarssize )
3304 		 *maxgubvarssize = gubset->gubconss[gubconsidx]->gubvarssize;
3305 	
3306 	#ifndef NDEBUG
3307 	      nvarsprocessed++;
3308 	#endif
3309 	   }
3310 	
3311 	   /* stores remaining part of the GUBs of group GFC1 (GF GUBs) and gets GUB sorting keys corresp. to following ordering
3312 	    *    non-increasing number of variables in F, and
3313 	    *    non-increasing max{x*_k : k in GFC1_j} in case of equality
3314 	    */
3315 	   for( i = 0; i < nvarsF; i++ )
3316 	   {
3317 	      var = varsF[i];
3318 	      gubconsidx = gubset->gubconssidx[var];
3319 	      varidx = gubset->gubvarsidx[var];
3320 	
3321 	      assert(gubconsidx >= 0 && gubconsidx < ngubconss);
3322 	      assert(gubset->gubconss[gubconsidx]->gubvarsstatus[varidx] == GUBVARSTATUS_BELONGSTOSET_F);
3323 	
3324 	#ifndef NDEBUG
3325 	      nvarsprocessed++;
3326 	#endif
3327 	
3328 	      /* the GUB was already handled (status set and stored in its group) by another variable of the GUB */
3329 	      if( gubset->gubconsstatus[gubconsidx] != GUBCONSSTATUS_UNINITIAL )
3330 	      {
3331 		 assert(gubset->gubconsstatus[gubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GF
3332 		      || gubset->gubconsstatus[gubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GNC1);
3333 	         continue;
3334 	      }
3335 	
3336 	      /* set status of GF GUB */
3337 	      gubset->gubconsstatus[gubconsidx] = GUBCONSSTATUS_BELONGSTOSET_GF;
3338 	
3339 	      /* update sorting key of corresponding GFC1 GUB */
3340 	      for( j = 0; j < gubset->gubconss[gubconsidx]->ngubvars; j++ )
3341 	      {
3342 	         assert(gubset->gubconss[gubconsidx]->gubvarsstatus[j] != GUBVARSTATUS_BELONGSTOSET_C2
3343 	            && gubset->gubconss[gubconsidx]->gubvarsstatus[j] != GUBVARSTATUS_BELONGSTOSET_C1);
3344 	
3345 	         /* F-variable: update sort key (number of F variables in GUB) of corresponding GFC1-GUB */
3346 	         if( gubset->gubconss[gubconsidx]->gubvarsstatus[j] == GUBVARSTATUS_BELONGSTOSET_F )
3347 	         {
3348 	            sortkeypairsGFC1[*ngubconsGFC1]->key1 += 1.0;
3349 	
3350 	            if( solvals[gubset->gubconss[gubconsidx]->gubvars[j]] > sortkeypairsGFC1[*ngubconsGFC1]->key2 )
3351 	               sortkeypairsGFC1[*ngubconsGFC1]->key2 = solvals[gubset->gubconss[gubconsidx]->gubvars[j]];
3352 	         }
3353 	      }
3354 	
3355 	      /* update set of GFC1 GUBs */
3356 	      gubconsGFC1[*ngubconsGFC1] = gubconsidx;
3357 	      (*ngubconsGFC1)++;
3358 	
3359 	      /* update maximum size of all GUB constraints */
3360 	      if( gubset->gubconss[gubconsidx]->gubvarssize > *maxgubvarssize )
3361 	         *maxgubvarssize = gubset->gubconss[gubconsidx]->gubvarssize;
3362 	   }
3363 	
3364 	   /* stores GUBs of group GR; sorting is not required because the R variables (which we loop over) are already sorted
3365 	    * correctly
3366 	    */
3367 	   for( i = 0; i < nvarsR; i++ )
3368 	   {
3369 	      var = varsR[i];
3370 	      gubconsidx = gubset->gubconssidx[var];
3371 	      varidx = gubset->gubvarsidx[var];
3372 	
3373 	      assert(gubconsidx >= 0 && gubconsidx < ngubconss);
3374 	      assert(gubset->gubconss[gubconsidx]->gubvarsstatus[varidx] == GUBVARSTATUS_BELONGSTOSET_R);
3375 	
3376 	#ifndef NDEBUG
3377 	      nvarsprocessed++;
3378 	#endif
3379 	
3380 	      /* the GUB was already handled (status set and stored in its group) by another variable of the GUB */
3381 	      if( gubset->gubconsstatus[gubconsidx] != GUBCONSSTATUS_UNINITIAL )
3382 	      {
3383 		 assert(gubset->gubconsstatus[gubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GR
3384 		      || gubset->gubconsstatus[gubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GF
3385 		      || gubset->gubconsstatus[gubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GNC1);
3386 	         continue;
3387 	      }
3388 	
3389 	      /* set status of GR GUB */
3390 	      gubset->gubconsstatus[gubconsidx] = GUBCONSSTATUS_BELONGSTOSET_GR;
3391 	
3392 	      /* update set of GR GUBs */
3393 	      gubconsGR[*ngubconsGR] = gubconsidx;
3394 	      (*ngubconsGR)++;
3395 	
3396 	      /* update maximum size of all GUB constraints */
3397 	      if( gubset->gubconss[gubconsidx]->gubvarssize > *maxgubvarssize )
3398 	         *maxgubvarssize = gubset->gubconss[gubconsidx]->gubvarssize;
3399 	   }
3400 	   assert(nvarsprocessed == nvarsC1 + nvarsC2 + nvarsF + nvarsR);
3401 	
3402 	   /* update number of GUBs with only capacity exceeding variables (will not be used for lifting) */
3403 	   (*ngubconscapexceed) =  ngubconss - (ngubconsGOC1 + (*ngubconsGC2) + (*ngubconsGFC1) + (*ngubconsGR));
3404 	   assert(*ngubconscapexceed >= 0);
3405 	#ifndef NDEBUG
3406 	   {
3407 	      int check;
3408 	
3409 	      check = 0;
3410 	
3411 	      /* remaining not handled GUBs should only contain capacity exceeding variables */
3412 	      for( i = 0; i < ngubconss; i++ )
3413 	      {
3414 	         if( gubset->gubconsstatus[i] ==  GUBCONSSTATUS_UNINITIAL )
3415 	            check++;
3416 	      }
3417 	      assert(check == *ngubconscapexceed);
3418 	   }
3419 	#endif
3420 	
3421 	   /* sort GFCI GUBs according to computed sorting keys */
3422 	   if( (*ngubconsGFC1) > 0 )
3423 	   {
3424 	      SCIPsortDownPtrInt((void**)sortkeypairsGFC1, gubconsGFC1, compSortkeypairs, (*ngubconsGFC1));
3425 	   }
3426 	
3427 	   /* free temporary memory */
3428 	#if GUBSPLITGNC1GUBS
3429 	   ngubconss = origngubconss;
3430 	#endif
3431 	   SCIPfreeBufferArray(scip, &nC1varsingubcons);
3432 	   SCIPfreeBufferArray(scip, &sortkeypairsGFC1store);
3433 	   SCIPfreeBufferArray(scip, &sortkeypairsGFC1);
3434 	
3435 	   return SCIP_OKAY;
3436 	}
3437 	
3438 	/** enlarges minweight table to at least the given length */
3439 	static
3440 	SCIP_RETCODE enlargeMinweights(
3441 	   SCIP*                 scip,               /**< SCIP data structure */
3442 	   SCIP_Longint**        minweightsptr,      /**< pointer to minweights table */
3443 	   int*                  minweightslen,      /**< pointer to store number of entries in minweights table (incl. z=0) */
3444 	   int*                  minweightssize,     /**< pointer to current size of minweights table */
3445 	   int                   newlen              /**< new length of minweights table */
3446 	   )
3447 	{
3448 	   int j;
3449 	
3450 	   assert(minweightsptr != NULL);
3451 	   assert(*minweightsptr != NULL);
3452 	   assert(minweightslen != NULL);
3453 	   assert(*minweightslen >= 0);
3454 	   assert(minweightssize != NULL);
3455 	   assert(*minweightssize >= 0);
3456 	
3457 	   if( newlen > *minweightssize )
3458 	   {
3459 	      int newsize;
3460 	
3461 	      /* reallocate table memory */
3462 	      newsize = SCIPcalcMemGrowSize(scip, newlen);
3463 	      SCIP_CALL( SCIPreallocBufferArray(scip, minweightsptr, newsize) );
3464 	      *minweightssize = newsize;
3465 	   }
3466 	   assert(newlen <= *minweightssize);
3467 	
3468 	   /* initialize new elements */
3469 	   for( j = *minweightslen; j < newlen; ++j )
3470 	      (*minweightsptr)[j] = SCIP_LONGINT_MAX;
3471 	   *minweightslen = newlen;
3472 	
3473 	   return SCIP_OKAY;
3474 	}
3475 	
3476 	/** lifts given inequality
3477 	 *    sum_{j in M_1} x_j <= alpha_0
3478 	 *  valid for
3479 	 *    S^0 = { x in {0,1}^|M_1| : sum_{j in M_1} a_j x_j <= a_0 - sum_{j in M_2} a_j }
3480 	 *  to a valid inequality
3481 	 *    sum_{j in M_1} x_j + sum_{j in F} alpha_j x_j + sum_{j in M_2} alpha_j x_j + sum_{j in R} alpha_j x_j
3482 	 *    <= alpha_0 + sum_{j in M_2} alpha_j
3483 	 *  for
3484 	 *    S = { x in {0,1}^|N| : sum_{j in N} a_j x_j <= a_0 };
3485 	 *  uses sequential up-lifting for the variables in F, sequential down-lifting for the variable in M_2, and
3486 	 *  sequential up-lifting for the variables in R; procedure can be used to strengthen minimal cover inequalities and
3487 	 *  extended weight inequalities.
3488 	 */
3489 	static
3490 	SCIP_RETCODE sequentialUpAndDownLifting(
3491 	   SCIP*                 scip,               /**< SCIP data structure */
3492 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
3493 	   int                   nvars,              /**< number of variables in knapsack constraint */
3494 	   int                   ntightened,         /**< number of variables with tightened upper bound */
3495 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
3496 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
3497 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
3498 	   int*                  varsM1,             /**< variables in M_1 */
3499 	   int*                  varsM2,             /**< variables in M_2 */
3500 	   int*                  varsF,              /**< variables in F */
3501 	   int*                  varsR,              /**< variables in R */
3502 	   int                   nvarsM1,            /**< number of variables in M_1 */
3503 	   int                   nvarsM2,            /**< number of variables in M_2 */
3504 	   int                   nvarsF,             /**< number of variables in F */
3505 	   int                   nvarsR,             /**< number of variables in R */
3506 	   int                   alpha0,             /**< rights hand side of given valid inequality */
3507 	   int*                  liftcoefs,          /**< pointer to store lifting coefficient of vars in knapsack constraint */
3508 	   SCIP_Real*            cutact,             /**< pointer to store activity of lifted valid inequality */
3509 	   int*                  liftrhs             /**< pointer to store right hand side of the lifted valid inequality */
3510 	   )
3511 	{
3512 	   SCIP_Longint* minweights;
3513 	   SCIP_Real* sortkeys;
3514 	   SCIP_Longint fixedonesweight;
3515 	   int minweightssize;
3516 	   int minweightslen;
3517 	   int j;
3518 	   int w;
3519 	
3520 	   assert(scip != NULL);
3521 	   assert(vars != NULL);
3522 	   assert(nvars >= 0);
3523 	   assert(weights != NULL);
3524 	   assert(capacity >= 0);
3525 	   assert(solvals != NULL);
3526 	   assert(varsM1 != NULL);
3527 	   assert(varsM2 != NULL);
3528 	   assert(varsF != NULL);
3529 	   assert(varsR != NULL);
3530 	   assert(nvarsM1 >= 0 && nvarsM1 <= nvars - ntightened);
3531 	   assert(nvarsM2 >= 0 && nvarsM2 <= nvars - ntightened);
3532 	   assert(nvarsF >= 0 && nvarsF <= nvars - ntightened);
3533 	   assert(nvarsR >= 0 && nvarsR <= nvars - ntightened);
3534 	   assert(nvarsM1 + nvarsM2 + nvarsF + nvarsR == nvars  - ntightened);
3535 	   assert(alpha0 >= 0);
3536 	   assert(liftcoefs != NULL);
3537 	   assert(cutact != NULL);
3538 	   assert(liftrhs != NULL);
3539 	
3540 	   /* allocates temporary memory */
3541 	   minweightssize = nvarsM1 + 1;
3542 	   SCIP_CALL( SCIPallocBufferArray(scip, &minweights, minweightssize) );
3543 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeys, nvarsM1) );
3544 	
3545 	   /* initializes data structures */
3546 	   BMSclearMemoryArray(liftcoefs, nvars);
3547 	   *cutact = 0.0;
3548 	
3549 	   /* sets lifting coefficient of variables in M1, sorts variables in M1 such that a_1 <= a_2 <= ... <= a_|M1|
3550 	    * and calculates activity of the current valid inequality
3551 	    */
3552 	   for( j = 0; j < nvarsM1; j++ )
3553 	   {
3554 	      assert(liftcoefs[varsM1[j]] == 0);
3555 	      liftcoefs[varsM1[j]] = 1;
3556 	      sortkeys[j] = (SCIP_Real) (weights[varsM1[j]]);
3557 	      (*cutact) += solvals[varsM1[j]];
3558 	   }
3559 	
3560 	   SCIPsortRealInt(sortkeys, varsM1, nvarsM1);
3561 	
3562 	   /* initializes (i = 1) the minweight table, defined as: minweights_i[w] =
3563 	    *   min   sum_{j in M_1} a_j x_j + sum_{k=1}^{i-1} a_{j_k}     x_{j_k}
3564 	    *   s.t.  sum_{j in M_1}     x_j + sum_{k=1}^{i-1} alpha_{j_k} x_{j_k} >= w
3565 	    *                                    x_j in {0,1} for j in M_1 & {j_i,...,j_i-1},
3566 	    * for i = 1,...,t with t = |N\M1| and w = 0,...,|M1| + sum_{k=1}^{i-1} alpha_{j_k};
3567 	    */
3568 	   minweights[0] = 0;
3569 	   for( w = 1; w <= nvarsM1; w++ )
3570 	      minweights[w] = minweights[w-1] + weights[varsM1[w-1]];
3571 	   minweightslen = nvarsM1 + 1;
3572 	
3573 	   /* gets sum of weights of variables fixed to one, i.e. sum of weights of variables in M_2 */
3574 	   fixedonesweight = 0;
3575 	   for( j = 0; j < nvarsM2; j++ )
3576 	      fixedonesweight += weights[varsM2[j]];
3577 	   assert(fixedonesweight >= 0);
3578 	
3579 	   /* initializes right hand side of lifted valid inequality */
3580 	   *liftrhs = alpha0;
3581 	
3582 	   /* sequentially up-lifts all variables in F: */
3583 	   for( j = 0; j < nvarsF; j++ )
3584 	   {
3585 	      SCIP_Longint weight;
3586 	      int liftvar;
3587 	      int liftcoef;
3588 	      int z;
3589 	
3590 	      liftvar = varsF[j];
3591 	      weight = weights[liftvar];
3592 	      assert(liftvar >= 0 && liftvar < nvars);
3593 	      assert(SCIPisFeasGT(scip, solvals[liftvar], 0.0));
3594 	      assert(weight > 0);
3595 	
3596 	      /* knapsack problem is infeasible:
3597 	       *   sets z = 0
3598 	       */
3599 	      if( capacity - fixedonesweight - weight < 0 )
3600 	      {
3601 	         z = 0;
3602 	      }
3603 	      /* knapsack problem is feasible:
3604 	       *   sets z = max { w : 0 <= w <= liftrhs, minweights_i[w] <= a_0 - fixedonesweight - a_{j_i}  } = liftrhs,
3605 	       *   if minweights_i[liftrhs] <= a_0 - fixedonesweight - a_{j_i}
3606 	       */
3607 	      else if( minweights[*liftrhs] <= capacity - fixedonesweight - weight )
3608 	      {
3609 	         z = *liftrhs;
3610 	      }
3611 	      /* knapsack problem is feasible:
3612 	       *   uses binary search to find z = max { w : 0 <= w <= liftrhs, minweights_i[w] <= a_0 - fixedonesweight - a_{j_i} }
3613 	       */
3614 	      else
3615 	      {
3616 	         int left;
3617 	         int right;
3618 	         int middle;
3619 	
3620 	         assert((*liftrhs) + 1 >= minweightslen || minweights[(*liftrhs) + 1] > capacity - fixedonesweight - weight);
3621 	         left = 0;
3622 	         right = (*liftrhs) + 1;
3623 	         while( left < right - 1 )
3624 	         {
3625 	            middle = (left + right) / 2;
3626 	            assert(0 <= middle && middle < minweightslen);
3627 	            if( minweights[middle] <= capacity - fixedonesweight - weight )
3628 	               left = middle;
3629 	            else
3630 	               right = middle;
3631 	         }
3632 	         assert(left == right - 1);
3633 	         assert(0 <= left && left < minweightslen);
3634 	         assert(minweights[left] <= capacity - fixedonesweight - weight );
3635 	         assert(left == minweightslen - 1 || minweights[left+1] > capacity - fixedonesweight - weight);
3636 	
3637 	         /* now z = left */
3638 	         z = left;
3639 	         assert(z <= *liftrhs);
3640 	      }
3641 	
3642 	      /* calculates lifting coefficients alpha_{j_i} = liftrhs - z */
3643 	      liftcoef = (*liftrhs) - z;
3644 	      liftcoefs[liftvar] = liftcoef;
3645 	      assert(liftcoef >= 0 && liftcoef <= (*liftrhs) + 1);
3646 	
3647 	      /* minweight table and activity of current valid inequality will not change, if alpha_{j_i} = 0 */
3648 	      if( liftcoef == 0 )
3649 	         continue;
3650 	
3651 	      /* updates activity of current valid inequality */
3652 	      (*cutact) += liftcoef * solvals[liftvar];
3653 	
3654 	      /* enlarges current minweight table:
3655 	       *  from minweightlen = |M1| + sum_{k=1}^{i-1} alpha_{j_k} + 1 entries
3656 	       *  to                  |M1| + sum_{k=1}^{i  } alpha_{j_k} + 1 entries
3657 	       * and sets minweights_i[w] = infinity for
3658 	       *  w = |M1| + sum_{k=1}^{i-1} alpha_{j_k} + 1 , ... , |M1| + sum_{k=1}^{i} alpha_{j_k}
3659 	       */
3660 	      SCIP_CALL( enlargeMinweights(scip, &minweights, &minweightslen, &minweightssize, minweightslen + liftcoef) );
3661 	
3662 	      /* updates minweight table: minweight_i+1[w] =
3663 	       *   min{ minweights_i[w], a_{j_i}},                                 if w <  alpha_j_i
3664 	       *   min{ minweights_i[w], minweights_i[w - alpha_j_i] + a_j_i},     if w >= alpha_j_i
3665 	       */
3666 	      for( w = minweightslen - 1; w >= 0; w-- )
3667 	      {
3668 	         SCIP_Longint min;
3669 	         if( w < liftcoef )
3670 	         {
3671 	            min = MIN(minweights[w], weight);
3672 	            minweights[w] = min;
3673 	         }
3674 	         else
3675 	         {
3676 	            assert(w >= liftcoef);
3677 	            min = MIN(minweights[w], minweights[w - liftcoef] + weight);
3678 	            minweights[w] = min;
3679 	         }
3680 	      }
3681 	   }
3682 	   assert(minweights[0] == 0);
3683 	
3684 	   /* sequentially down-lifts all variables in M_2: */
3685 	   for( j = 0; j < nvarsM2; j++ )
3686 	   {
3687 	      SCIP_Longint weight;
3688 	      int liftvar;
3689 	      int liftcoef;
3690 	      int left;
3691 	      int right;
3692 	      int middle;
3693 	      int z;
3694 	
3695 	      liftvar = varsM2[j];
3696 	      weight = weights[liftvar];
3697 	      assert(SCIPisFeasEQ(scip, solvals[liftvar], 1.0));
3698 	      assert(liftvar >= 0 && liftvar < nvars);
3699 	      assert(weight > 0);
3700 	
3701 	      /* uses binary search to find
3702 	       *   z = max { w : 0 <= w <= |M_1| + sum_{k=1}^{i-1} alpha_{j_k}, minweights_[w] <= a_0 - fixedonesweight + a_{j_i}}
3703 	       */
3704 	      left = 0;
3705 	      right = minweightslen;
3706 	      while( left < right - 1 )
3707 	      {
3708 	         middle = (left + right) / 2;
3709 	         assert(0 <= middle && middle < minweightslen);
3710 	         if( minweights[middle] <= capacity - fixedonesweight + weight )
3711 	            left = middle;
3712 	         else
3713 	            right = middle;
3714 	      }
3715 	      assert(left == right - 1);
3716 	      assert(0 <= left && left < minweightslen);
3717 	      assert(minweights[left] <= capacity - fixedonesweight + weight );
3718 	      assert(left == minweightslen - 1 || minweights[left+1] > capacity - fixedonesweight + weight);
3719 	
3720 	      /* now z = left */
3721 	      z = left;
3722 	      assert(z >= *liftrhs);
3723 	
3724 	      /* calculates lifting coefficients alpha_{j_i} = z - liftrhs */
3725 	      liftcoef = z - (*liftrhs);
3726 	      liftcoefs[liftvar] = liftcoef;
3727 	      assert(liftcoef >= 0);
3728 	
3729 	      /* updates sum of weights of variables fixed to one */
3730 	      fixedonesweight -= weight;
3731 	
3732 	      /* updates right-hand side of current valid inequality */
3733 	      (*liftrhs) += liftcoef;
3734 	      assert(*liftrhs >= alpha0);
3735 	
3736 	      /* minweight table and activity of current valid inequality will not change, if alpha_{j_i} = 0 */
3737 	      if( liftcoef == 0 )
3738 	         continue;
3739 	
3740 	      /* updates activity of current valid inequality */
3741 	      (*cutact) += liftcoef * solvals[liftvar];
3742 	
3743 	      /* enlarges current minweight table:
3744 	       *  from minweightlen = |M1| + sum_{k=1}^{i-1} alpha_{j_k} + 1 entries
3745 	       *  to                  |M1| + sum_{k=1}^{i  } alpha_{j_k} + 1 entries
3746 	       * and sets minweights_i[w] = infinity for
3747 	       *  w = |M1| + sum_{k=1}^{i-1} alpha_{j_k} + 1 , ... , |M1| + sum_{k=1}^{i} alpha_{j_k}
3748 	       */
3749 	      SCIP_CALL( enlargeMinweights(scip, &minweights, &minweightslen, &minweightssize, minweightslen + liftcoef) );
3750 	
3751 	      /* updates minweight table: minweight_i+1[w] =
3752 	       *   min{ minweights_i[w], a_{j_i}},                                 if w <  alpha_j_i
3753 	       *   min{ minweights_i[w], minweights_i[w - alpha_j_i] + a_j_i},     if w >= alpha_j_i
3754 	       */
3755 	      for( w = minweightslen - 1; w >= 0; w-- )
3756 	      {
3757 	         SCIP_Longint min;
3758 	         if( w < liftcoef )
3759 	         {
3760 	            min = MIN(minweights[w], weight);
3761 	            minweights[w] = min;
3762 	         }
3763 	         else
3764 	         {
3765 	            assert(w >= liftcoef);
3766 	            min = MIN(minweights[w], minweights[w - liftcoef] + weight);
3767 	            minweights[w] = min;
3768 	         }
3769 	      }
3770 	   }
3771 	   assert(fixedonesweight == 0);
3772 	   assert(*liftrhs >= alpha0);
3773 	
3774 	   /* sequentially up-lifts all variables in R: */
3775 	   for( j = 0; j < nvarsR; j++ )
3776 	   {
3777 	      SCIP_Longint weight;
3778 	      int liftvar;
3779 	      int liftcoef;
3780 	      int z;
3781 	
3782 	      liftvar = varsR[j];
3783 	      weight = weights[liftvar];
3784 	      assert(liftvar >= 0 && liftvar < nvars);
3785 	      assert(SCIPisFeasEQ(scip, solvals[liftvar], 0.0));
3786 	      assert(weight > 0);
3787 	      assert(capacity - weight >= 0);
3788 	      assert((*liftrhs) + 1 >= minweightslen || minweights[(*liftrhs) + 1] > capacity - weight);
3789 	
3790 	      /* sets z = max { w : 0 <= w <= liftrhs, minweights_i[w] <= a_0 - a_{j_i} } = liftrhs,
3791 	       * if minweights_i[liftrhs] <= a_0 - a_{j_i}
3792 	       */
3793 	      if( minweights[*liftrhs] <= capacity - weight )
3794 	      {
3795 	         z = *liftrhs;
3796 	      }
3797 	      /* uses binary search to find z = max { w : 0 <= w <= liftrhs, minweights_i[w] <= a_0 - a_{j_i} }
3798 	       */
3799 	      else
3800 	      {
3801 	         int left;
3802 	         int right;
3803 	         int middle;
3804 	
3805 	         left = 0;
3806 	         right = (*liftrhs) + 1;
3807 	         while( left < right - 1)
3808 	         {
3809 	            middle = (left + right) / 2;
3810 	            assert(0 <= middle && middle < minweightslen);
3811 	            if( minweights[middle] <= capacity - weight )
3812 	               left = middle;
3813 	            else
3814 	               right = middle;
3815 	         }
3816 	         assert(left == right - 1);
3817 	         assert(0 <= left && left < minweightslen);
3818 	         assert(minweights[left] <= capacity - weight );
3819 	         assert(left == minweightslen - 1 || minweights[left+1] > capacity - weight);
3820 	
3821 	         /* now z = left */
3822 	         z = left;
3823 	         assert(z <= *liftrhs);
3824 	      }
3825 	
3826 	      /* calculates lifting coefficients alpha_{j_i} = liftrhs - z */
3827 	      liftcoef = (*liftrhs) - z;
3828 	      liftcoefs[liftvar] = liftcoef;
3829 	      assert(liftcoef >= 0 && liftcoef <= *liftrhs);
3830 	
3831 	      /* minweight table and activity of current valid inequality will not change, if alpha_{j_i} = 0 */
3832 	      if( liftcoef == 0 )
3833 	         continue;
3834 	
3835 	      /* updates activity of current valid inequality */
3836 	      (*cutact) += liftcoef * solvals[liftvar];
3837 	
3838 	      /* updates minweight table: minweight_i+1[w] =
3839 	       *   min{ minweight_i[w], a_{j_i}},                                if w <  alpha_j_i
3840 	       *   min{ minweight_i[w], minweight_i[w - alpha_j_i] + a_j_i},     if w >= alpha_j_i
3841 	       */
3842 	      for( w = *liftrhs; w >= 0; w-- )
3843 	      {
3844 	         SCIP_Longint min;
3845 	         if( w < liftcoef )
3846 	         {
3847 	            min = MIN(minweights[w], weight);
3848 	            minweights[w] = min;
3849 	         }
3850 	         else
3851 	         {
3852 	            assert(w >= liftcoef);
3853 	            min = MIN(minweights[w], minweights[w - liftcoef] + weight);
3854 	            minweights[w] = min;
3855 	         }
3856 	      }
3857 	   }
3858 	
3859 	   /* frees temporary memory */
3860 	   SCIPfreeBufferArray(scip, &sortkeys);
3861 	   SCIPfreeBufferArray(scip, &minweights);
3862 	
3863 	   return SCIP_OKAY;
3864 	}
3865 	
3866 	/** adds two minweight values in a safe way, i.e,, ensures no overflow */
3867 	static
3868 	SCIP_Longint safeAddMinweightsGUB(
3869 	   SCIP_Longint          val1,               /**< first value to add */
3870 	   SCIP_Longint          val2                /**< second value to add */
3871 	   )
3872 	{
3873 	   assert(val1 >= 0);
3874 	   assert(val2 >= 0);
3875 	
3876 	   if( val1 >= SCIP_LONGINT_MAX || val2 >= SCIP_LONGINT_MAX )
3877 	      return SCIP_LONGINT_MAX;
3878 	   else
3879 	   {
3880 	      assert(val1 <= SCIP_LONGINT_MAX - val2);
3881 	      return (val1 + val2);
3882 	   }
3883 	}
3884 	
3885 	/** computes minweights table for lifting with GUBs by combining unfished and fished tables */
3886 	static
3887 	void computeMinweightsGUB(
3888 	   SCIP_Longint*         minweights,         /**< minweight table to compute */
3889 	   SCIP_Longint*         finished,           /**< given finished table */
3890 	   SCIP_Longint*         unfinished,         /**< given unfinished table */
3891 	   int                   minweightslen       /**< length of minweight, finished, and unfinished tables */
3892 	   )
3893 	{
3894 	   int w1;
3895 	   int w2;
3896 	
3897 	   /* minweights_i[w] = min{finished_i[w1] + unfinished_i[w2] : w1>=0, w2>=0, w1+w2=w};
3898 	    * note that finished and unfished arrays sorted by non-decreasing weight
3899 	    */
3900 	
3901 	   /* initialize minweight with w2 = 0 */
3902 	   w2 = 0;
3903 	   assert(unfinished[w2] == 0);
3904 	   for( w1 = 0; w1 < minweightslen; w1++ )
3905 	      minweights[w1] = finished[w1];
3906 	
3907 	   /* consider w2 = 1, ..., minweightslen-1 */
3908 	   for( w2 = 1; w2 < minweightslen; w2++ )
3909 	   {
3910 	      if( unfinished[w2] >= SCIP_LONGINT_MAX )
3911 	         break;
3912 	
3913 	      for( w1 = 0; w1 < minweightslen - w2; w1++ )
3914 	      {
3915 	         SCIP_Longint temp;
3916 	
3917 		 temp = safeAddMinweightsGUB(finished[w1], unfinished[w2]);
3918 		 if( temp <= minweights[w1+w2] )
3919 		    minweights[w1+w2] = temp;
3920 	      }
3921 	   }
3922 	}
3923 	
3924 	/** lifts given inequality
3925 	 *    sum_{j in C_1} x_j <= alpha_0
3926 	 *  valid for
3927 	 *    S^0 = { x in {0,1}^|C_1| : sum_{j in C_1} a_j x_j <= a_0 - sum_{j in C_2} a_j;
3928 	 *                               sum_{j in Q_i} x_j <= 1, forall i in I }
3929 	 *  to a valid inequality
3930 	 *    sum_{j in C_1} x_j + sum_{j in F} alpha_j x_j + sum_{j in C_2} alpha_j x_j + sum_{j in R} alpha_j x_j
3931 	 *    <= alpha_0 + sum_{j in C_2} alpha_j
3932 	 *  for
3933 	 *    S = { x in {0,1}^|N| : sum_{j in N} a_j x_j <= a_0; sum_{j in Q_i} x_j <= 1, forall i in I };
3934 	 *  uses sequential up-lifting   for the variables in GUB constraints in gubconsGFC1,
3935 	 *       sequential down-lifting for the variables in GUB constraints in gubconsGC2, and
3936 	 *       sequential up-lifting   for the variabels in GUB constraints in gubconsGR.
3937 	 */
3938 	static
3939 	SCIP_RETCODE sequentialUpAndDownLiftingGUB(
3940 	   SCIP*                 scip,               /**< SCIP data structure */
3941 	   SCIP_GUBSET*          gubset,             /**< GUB set data structure */
3942 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
3943 	   int                   ngubconscapexceed,  /**< number of GUBs with only capacity exceeding variables */
3944 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
3945 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
3946 	   SCIP_Real*            solvals,            /**< solution values of all knapsack variables */
3947 	   int*                  gubconsGC1,         /**< GUBs in GC1(GNC1+GOC1) */
3948 	   int*                  gubconsGC2,         /**< GUBs in GC2 */
3949 	   int*                  gubconsGFC1,        /**< GUBs in GFC1(GNC1+GF) */
3950 	   int*                  gubconsGR,          /**< GUBs in GR */
3951 	   int                   ngubconsGC1,        /**< number of GUBs in GC1(GNC1+GOC1) */
3952 	   int                   ngubconsGC2,        /**< number of GUBs in GC2 */
3953 	   int                   ngubconsGFC1,       /**< number of GUBs in GFC1(GNC1+GF) */
3954 	   int                   ngubconsGR,         /**< number of GUBs in GR */
3955 	   int                   alpha0,             /**< rights hand side of given valid inequality */
3956 	   int*                  liftcoefs,          /**< pointer to store lifting coefficient of vars in knapsack constraint */
3957 	   SCIP_Real*            cutact,             /**< pointer to store activity of lifted valid inequality */
3958 	   int*                  liftrhs,            /**< pointer to store right hand side of the lifted valid inequality */
3959 	   int                   maxgubvarssize      /**< maximal size of GUB constraints */
3960 	   )
3961 	{
3962 	   SCIP_Longint* minweights;
3963 	   SCIP_Longint* finished;
3964 	   SCIP_Longint* unfinished;
3965 	   int* gubconsGOC1;
3966 	   int* gubconsGNC1;
3967 	   int* liftgubvars;
3968 	   SCIP_Longint fixedonesweight;
3969 	   SCIP_Longint weight;
3970 	   SCIP_Longint weightdiff1;
3971 	   SCIP_Longint weightdiff2;
3972 	   SCIP_Longint min;
3973 	   int minweightssize;
3974 	   int minweightslen;
3975 	   int nvars;
3976 	   int varidx;
3977 	   int liftgubconsidx;
3978 	   int liftvar;
3979 	   int sumliftcoef;
3980 	   int liftcoef;
3981 	   int ngubconsGOC1;
3982 	   int ngubconsGNC1;
3983 	   int left;
3984 	   int right;
3985 	   int middle;
3986 	   int nliftgubvars;
3987 	   int tmplen;
3988 	   int tmpsize;
3989 	   int j;
3990 	   int k;
3991 	   int w;
3992 	   int z;
3993 	#ifndef NDEBUG
3994 	   int ngubconss;
3995 	   int nliftgubC1;
3996 	
3997 	   assert(gubset != NULL);
3998 	   ngubconss = gubset->ngubconss;
3999 	#else
4000 	   assert(gubset != NULL);
4001 	#endif
4002 	
4003 	   nvars = gubset->nvars;
4004 	
4005 	   assert(scip != NULL);
4006 	   assert(vars != NULL);
4007 	   assert(nvars >= 0);
4008 	   assert(weights != NULL);
4009 	   assert(capacity >= 0);
4010 	   assert(solvals != NULL);
4011 	   assert(gubconsGC1 != NULL);
4012 	   assert(gubconsGC2 != NULL);
4013 	   assert(gubconsGFC1 != NULL);
4014 	   assert(gubconsGR != NULL);
4015 	   assert(ngubconsGC1 >= 0 && ngubconsGC1 <= ngubconss - ngubconscapexceed);
4016 	   assert(ngubconsGC2 >= 0 && ngubconsGC2 <= ngubconss - ngubconscapexceed);
4017 	   assert(ngubconsGFC1 >= 0 && ngubconsGFC1 <= ngubconss - ngubconscapexceed);
4018 	   assert(ngubconsGR >= 0 && ngubconsGR <= ngubconss - ngubconscapexceed);
4019 	   assert(alpha0 >= 0);
4020 	   assert(liftcoefs != NULL);
4021 	   assert(cutact != NULL);
4022 	   assert(liftrhs != NULL);
4023 	
4024 	   minweightssize = ngubconsGC1+1;
4025 	
4026 	   /* allocates temporary memory */
4027 	   SCIP_CALL( SCIPallocBufferArray(scip, &liftgubvars, maxgubvarssize) );
4028 	   SCIP_CALL( SCIPallocBufferArray(scip, &gubconsGOC1, ngubconsGC1) );
4029 	   SCIP_CALL( SCIPallocBufferArray(scip, &gubconsGNC1, ngubconsGC1) );
4030 	   SCIP_CALL( SCIPallocBufferArray(scip, &minweights, minweightssize) );
4031 	   SCIP_CALL( SCIPallocBufferArray(scip, &finished, minweightssize) );
4032 	   SCIP_CALL( SCIPallocBufferArray(scip, &unfinished, minweightssize) );
4033 	
4034 	   /* initializes data structures */
4035 	   BMSclearMemoryArray(liftcoefs, nvars);
4036 	   *cutact = 0.0;
4037 	
4038 	   /* gets GOC1 and GNC1 GUBs, sets lifting coefficient of variables in C1 and calculates activity of the current
4039 	    * valid inequality
4040 	    */
4041 	   ngubconsGOC1 = 0;
4042 	   ngubconsGNC1 = 0;
4043 	   for( j = 0; j < ngubconsGC1; j++ )
4044 	   {
4045 	      if( gubset->gubconsstatus[gubconsGC1[j]] == GUBCONSSTATUS_BELONGSTOSET_GOC1 )
4046 	      {
4047 	         gubconsGOC1[ngubconsGOC1] = gubconsGC1[j];
4048 	         ngubconsGOC1++;
4049 	      }
4050 	      else
4051 	      {
4052 	         assert(gubset->gubconsstatus[gubconsGC1[j]] == GUBCONSSTATUS_BELONGSTOSET_GNC1);
4053 	         gubconsGNC1[ngubconsGNC1] = gubconsGC1[j];
4054 	         ngubconsGNC1++;
4055 	      }
4056 	      for( k = 0; k < gubset->gubconss[gubconsGC1[j]]->ngubvars
4057 	              && gubset->gubconss[gubconsGC1[j]]->gubvarsstatus[k] == GUBVARSTATUS_BELONGSTOSET_C1; k++ )
4058 	      {
4059 	         varidx = gubset->gubconss[gubconsGC1[j]]->gubvars[k];
4060 	         assert(varidx >= 0 && varidx < nvars);
4061 	         assert(liftcoefs[varidx] == 0);
4062 	
4063 	         liftcoefs[varidx] = 1;
4064 	         (*cutact) += solvals[varidx];
4065 	      }
4066 	      assert(k >= 1);
4067 	   }
4068 	   assert(ngubconsGOC1 + ngubconsGFC1 + ngubconsGC2 + ngubconsGR == ngubconss - ngubconscapexceed);
4069 	   assert(ngubconsGOC1 + ngubconsGNC1 == ngubconsGC1);
4070 	
4071 	   /* initialize the minweight tables, defined as: for i = 1,...,m with m = |I| and w = 0,...,|gubconsGC1|;
4072 	    * - finished_i[w] =
4073 	    *   min   sum_{k = 1,2,...,i-1} sum_{j in Q_k} a_j x_j
4074 	    *   s.t.  sum_{k = 1,2,...,i-1} sum_{j in Q_k} alpha_j x_j  >= w
4075 	    *                               sum_{j in Q_k} x_j <= 1
4076 	    *                               x_j in {0,1} forall j in Q_k forall k = 1,2,...,i-1,
4077 	    * - unfinished_i[w] =
4078 	    *   min   sum_{k = i+1,...,m} sum_{j in Q_k && j in C1} a_j x_j
4079 	    *   s.t.  sum_{k = i+1,...,m} sum_{j in Q_k && j in C1} x_j  >= w
4080 	    *                             sum_{j in Q_k} x_j <= 1
4081 	    *                             x_j in {0,1} forall j in Q_k forall k = 1,2,...,i-1,
4082 	    * - minweights_i[w] = min{finished_i[w1] + unfinished_i[w2] : w1>=0, w2>=0, w1+w2=w};
4083 	    */
4084 	
4085 	   /* initialize finished table; note that variables in GOC1 GUBs (includes C1 and capacity exceeding variables)
4086 	    * are sorted s.t. C1 variables come first and are sorted by non-decreasing weight.
4087 	    * GUBs in the group GCI are sorted by non-decreasing min{ a_k : k in GC1_j } where min{ a_k : k in GC1_j } always
4088 	    * comes from the first variable in the GUB
4089 	    */
4090 	   assert(ngubconsGOC1 <= ngubconsGC1);
4091 	   finished[0] = 0;
4092 	   for( w = 1; w <= ngubconsGOC1; w++ )
4093 	   {
4094 	      liftgubconsidx = gubconsGOC1[w-1];
4095 	
4096 	      assert(gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GOC1);
4097 	      assert(gubset->gubconss[liftgubconsidx]->gubvarsstatus[0] == GUBVARSTATUS_BELONGSTOSET_C1);
4098 	
4099 	      varidx = gubset->gubconss[liftgubconsidx]->gubvars[0];
4100 	
4101 	      assert(varidx >= 0 && varidx < nvars);
4102 	      assert(liftcoefs[varidx] == 1);
4103 	
4104 	      min = weights[varidx];
4105 	      finished[w] = finished[w-1] + min;
4106 	
4107 	#ifndef NDEBUG
4108 	      for( k = 1; k < gubset->gubconss[liftgubconsidx]->ngubvars
4109 	              && gubset->gubconss[liftgubconsidx]->gubvarsstatus[k] == GUBVARSTATUS_BELONGSTOSET_C1; k++ )
4110 	      {
4111 	         varidx = gubset->gubconss[liftgubconsidx]->gubvars[k];
4112 	         assert(varidx >= 0 && varidx < nvars);
4113 	         assert(liftcoefs[varidx] == 1);
4114 	         assert(weights[varidx] >= min);
4115 	      }
4116 	#endif
4117 	   }
4118 	   for( w = ngubconsGOC1+1; w <= ngubconsGC1; w++ )
4119 	      finished[w] = SCIP_LONGINT_MAX;
4120 	
4121 	   /* initialize unfinished table; note that variables in GNC1 GUBs
4122 	    * are sorted s.t. C1 variables come first and are sorted by non-decreasing weight.
4123 	    * GUBs in the group GCI are sorted by non-decreasing min{ a_k : k in GC1_j } where min{ a_k : k in GC1_j } always
4124 	    * comes from the first variable in the GUB
4125 	    */
4126 	   assert(ngubconsGNC1 <= ngubconsGC1);
4127 	   unfinished[0] = 0;
4128 	   for( w = 1; w <= ngubconsGNC1; w++ )
4129 	   {
4130 	      liftgubconsidx = gubconsGNC1[w-1];
4131 	
4132 	      assert(gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GNC1);
4133 	      assert(gubset->gubconss[liftgubconsidx]->gubvarsstatus[0] == GUBVARSTATUS_BELONGSTOSET_C1);
4134 	
4135 	      varidx = gubset->gubconss[liftgubconsidx]->gubvars[0];
4136 	
4137 	      assert(varidx >= 0 && varidx < nvars);
4138 	      assert(liftcoefs[varidx] == 1);
4139 	
4140 	      min = weights[varidx];
4141 	      unfinished[w] = unfinished[w-1] + min;
4142 	
4143 	#ifndef NDEBUG
4144 	      for( k = 1; k < gubset->gubconss[liftgubconsidx]->ngubvars
4145 	              && gubset->gubconss[liftgubconsidx]->gubvarsstatus[k] == GUBVARSTATUS_BELONGSTOSET_C1; k++ )
4146 	      {
4147 	         varidx = gubset->gubconss[liftgubconsidx]->gubvars[k];
4148 	         assert(varidx >= 0 && varidx < nvars);
4149 	         assert(liftcoefs[varidx] == 1);
4150 	         assert(weights[varidx] >= min );
4151 	      }
4152 	#endif
4153 	   }
4154 	   for( w = ngubconsGNC1 + 1; w <= ngubconsGC1; w++ )
4155 	      unfinished[w] = SCIP_LONGINT_MAX;
4156 	
4157 	   /* initialize minweights table; note that variables in GC1 GUBs
4158 	    * are sorted s.t. C1 variables come first and are sorted by non-decreasing weight.
4159 	    * we can directly initialize minweights instead of computing it from finished and unfinished (which would be more time
4160 	    * consuming) because is it has to be build using weights from C1 only.
4161 	    */
4162 	   assert(ngubconsGOC1 + ngubconsGNC1 == ngubconsGC1);
4163 	   minweights[0] = 0;
4164 	   for( w = 1; w <= ngubconsGC1; w++ )
4165 	   {
4166 	      liftgubconsidx = gubconsGC1[w-1];
4167 	
4168 	      assert(gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GOC1
4169 	          || gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GNC1);
4170 	      assert(gubset->gubconss[liftgubconsidx]->gubvarsstatus[0] == GUBVARSTATUS_BELONGSTOSET_C1);
4171 	
4172 	      varidx = gubset->gubconss[liftgubconsidx]->gubvars[0];
4173 	
4174 	      assert(varidx >= 0 && varidx < nvars);
4175 	      assert(liftcoefs[varidx] == 1);
4176 	
4177 	      min = weights[varidx];
4178 	      minweights[w] = minweights[w-1] + min;
4179 	
4180 	#ifndef NDEBUG
4181 	      for( k = 1; k < gubset->gubconss[liftgubconsidx]->ngubvars
4182 	              && gubset->gubconss[liftgubconsidx]->gubvarsstatus[k] == GUBVARSTATUS_BELONGSTOSET_C1; k++ )
4183 	      {
4184 	         varidx = gubset->gubconss[liftgubconsidx]->gubvars[k];
4185 	         assert(varidx >= 0 && varidx < nvars);
4186 	         assert(liftcoefs[varidx] == 1);
4187 	         assert(weights[varidx] >= min);
4188 	      }
4189 	#endif
4190 	   }
4191 	   minweightslen = ngubconsGC1 + 1;
4192 	
4193 	   /* gets sum of weights of variables fixed to one, i.e. sum of weights of C2 variables GC2 GUBs */
4194 	   fixedonesweight = 0;
4195 	   for( j = 0; j < ngubconsGC2; j++ )
4196 	   {
4197 	      varidx = gubset->gubconss[gubconsGC2[j]]->gubvars[0];
4198 	
4199 	      assert(gubset->gubconss[gubconsGC2[j]]->ngubvars == 1);
4200 	      assert(varidx >= 0 && varidx < nvars);
4201 	      assert(gubset->gubconss[gubconsGC2[j]]->gubvarsstatus[0] == GUBVARSTATUS_BELONGSTOSET_C2);
4202 	
4203 	      fixedonesweight += weights[varidx];
4204 	   }
4205 	   assert(fixedonesweight >= 0);
4206 	
4207 	   /* initializes right hand side of lifted valid inequality */
4208 	   *liftrhs = alpha0;
4209 	
4210 	   /* sequentially up-lifts all variables in GFC1 GUBs */
4211 	   for( j = 0; j < ngubconsGFC1; j++ )
4212 	   {
4213 	      liftgubconsidx = gubconsGFC1[j];
4214 	      assert(liftgubconsidx >= 0 && liftgubconsidx < ngubconss);
4215 	
4216 	      /* GNC1 GUB: update unfinished table (remove current GUB, i.e., remove min weight of C1 vars in GUB) and
4217 	       * compute minweight table via updated unfinished table and aleady upto date finished table;
4218 	       */
4219 	      k = 0;
4220 	      if( gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GNC1 )
4221 	      {
4222 		 assert(gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GNC1);
4223 	         assert(gubset->gubconss[liftgubconsidx]->gubvarsstatus[0] == GUBVARSTATUS_BELONGSTOSET_C1);
4224 	         assert(ngubconsGNC1 > 0);
4225 	
4226 	         /* get number of C1 variables of current GNC1 GUB and put them into array of variables in GUB that
4227 	          * are considered for the lifting, i.e., not capacity exceeding
4228 	          */
4229 	         for( ; k < gubset->gubconss[liftgubconsidx]->ngubvars
4230 			&& gubset->gubconss[liftgubconsidx]->gubvarsstatus[k] == GUBVARSTATUS_BELONGSTOSET_C1; k++ )
4231 	            liftgubvars[k] = gubset->gubconss[liftgubconsidx]->gubvars[k];
4232 	         assert(k >= 1);
4233 	
4234 	         /* update unfinished table by removing current GNC1 GUB, i.e, remove C1 variable with minimal weight
4235 		  * unfinished[w] = MAX{unfinished[w], unfinished[w+1] - weight}, "weight" is the minimal weight of current GUB
4236 		  */
4237 	         weight = weights[liftgubvars[0]];
4238 	
4239 		 weightdiff2 = unfinished[ngubconsGNC1] - weight;
4240 		 unfinished[ngubconsGNC1] = SCIP_LONGINT_MAX;
4241 	         for( w = ngubconsGNC1-1; w >= 1; w-- )
4242 	         {
4243 		    weightdiff1 = weightdiff2;
4244 		    weightdiff2 = unfinished[w] - weight;
4245 	
4246 	            if( unfinished[w] < weightdiff1 )
4247 		       unfinished[w] = weightdiff1;
4248 		    else
4249 		       break;
4250 	         }
4251 	         ngubconsGNC1--;
4252 	
4253 	         /* computes minweights table by combining unfished and fished tables */
4254 	         computeMinweightsGUB(minweights, finished, unfinished, minweightslen);
4255 	         assert(minweights[0] == 0);
4256 	      }
4257 	      /* GF GUB: no update of unfinished table (and minweight table) required because GF GUBs have no C1 variables and
4258 	       * are therefore not in the unfinished table
4259 	       */
4260 	      else
4261 		 assert(gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GF);
4262 	
4263 	#ifndef NDEBUG
4264 	      nliftgubC1 = k;
4265 	#endif
4266 	      nliftgubvars = k;
4267 	      sumliftcoef = 0;
4268 	
4269 	      /* compute lifting coefficient of F and R variables in GNC1 and GF GUBs (C1 vars have already liftcoef 1) */
4270 	      for( ; k < gubset->gubconss[liftgubconsidx]->ngubvars; k++ )
4271 	      {
4272 	         if( gubset->gubconss[liftgubconsidx]->gubvarsstatus[k] == GUBVARSTATUS_BELONGSTOSET_F
4273 	             || gubset->gubconss[liftgubconsidx]->gubvarsstatus[k] == GUBVARSTATUS_BELONGSTOSET_R )
4274 	         {
4275 	            liftvar = gubset->gubconss[liftgubconsidx]->gubvars[k];
4276 	            weight = weights[liftvar];
4277 	            assert(weight > 0);
4278 	            assert(liftvar >= 0 && liftvar < nvars);
4279 		    assert(capacity - weight >= 0);
4280 	
4281 	            /* put variable into array of variables in GUB that are considered for the lifting,
4282 	             *  i.e., not capacity exceeding
4283 	             */
4284 	            liftgubvars[nliftgubvars] = liftvar;
4285 	            nliftgubvars++;
4286 	
4287 		    /* knapsack problem is infeasible:
4288 	             * sets z = 0
4289 	             */
4290 	            if( capacity - fixedonesweight - weight < 0 )
4291 	            {
4292 	               z = 0;
4293 	            }
4294 	            /* knapsack problem is feasible:
4295 	             *   sets z = max { w : 0 <= w <= liftrhs, minweights_i[w] <= a_0 - fixedonesweight - a_{j_i}  } = liftrhs,
4296 	             *   if minweights_i[liftrhs] <= a_0 - fixedonesweight - a_{j_i}
4297 	             */
4298 	            else if( minweights[*liftrhs] <= capacity - fixedonesweight - weight )
4299 	            {
4300 	               z = *liftrhs;
4301 	            }
4302 	            /* knapsack problem is feasible:
4303 	             *   binary search to find z = max {w : 0 <= w <= liftrhs, minweights_i[w] <= a_0 - fixedonesweight - a_{j_i}}
4304 	             */
4305 	            else
4306 	            {
4307 	               assert((*liftrhs) + 1 >= minweightslen || minweights[(*liftrhs) + 1] > capacity - fixedonesweight - weight);
4308 	               left = 0;
4309 	               right = (*liftrhs) + 1;
4310 	               while( left < right - 1 )
4311 	               {
4312 	                  middle = (left + right) / 2;
4313 	                  assert(0 <= middle && middle < minweightslen);
4314 	                  if( minweights[middle] <= capacity - fixedonesweight - weight )
4315 	                     left = middle;
4316 	                  else
4317 	                     right = middle;
4318 	               }
4319 	               assert(left == right - 1);
4320 	               assert(0 <= left && left < minweightslen);
4321 	               assert(minweights[left] <= capacity - fixedonesweight - weight);
4322 	               assert(left == minweightslen - 1 || minweights[left+1] > capacity - fixedonesweight - weight);
4323 	
4324 	               /* now z = left */
4325 	               z = left;
4326 	               assert(z <= *liftrhs);
4327 	            }
4328 	
4329 	            /* calculates lifting coefficients alpha_{j_i} = liftrhs - z */
4330 	            liftcoef = (*liftrhs) - z;
4331 	            liftcoefs[liftvar] = liftcoef;
4332 	            assert(liftcoef >= 0 && liftcoef <= (*liftrhs) + 1);
4333 	
4334 		    /* updates activity of current valid inequality */
4335 	            (*cutact) += liftcoef * solvals[liftvar];
4336 	
4337 	            /* updates sum of all lifting coefficients in GUB */
4338 	            sumliftcoef += liftcoefs[liftvar];
4339 		 }
4340 	         else
4341 	            assert(gubset->gubconss[liftgubconsidx]->gubvarsstatus[k] == GUBVARSTATUS_CAPACITYEXCEEDED);
4342 	      }
4343 	      /* at least one variable is in F or R (j = number of C1 variables in current GUB) */
4344 	      assert(nliftgubvars > nliftgubC1);
4345 	
4346 	      /* activity of current valid inequality will not change if (sum of alpha_{j_i} in GUB) = 0
4347 	       * and finished and minweight table can be updated easily as only C1 variables need to be considered;
4348 	       * not needed for GF GUBs
4349 	       */
4350 	      if( sumliftcoef == 0 )
4351 	      {
4352 		 if( gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GNC1 )
4353 		 {
4354 	            weight = weights[liftgubvars[0]];
4355 	            /* update finished table and minweights table by applying special case of
4356 	             * finished[w] = MIN{finished[w], finished[w-1] + weight}, "weight" is the minimal weight of current GUB
4357 		     * minweights[w] = MIN{minweights[w], minweights[w-1] + weight}, "weight" is the minimal weight of current GUB
4358 	             */
4359 	            for( w = minweightslen-1; w >= 1; w-- )
4360 	            {
4361 	               SCIP_Longint tmpval;
4362 	
4363 	               tmpval = safeAddMinweightsGUB(finished[w-1], weight);
4364 	               finished[w] = MIN(finished[w], tmpval);
4365 	
4366 	               tmpval = safeAddMinweightsGUB(minweights[w-1], weight);
4367 	               minweights[w] = MIN(minweights[w], tmpval);
4368 	            }
4369 	         }
4370 	         else
4371 		    assert(gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GF);
4372 	
4373 	         continue;
4374 	      }
4375 	
4376 	      /* enlarges current minweights tables(finished, unfinished, minweights):
4377 	       *  from minweightlen = |gubconsGC1| + sum_{k=1,2,...,i-1}sum_{j in Q_k} alpha_j + 1 entries
4378 	       *  to                  |gubconsGC1| + sum_{k=1,2,...,i  }sum_{j in Q_k} alpha_j + 1 entries
4379 	       *  and sets minweights_i[w] = infinity for
4380 	       *  w = |gubconsGC1| + sum_{k=1,2,..,i-1}sum_{j in Q_k} alpha_j+1,..,|C1| + sum_{k=1,2,..,i}sum_{j in Q_k} alpha_j
4381 	       */
4382 	      tmplen = minweightslen; /* will be updated in enlargeMinweights() */
4383 	      tmpsize = minweightssize;
4384 	      SCIP_CALL( enlargeMinweights(scip, &unfinished, &tmplen, &tmpsize, tmplen + sumliftcoef) );
4385 	      tmplen = minweightslen;
4386 	      tmpsize = minweightssize;
4387 	      SCIP_CALL( enlargeMinweights(scip, &finished, &tmplen, &tmpsize, tmplen + sumliftcoef) );
4388 	      SCIP_CALL( enlargeMinweights(scip, &minweights, &minweightslen, &minweightssize, minweightslen + sumliftcoef) );
4389 	
4390 	      /* update finished table and minweight table;
4391 	       * note that instead of computing minweight table from updated finished and updated unfinished table again
4392 	       * (for the lifting coefficient, we had to update unfinished table and compute minweight table), we here
4393 	       * only need to update the minweight table and the updated finished in the same way (i.e., computing for minweight
4394 	       * not needed because only finished table changed at this point and the change was "adding" one weight)
4395 	       *
4396 	       * update formular for minweight table is: minweight_i+1[w] =
4397 	       *   min{ minweights_i[w], min{ minweights_i[w - alpha_k]^{+} + a_k : k in GUB_j_i } }
4398 	       * formular for finished table has the same pattern.
4399 	       */
4400 	      for( w = minweightslen-1; w >= 0; w-- )
4401 	      {
4402 	         SCIP_Longint minminweight;
4403 	         SCIP_Longint minfinished;
4404 	
4405 	         for( k = 0; k < nliftgubvars; k++ )
4406 		 {
4407 		    liftcoef = liftcoefs[liftgubvars[k]];
4408 		    weight = weights[liftgubvars[k]];
4409 	
4410 	            if( w < liftcoef )
4411 	            {
4412 		       minfinished = MIN(finished[w], weight);
4413 		       minminweight = MIN(minweights[w], weight);
4414 	
4415 	               finished[w] = minfinished;
4416 	               minweights[w] = minminweight;
4417 	            }
4418 	            else
4419 	            {
4420 	               SCIP_Longint tmpval;
4421 	
4422 	               assert(w >= liftcoef);
4423 	
4424 	               tmpval = safeAddMinweightsGUB(finished[w-liftcoef], weight);
4425 	               minfinished = MIN(finished[w], tmpval);
4426 	
4427 	               tmpval = safeAddMinweightsGUB(minweights[w-liftcoef], weight);
4428 	               minminweight = MIN(minweights[w], tmpval);
4429 	
4430 	               finished[w] = minfinished;
4431 	               minweights[w] = minminweight;
4432 	            }
4433 		 }
4434 	      }
4435 	      assert(minweights[0] == 0);
4436 	   }
4437 	   assert(ngubconsGNC1 == 0);
4438 	
4439 	   /* note: now the unfinished table no longer exists, i.e., it is "0, MAX, MAX, ..." and minweight equals to finished;
4440 	    * therefore, only work with minweight table from here on
4441 	    */
4442 	
4443 	   /* sequentially down-lifts C2 variables contained in trivial GC2 GUBs */
4444 	   for( j = 0; j < ngubconsGC2; j++ )
4445 	   {
4446 	      liftgubconsidx = gubconsGC2[j];
4447 	
4448 	      assert(liftgubconsidx >=0 && liftgubconsidx < ngubconss);
4449 	      assert(gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GC2);
4450 	      assert(gubset->gubconss[liftgubconsidx]->ngubvars == 1);
4451 	      assert(gubset->gubconss[liftgubconsidx]->gubvarsstatus[0] == GUBVARSTATUS_BELONGSTOSET_C2);
4452 	
4453 	      liftvar = gubset->gubconss[liftgubconsidx]->gubvars[0]; /* C2 GUBs contain only one variable */
4454 	      weight = weights[liftvar];
4455 	
4456 	      assert(liftvar >= 0 && liftvar < nvars);
4457 	      assert(SCIPisFeasEQ(scip, solvals[liftvar], 1.0));
4458 	      assert(weight > 0);
4459 	
4460 	      /* uses binary search to find
4461 	       *   z = max { w : 0 <= w <= |C_1| + sum_{k=1}^{i-1} alpha_{j_k}, minweights_[w] <= a_0 - fixedonesweight + a_{j_i}}
4462 	       */
4463 	      left = 0;
4464 	      right = minweightslen;
4465 	      while( left < right - 1 )
4466 	      {
4467 	         middle = (left + right) / 2;
4468 	         assert(0 <= middle && middle < minweightslen);
4469 	         if( minweights[middle] <= capacity - fixedonesweight + weight )
4470 	            left = middle;
4471 	         else
4472 	            right = middle;
4473 	      }
4474 	      assert(left == right - 1);
4475 	      assert(0 <= left && left < minweightslen);
4476 	      assert(minweights[left] <= capacity - fixedonesweight + weight);
4477 	      assert(left == minweightslen - 1 || minweights[left + 1] > capacity - fixedonesweight + weight);
4478 	
4479 	      /* now z = left */
4480 	      z = left;
4481 	      assert(z >= *liftrhs);
4482 	
4483 	      /* calculates lifting coefficients alpha_{j_i} = z - liftrhs */
4484 	      liftcoef = z - (*liftrhs);
4485 	      liftcoefs[liftvar] = liftcoef;
4486 	      assert(liftcoef >= 0);
4487 	
4488 	      /* updates sum of weights of variables fixed to one */
4489 	      fixedonesweight -= weight;
4490 	
4491 	      /* updates right-hand side of current valid inequality */
4492 	      (*liftrhs) += liftcoef;
4493 	      assert(*liftrhs >= alpha0);
4494 	
4495 	      /* minweight table and activity of current valid inequality will not change, if alpha_{j_i} = 0 */
4496 	      if( liftcoef == 0 )
4497 		 continue;
4498 	
4499 	      /* updates activity of current valid inequality */
4500 	      (*cutact) += liftcoef * solvals[liftvar];
4501 	
4502 	      /* enlarges current minweight table:
4503 	       *  from minweightlen = |gubconsGC1| + sum_{k=1,2,...,i-1}sum_{j in Q_k} alpha_j + 1 entries
4504 	       *  to                  |gubconsGC1| + sum_{k=1,2,...,i  }sum_{j in Q_k} alpha_j + 1 entries
4505 	       * and sets minweights_i[w] = infinity for
4506 	       *  w = |C1| + sum_{k=1,2,...,i-1}sum_{j in Q_k} alpha_j + 1 , ... , |C1| + sum_{k=1,2,...,i}sum_{j in Q_k} alpha_j
4507 	       */
4508 	      SCIP_CALL( enlargeMinweights(scip, &minweights, &minweightslen, &minweightssize, minweightslen + liftcoef) );
4509 	
4510 	      /* updates minweight table: minweight_i+1[w] =
4511 	       *  min{ minweights_i[w], a_{j_i}},                                 if w <  alpha_j_i
4512 	       *  min{ minweights_i[w], minweights_i[w - alpha_j_i] + a_j_i},     if w >= alpha_j_i
4513 	       */
4514 	      for( w = minweightslen - 1; w >= 0; w-- )
4515 	      {
4516 	         if( w < liftcoef )
4517 	         {
4518 	            min = MIN(minweights[w], weight);
4519 	            minweights[w] = min;
4520 	         }
4521 	         else
4522 	         {
4523 	            SCIP_Longint tmpval;
4524 	
4525 	            assert(w >= liftcoef);
4526 	
4527 	            tmpval = safeAddMinweightsGUB(minweights[w-liftcoef], weight);
4528 	            min = MIN(minweights[w], tmpval);
4529 	            minweights[w] = min;
4530 	         }
4531 	      }
4532 	   }
4533 	   assert(fixedonesweight == 0);
4534 	   assert(*liftrhs >= alpha0);
4535 	
4536 	   /* sequentially up-lifts variables in GUB constraints in GR GUBs */
4537 	   for( j = 0; j < ngubconsGR; j++ )
4538 	   {
4539 	      liftgubconsidx = gubconsGR[j];
4540 	
4541 	      assert(liftgubconsidx >=0 && liftgubconsidx < ngubconss);
4542 	      assert(gubset->gubconsstatus[liftgubconsidx] == GUBCONSSTATUS_BELONGSTOSET_GR);
4543 	
4544 	      sumliftcoef = 0;
4545 	      nliftgubvars = 0;
4546 	      for( k = 0; k < gubset->gubconss[liftgubconsidx]->ngubvars; k++ )
4547 	      {
4548 	         if(gubset->gubconss[liftgubconsidx]->gubvarsstatus[k] == GUBVARSTATUS_BELONGSTOSET_R )
4549 	         {
4550 	            liftvar = gubset->gubconss[liftgubconsidx]->gubvars[k];
4551 	            weight = weights[liftvar];
4552 	            assert(weight > 0);
4553 	            assert(liftvar >= 0 && liftvar < nvars);
4554 		    assert(capacity - weight >= 0);
4555 	            assert((*liftrhs) + 1 >= minweightslen || minweights[(*liftrhs) + 1] > capacity - weight);
4556 	
4557 	            /* put variable into array of variables in GUB that are considered for the lifting,
4558 	             *  i.e., not capacity exceeding
4559 	             */
4560 		    liftgubvars[nliftgubvars] = liftvar;
4561 	            nliftgubvars++;
4562 	
4563 	            /* sets z = max { w : 0 <= w <= liftrhs, minweights_i[w] <= a_0 - a_{j_i} } = liftrhs,
4564 	             * if minweights_i[liftrhs] <= a_0 - a_{j_i}
4565 	             */
4566 	            if( minweights[*liftrhs] <= capacity - weight )
4567 	            {
4568 	               z = *liftrhs;
4569 	            }
4570 	            /* uses binary search to find z = max { w : 0 <= w <= liftrhs, minweights_i[w] <= a_0 - a_{j_i} }
4571 	             */
4572 	            else
4573 	            {
4574 	               left = 0;
4575 	               right = (*liftrhs) + 1;
4576 	               while( left < right - 1 )
4577 	               {
4578 	                  middle = (left + right) / 2;
4579 	                  assert(0 <= middle && middle < minweightslen);
4580 	                  if( minweights[middle] <= capacity - weight )
4581 	                     left = middle;
4582 	                  else
4583 	                     right = middle;
4584 	               }
4585 	               assert(left == right - 1);
4586 	               assert(0 <= left && left < minweightslen);
4587 	               assert(minweights[left] <= capacity - weight);
4588 	               assert(left == minweightslen - 1 || minweights[left + 1] > capacity - weight);
4589 	
4590 	               /* now z = left */
4591 	               z = left;
4592 	               assert(z <= *liftrhs);
4593 	            }
4594 	            /* calculates lifting coefficients alpha_{j_i} = liftrhs - z */
4595 	            liftcoef = (*liftrhs) - z;
4596 	            liftcoefs[liftvar] = liftcoef;
4597 	            assert(liftcoef >= 0 && liftcoef <= (*liftrhs) + 1);
4598 	
4599 	            /* updates activity of current valid inequality */
4600 	            (*cutact) += liftcoef * solvals[liftvar];
4601 	
4602 	            /* updates sum of all lifting coefficients in GUB */
4603 	            sumliftcoef += liftcoefs[liftvar];
4604 	         }
4605 	         else
4606 	            assert(gubset->gubconss[liftgubconsidx]->gubvarsstatus[k] == GUBVARSTATUS_CAPACITYEXCEEDED);
4607 	      }
4608 	      assert(nliftgubvars >= 1); /* at least one variable is in R */
4609 	
4610 	      /* minweight table and activity of current valid inequality will not change if (sum of alpha_{j_i} in GUB) = 0 */
4611 	      if( sumliftcoef == 0 )
4612 		 continue;
4613 	
4614 	      /* updates minweight table: minweight_i+1[w] =
4615 	       *   min{ minweights_i[w], min{ minweights_i[w - alpha_k]^{+} + a_k : k in GUB_j_i } }
4616 	       */
4617 	      for( w = *liftrhs; w >= 0; w-- )
4618 	      {
4619 	         for( k = 0; k < nliftgubvars; k++ )
4620 	         {
4621 	            liftcoef = liftcoefs[liftgubvars[k]];
4622 	            weight = weights[liftgubvars[k]];
4623 	
4624 	            if( w < liftcoef )
4625 	            {
4626 	               min = MIN(minweights[w], weight);
4627 	               minweights[w] = min;
4628 	            }
4629 	            else
4630 	            {
4631 	               SCIP_Longint tmpval;
4632 	
4633 	               assert(w >= liftcoef);
4634 	
4635 	               tmpval = safeAddMinweightsGUB(minweights[w-liftcoef], weight);
4636 	               min = MIN(minweights[w], tmpval);
4637 	               minweights[w] = min;
4638 	            }
4639 	         }
4640 	      }
4641 	      assert(minweights[0] == 0);
4642 	   }
4643 	
4644 	   /* frees temporary memory */
4645 	   SCIPfreeBufferArray(scip, &minweights);
4646 	   SCIPfreeBufferArray(scip, &finished);
4647 	   SCIPfreeBufferArray(scip, &unfinished);
4648 	   SCIPfreeBufferArray(scip, &liftgubvars);
4649 	   SCIPfreeBufferArray(scip, &gubconsGOC1 );
4650 	   SCIPfreeBufferArray(scip, &gubconsGNC1);
4651 	
4652 	   return SCIP_OKAY;
4653 	}
4654 	
4655 	/** lifts given minimal cover inequality
4656 	 *  \f[
4657 	 *    \sum_{j \in C} x_j \leq |C| - 1
4658 	 *  \f]
4659 	 *  valid for
4660 	 *  \f[
4661 	 *    S^0 = \{ x \in {0,1}^{|C|} : \sum_{j \in C} a_j x_j \leq a_0 \}
4662 	 *  \f]
4663 	 *  to a valid inequality
4664 	 *  \f[
4665 	 *    \sum_{j \in C} x_j + \sum_{j \in N \setminus C} \alpha_j x_j \leq |C| - 1
4666 	 *  \f]
4667 	 *  for
4668 	 *  \f[
4669 	 *    S = \{ x \in {0,1}^{|N|} : \sum_{j \in N} a_j x_j \leq a_0 \};
4670 	 *  \f]
4671 	 *  uses superadditive up-lifting for the variables in \f$N \setminus C\f$.
4672 	 */
4673 	static
4674 	SCIP_RETCODE superadditiveUpLifting(
4675 	   SCIP*                 scip,               /**< SCIP data structure */
4676 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
4677 	   int                   nvars,              /**< number of variables in knapsack constraint */
4678 	   int                   ntightened,         /**< number of variables with tightened upper bound */
4679 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
4680 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
4681 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
4682 	   int*                  covervars,          /**< cover variables */
4683 	   int*                  noncovervars,       /**< noncover variables */
4684 	   int                   ncovervars,         /**< number of cover variables */
4685 	   int                   nnoncovervars,      /**< number of noncover variables */
4686 	   SCIP_Longint          coverweight,        /**< weight of cover */
4687 	   SCIP_Real*            liftcoefs,          /**< pointer to store lifting coefficient of vars in knapsack constraint */
4688 	   SCIP_Real*            cutact              /**< pointer to store activity of lifted valid inequality */
4689 	   )
4690 	{
4691 	   SCIP_Longint* maxweightsums;
4692 	   SCIP_Longint* intervalends;
4693 	   SCIP_Longint* rhos;
4694 	   SCIP_Real* sortkeys;
4695 	   SCIP_Longint lambda;
4696 	   int j;
4697 	   int h;
4698 	
4699 	   assert(scip != NULL);
4700 	   assert(vars != NULL);
4701 	   assert(nvars >= 0);
4702 	   assert(weights != NULL);
4703 	   assert(capacity >= 0);
4704 	   assert(solvals != NULL);
4705 	   assert(covervars != NULL);
4706 	   assert(noncovervars != NULL);
4707 	   assert(ncovervars > 0 && ncovervars <= nvars);
4708 	   assert(nnoncovervars >= 0 && nnoncovervars <= nvars - ntightened);
4709 	   assert(ncovervars + nnoncovervars == nvars - ntightened);
4710 	   assert(liftcoefs != NULL);
4711 	   assert(cutact != NULL);
4712 	
4713 	   /* allocates temporary memory */
4714 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeys, ncovervars) );
4715 	   SCIP_CALL( SCIPallocBufferArray(scip, &maxweightsums, ncovervars + 1) );
4716 	   SCIP_CALL( SCIPallocBufferArray(scip, &intervalends, ncovervars) );
4717 	   SCIP_CALL( SCIPallocBufferArray(scip, &rhos, ncovervars) );
4718 	
4719 	   /* initializes data structures */
4720 	   BMSclearMemoryArray(liftcoefs, nvars);
4721 	   *cutact = 0.0;
4722 	
4723 	   /* sets lifting coefficient of variables in C, sorts variables in C such that a_1 >= a_2 >= ... >= a_|C|
4724 	    * and calculates activity of current valid inequality
4725 	    */
4726 	   for( j = 0; j < ncovervars; j++ )
4727 	   {
4728 	      assert(liftcoefs[covervars[j]] == 0.0);
4729 	      liftcoefs[covervars[j]] = 1.0;
4730 	      sortkeys[j] = (SCIP_Real) weights[covervars[j]];
4731 	      (*cutact) += solvals[covervars[j]];
4732 	   }
4733 	   SCIPsortDownRealInt(sortkeys, covervars, ncovervars);
4734 	
4735 	   /* calculates weight excess of cover C */
4736 	   lambda = coverweight - capacity;
4737 	   assert(lambda > 0);
4738 	
4739 	   /* calculates A_h for h = 0,...,|C|, I_h for h = 1,...,|C| and rho_h for h = 1,...,|C| */
4740 	   maxweightsums[0] = 0;
4741 	   for( h = 1; h <= ncovervars; h++ )
4742 	   {
4743 	      maxweightsums[h] = maxweightsums[h-1] + weights[covervars[h-1]];
4744 	      intervalends[h-1] = maxweightsums[h] - lambda;
4745 	      rhos[h-1] = MAX(0, weights[covervars[h-1]] - weights[covervars[0]] + lambda);
4746 	   }
4747 	
4748 	   /* sorts variables in N\C such that a_{j_1} <= a_{j_2} <= ... <= a_{j_t} */
4749 	   for( j = 0; j < nnoncovervars; j++ )
4750 	      sortkeys[j] = (SCIP_Real) (weights[noncovervars[j]]);
4751 	   SCIPsortRealInt(sortkeys, noncovervars, nnoncovervars);
4752 	
4753 	   /* calculates lifting coefficient for all variables in N\C */
4754 	   h = 0;
4755 	   for( j = 0; j < nnoncovervars; j++ )
4756 	   {
4757 	      int liftvar;
4758 	      SCIP_Longint weight;
4759 	      SCIP_Real liftcoef;
4760 	
4761 	      liftvar = noncovervars[j];
4762 	      weight = weights[liftvar];
4763 	
4764 	      while( intervalends[h] < weight )
4765 	         h++;
4766 	
4767 	      if( h == 0 )
4768 	         liftcoef = h;
4769 	      else
4770 	      {
4771 	         if( weight <= intervalends[h-1] + rhos[h] )
4772 	         {
4773 	            SCIP_Real tmp1;
4774 	            SCIP_Real tmp2;
4775 	            tmp1 =  (SCIP_Real) (intervalends[h-1] + rhos[h] - weight);
4776 	            tmp2 =  (SCIP_Real) rhos[1];
4777 	            liftcoef = h - ( tmp1 / tmp2 );
4778 	         }
4779 	         else
4780 	            liftcoef = h;
4781 	      }
4782 	
4783 	      /* sets lifting coefficient */
4784 	      assert(liftcoefs[liftvar] == 0.0);
4785 	      liftcoefs[liftvar] = liftcoef;
4786 	
4787 	      /* updates activity of current valid inequality */
4788 	      (*cutact) += liftcoef * solvals[liftvar];
4789 	   }
4790 	
4791 	   /* frees temporary memory */
4792 	   SCIPfreeBufferArray(scip, &rhos);
4793 	   SCIPfreeBufferArray(scip, &intervalends);
4794 	   SCIPfreeBufferArray(scip, &maxweightsums);
4795 	   SCIPfreeBufferArray(scip, &sortkeys);
4796 	
4797 	   return SCIP_OKAY;
4798 	}
4799 	
4800 	
4801 	/** separates lifted minimal cover inequalities using sequential up- and down-lifting and GUB information, if wanted, for
4802 	 *  given knapsack problem
4803 	*/
4804 	static
4805 	SCIP_RETCODE separateSequLiftedMinimalCoverInequality(
4806 	   SCIP*                 scip,               /**< SCIP data structure */
4807 	   SCIP_CONS*            cons,               /**< originating constraint of the knapsack problem, or NULL */
4808 	   SCIP_SEPA*            sepa,               /**< originating separator of the knapsack problem, or NULL */
4809 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
4810 	   int                   nvars,              /**< number of variables in knapsack constraint */
4811 	   int                   ntightened,         /**< number of variables with tightened upper bound */
4812 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
4813 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
4814 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
4815 	   int*                  mincovervars,       /**< mincover variables */
4816 	   int*                  nonmincovervars,    /**< nonmincover variables */
4817 	   int                   nmincovervars,      /**< number of mincover variables */
4818 	   int                   nnonmincovervars,   /**< number of nonmincover variables */
4819 	   SCIP_SOL*             sol,                /**< primal SCIP solution to separate, NULL for current LP solution */
4820 	   SCIP_GUBSET*          gubset,             /**< GUB set data structure, NULL if no GUB information should be used */
4821 	   SCIP_Bool*            cutoff,             /**< pointer to store whether a cutoff has been detected */
4822 	   int*                  ncuts               /**< pointer to add up the number of found cuts */
4823 	   )
4824 	{
4825 	   int* varsC1;
4826 	   int* varsC2;
4827 	   int* varsF;
4828 	   int* varsR;
4829 	   int nvarsC1;
4830 	   int nvarsC2;
4831 	   int nvarsF;
4832 	   int nvarsR;
4833 	   SCIP_Real cutact;
4834 	   int* liftcoefs;
4835 	   int liftrhs;
4836 	
4837 	   assert( cutoff != NULL );
4838 	   *cutoff = FALSE;
4839 	
4840 	   /* allocates temporary memory */
4841 	   SCIP_CALL( SCIPallocBufferArray(scip, &varsC1, nvars) );
4842 	   SCIP_CALL( SCIPallocBufferArray(scip, &varsC2, nvars) );
4843 	   SCIP_CALL( SCIPallocBufferArray(scip, &varsF, nvars) );
4844 	   SCIP_CALL( SCIPallocBufferArray(scip, &varsR, nvars) );
4845 	   SCIP_CALL( SCIPallocBufferArray(scip, &liftcoefs, nvars) );
4846 	
4847 	   /* gets partition (C_1,C_2) of C, i.e. C_1 & C_2 = C and C_1 cap C_2 = emptyset, with C_1 not empty; chooses partition
4848 	    * as follows
4849 	    *   C_2 = { j in C : x*_j = 1 } and
4850 	    *   C_1 = C\C_2
4851 	    */
4852 	   getPartitionCovervars(scip, solvals, mincovervars, nmincovervars, varsC1, varsC2, &nvarsC1, &nvarsC2);
4853 	   assert(nvarsC1 + nvarsC2 == nmincovervars);
4854 	   assert(nmincovervars > 0);
4855 	   assert(nvarsC1 >= 0); /* nvarsC1 > 0 does not always hold, because relaxed knapsack conss may already be violated */
4856 	
4857 	   /* changes partition (C_1,C_2) of minimal cover C, if |C1| = 1, by moving one variable from C2 to C1 */
4858 	   if( nvarsC1 < 2 && nvarsC2 > 0)
4859 	   {
4860 	      SCIP_CALL( changePartitionCovervars(scip, weights, varsC1, varsC2, &nvarsC1, &nvarsC2) );
4861 	      assert(nvarsC1 >= 1);
4862 	   }
4863 	   assert(nvarsC2 == 0 || nvarsC1 >= 1);
4864 	
4865 	   /* gets partition (F,R) of N\C, i.e. F & R = N\C and F cap R = emptyset; chooses partition as follows
4866 	    *   R = { j in N\C : x*_j = 0 } and
4867 	    *   F = (N\C)\F
4868 	    */
4869 	   getPartitionNoncovervars(scip, solvals, nonmincovervars, nnonmincovervars, varsF, varsR, &nvarsF, &nvarsR);
4870 	   assert(nvarsF + nvarsR == nnonmincovervars);
4871 	   assert(nvarsC1 + nvarsC2 + nvarsF + nvarsR == nvars - ntightened);
4872 	
4873 	   /* lift cuts without GUB information */
4874 	   if( gubset == NULL )
4875 	   {
4876 	      /* sorts variables in F, C_2, R according to the second level lifting sequence that will be used in the sequential
4877 	       * lifting procedure
4878 	       */
4879 	      SCIP_CALL( getLiftingSequence(scip, solvals, weights, varsF, varsC2, varsR, nvarsF, nvarsC2, nvarsR) );
4880 	
4881 	      /* lifts minimal cover inequality sum_{j in C_1} x_j <= |C_1| - 1 valid for
4882 	       *
4883 	       *    S^0 = { x in {0,1}^|C_1| : sum_{j in C_1} a_j x_j <= a_0 - sum_{j in C_2} a_j }
4884 	       *
4885 	       * to a valid inequality sum_{j in C_1} x_j + sum_{j in N\C_1} alpha_j x_j <= |C_1| - 1 + sum_{j in C_2} alpha_j for
4886 	       *
4887 	       *      S = { x in {0,1}^|N|   : sum_{j in N}   a_j x_j <= a_0 },
4888 	       *
4889 	       * uses sequential up-lifting for the variables in F, sequential down-lifting for the variable in C_2 and sequential
4890 	       * up-lifting for the variables in R according to the second level lifting sequence
4891 	       */
4892 	      SCIP_CALL( sequentialUpAndDownLifting(scip, vars, nvars, ntightened, weights, capacity, solvals, varsC1, varsC2,
4893 	            varsF, varsR, nvarsC1, nvarsC2, nvarsF, nvarsR, nvarsC1 - 1, liftcoefs, &cutact, &liftrhs) );
4894 	   }
4895 	   /* lift cuts with GUB information */
4896 	   else
4897 	   {
4898 	      int* gubconsGC1;
4899 	      int* gubconsGC2;
4900 	      int* gubconsGFC1;
4901 	      int* gubconsGR;
4902 	      int ngubconsGC1;
4903 	      int ngubconsGC2;
4904 	      int ngubconsGFC1;
4905 	      int ngubconsGR;
4906 	      int ngubconss;
4907 	      int nconstightened;
4908 	      int maxgubvarssize;
4909 	
4910 	      assert(nvars == gubset->nvars);
4911 	
4912 	      ngubconsGC1 = 0;
4913 	      ngubconsGC2 = 0;
4914 	      ngubconsGFC1 = 0;
4915 	      ngubconsGR = 0;
4916 	      ngubconss = gubset->ngubconss;
4917 	      nconstightened = 0;
4918 	      maxgubvarssize = 0;
4919 	
4920 	      /* allocates temporary memory */
4921 	      SCIP_CALL( SCIPallocBufferArray(scip, &gubconsGC1, ngubconss) );
4922 	      SCIP_CALL( SCIPallocBufferArray(scip, &gubconsGC2, ngubconss) );
4923 	      SCIP_CALL( SCIPallocBufferArray(scip, &gubconsGFC1, ngubconss) );
4924 	      SCIP_CALL( SCIPallocBufferArray(scip, &gubconsGR, ngubconss) );
4925 	
4926 	      /* categorizies GUBs of knapsack GUB partion into GOC1, GNC1, GF, GC2, and GR and computes a lifting sequence of
4927 	       * the GUBs for the sequential GUB wise lifting procedure
4928 	       */
4929 	      SCIP_CALL( getLiftingSequenceGUB(scip, gubset, solvals, weights, varsC1, varsC2, varsF, varsR, nvarsC1,
4930 	            nvarsC2, nvarsF, nvarsR, gubconsGC1, gubconsGC2, gubconsGFC1, gubconsGR, &ngubconsGC1, &ngubconsGC2,
4931 	            &ngubconsGFC1, &ngubconsGR, &nconstightened, &maxgubvarssize) );
4932 	
4933 	      /* lifts minimal cover inequality sum_{j in C_1} x_j <= |C_1| - 1 valid for
4934 	       *
4935 	       *    S^0 = { x in {0,1}^|C_1| : sum_{j in C_1} a_j x_j <= a_0 - sum_{j in C_2} a_j,
4936 	       *                               sum_{j in Q_i} x_j <= 1, forall i in I }
4937 	       *
4938 	       * to a valid inequality sum_{j in C_1} x_j + sum_{j in N\C_1} alpha_j x_j <= |C_1| - 1 + sum_{j in C_2} alpha_j for
4939 	       *
4940 	       *      S = { x in {0,1}^|N|   : sum_{j in N}   a_j x_j <= a_0, sum_{j in Q_i} x_j <= 1, forall i in I },
4941 	       *
4942 	       *  uses sequential up-lifting   for the variables in GUB constraints in gubconsGFC1,
4943 	       *       sequential down-lifting for the variables in GUB constraints in gubconsGC2, and
4944 	       *       sequential up-lifting   for the variabels in GUB constraints in gubconsGR.
4945 	       */
4946 	      SCIP_CALL( sequentialUpAndDownLiftingGUB(scip, gubset, vars, nconstightened, weights, capacity, solvals, gubconsGC1,
4947 	            gubconsGC2, gubconsGFC1, gubconsGR, ngubconsGC1, ngubconsGC2, ngubconsGFC1, ngubconsGR,
4948 	            MIN(nvarsC1 - 1, ngubconsGC1), liftcoefs, &cutact, &liftrhs, maxgubvarssize) );
4949 	
4950 	      /* frees temporary memory */
4951 	      SCIPfreeBufferArray(scip, &gubconsGR);
4952 	      SCIPfreeBufferArray(scip, &gubconsGFC1);
4953 	      SCIPfreeBufferArray(scip, &gubconsGC2);
4954 	      SCIPfreeBufferArray(scip, &gubconsGC1);
4955 	   }
4956 	
4957 	   /* checks, if lifting yielded a violated cut */
4958 	   if( SCIPisEfficacious(scip, (cutact - liftrhs)/sqrt((SCIP_Real)MAX(liftrhs, 1))) )
4959 	   {
4960 	      SCIP_ROW* row;
4961 	      char name[SCIP_MAXSTRLEN];
4962 	      int j;
4963 	
4964 	      /* creates LP row */
4965 	      assert( cons == NULL || sepa == NULL );
4966 	      if ( cons != NULL )
4967 	      {
4968 	         (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_mcseq%" SCIP_LONGINT_FORMAT "", SCIPconsGetName(cons), SCIPconshdlrGetNCutsFound(SCIPconsGetHdlr(cons)));
4969 	         SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, name, -SCIPinfinity(scip), (SCIP_Real)liftrhs,
4970 	            cons != NULL ? SCIPconsIsLocal(cons) : FALSE, FALSE,
4971 	            cons != NULL ? SCIPconsIsRemovable(cons) : TRUE) );
4972 	      }
4973 	      else if ( sepa != NULL )
4974 	      {
4975 	         (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_mcseq_%" SCIP_LONGINT_FORMAT "", SCIPsepaGetName(sepa), SCIPsepaGetNCutsFound(sepa));
4976 	         SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &row, sepa, name, -SCIPinfinity(scip), (SCIP_Real)liftrhs, FALSE, FALSE, TRUE) );
4977 	      }
4978 	      else
4979 	      {
4980 	         (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "nn_mcseq_%d", *ncuts);
4981 	         SCIP_CALL( SCIPcreateEmptyRowUnspec(scip, &row, name, -SCIPinfinity(scip), (SCIP_Real)liftrhs, FALSE, FALSE, TRUE) );
4982 	      }
4983 	
4984 	      /* adds all variables in the knapsack constraint with calculated lifting coefficient to the cut */
4985 	      SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
4986 	      assert(nvarsC1 + nvarsC2 + nvarsF + nvarsR == nvars - ntightened);
4987 	      for( j = 0; j < nvarsC1; j++ )
4988 	      {
4989 	         SCIP_CALL( SCIPaddVarToRow(scip, row, vars[varsC1[j]], 1.0) );
4990 	      }
4991 	      for( j = 0; j < nvarsC2; j++ )
4992 	      {
4993 	         if( liftcoefs[varsC2[j]] > 0 )
4994 	         {
4995 	            SCIP_CALL( SCIPaddVarToRow(scip, row, vars[varsC2[j]], (SCIP_Real)liftcoefs[varsC2[j]]) );
4996 	         }
4997 	      }
4998 	      for( j = 0; j < nvarsF; j++ )
4999 	      {
5000 	         if( liftcoefs[varsF[j]] > 0 )
5001 	         {
5002 	            SCIP_CALL( SCIPaddVarToRow(scip, row, vars[varsF[j]], (SCIP_Real)liftcoefs[varsF[j]]) );
5003 	         }
5004 	      }
5005 	      for( j = 0; j < nvarsR; j++ )
5006 	      {
5007 	         if( liftcoefs[varsR[j]] > 0 )
5008 	         {
5009 	            SCIP_CALL( SCIPaddVarToRow(scip, row, vars[varsR[j]], (SCIP_Real)liftcoefs[varsR[j]]) );
5010 	         }
5011 	      }
5012 	      SCIP_CALL( SCIPflushRowExtensions(scip, row) );
5013 	
5014 	      /* checks, if cut is violated enough */
5015 	      if( SCIPisCutEfficacious(scip, sol, row) )
5016 	      {
5017 	         if( cons != NULL )
5018 	         {
5019 	            SCIP_CALL( SCIPresetConsAge(scip, cons) );
5020 	         }
5021 	         SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
5022 	         (*ncuts)++;
5023 	      }
5024 	      SCIP_CALL( SCIPreleaseRow(scip, &row) );
5025 	   }
5026 	
5027 	   /* frees temporary memory */
5028 	   SCIPfreeBufferArray(scip, &liftcoefs);
5029 	   SCIPfreeBufferArray(scip, &varsR);
5030 	   SCIPfreeBufferArray(scip, &varsF);
5031 	   SCIPfreeBufferArray(scip, &varsC2);
5032 	   SCIPfreeBufferArray(scip, &varsC1);
5033 	
5034 	   return SCIP_OKAY;
5035 	}
5036 	
5037 	/** separates lifted extended weight inequalities using sequential up- and down-lifting for given knapsack problem */
5038 	static
5039 	SCIP_RETCODE separateSequLiftedExtendedWeightInequality(
5040 	   SCIP*                 scip,               /**< SCIP data structure */
5041 	   SCIP_CONS*            cons,               /**< constraint that originates the knapsack problem, or NULL */
5042 	   SCIP_SEPA*            sepa,               /**< originating separator of the knapsack problem, or NULL */
5043 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
5044 	   int                   nvars,              /**< number of variables in knapsack constraint */
5045 	   int                   ntightened,         /**< number of variables with tightened upper bound */
5046 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
5047 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
5048 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
5049 	   int*                  feassetvars,        /**< variables in feasible set */
5050 	   int*                  nonfeassetvars,     /**< variables not in feasible set */
5051 	   int                   nfeassetvars,       /**< number of variables in feasible set */
5052 	   int                   nnonfeassetvars,    /**< number of variables not in feasible set */
5053 	   SCIP_SOL*             sol,                /**< primal SCIP solution to separate, NULL for current LP solution */
5054 	   SCIP_Bool*            cutoff,             /**< whether a cutoff has been detected */
5055 	   int*                  ncuts               /**< pointer to add up the number of found cuts */
5056 	   )
5057 	{
5058 	   int* varsT1;
5059 	   int* varsT2;
5060 	   int* varsF;
5061 	   int* varsR;
5062 	   int* liftcoefs;
5063 	   SCIP_Real cutact;
5064 	   int nvarsT1;
5065 	   int nvarsT2;
5066 	   int nvarsF;
5067 	   int nvarsR;
5068 	   int liftrhs;
5069 	   int j;
5070 	
5071 	   assert( cutoff != NULL );
5072 	   *cutoff = FALSE;
5073 	
5074 	   /* allocates temporary memory */
5075 	   SCIP_CALL( SCIPallocBufferArray(scip, &varsT1, nvars) );
5076 	   SCIP_CALL( SCIPallocBufferArray(scip, &varsT2, nvars) );
5077 	   SCIP_CALL( SCIPallocBufferArray(scip, &varsF, nvars) );
5078 	   SCIP_CALL( SCIPallocBufferArray(scip, &varsR, nvars) );
5079 	   SCIP_CALL( SCIPallocBufferArray(scip, &liftcoefs, nvars) );
5080 	
5081 	   /* gets partition (T_1,T_2) of T, i.e. T_1 & T_2 = T and T_1 cap T_2 = emptyset, with T_1 not empty; chooses partition
5082 	    * as follows
5083 	    *   T_2 = { j in T : x*_j = 1 } and
5084 	    *   T_1 = T\T_2
5085 	    */
5086 	   getPartitionCovervars(scip, solvals, feassetvars, nfeassetvars, varsT1, varsT2, &nvarsT1, &nvarsT2);
5087 	   assert(nvarsT1 + nvarsT2 == nfeassetvars);
5088 	
5089 	   /* changes partition (T_1,T_2) of feasible set T, if |T1| = 0, by moving one variable from T2 to T1 */
5090 	   if( nvarsT1 == 0 && nvarsT2 > 0)
5091 	   {
5092 	      SCIP_CALL( changePartitionFeasiblesetvars(scip, weights, varsT1, varsT2, &nvarsT1, &nvarsT2) );
5093 	      assert(nvarsT1 == 1);
5094 	   }
5095 	   assert(nvarsT2 == 0 || nvarsT1 > 0);
5096 	
5097 	   /* gets partition (F,R) of N\T, i.e. F & R = N\T and F cap R = emptyset; chooses partition as follows
5098 	    *   R = { j in N\T : x*_j = 0 } and
5099 	    *   F = (N\T)\F
5100 	    */
5101 	   getPartitionNoncovervars(scip, solvals, nonfeassetvars, nnonfeassetvars, varsF, varsR, &nvarsF, &nvarsR);
5102 	   assert(nvarsF + nvarsR == nnonfeassetvars);
5103 	   assert(nvarsT1 + nvarsT2 + nvarsF + nvarsR == nvars - ntightened);
5104 	
5105 	   /* sorts variables in F, T_2, and R according to the second level lifting sequence that will be used in the sequential
5106 	    * lifting procedure (the variable removed last from the initial cover does not have to be lifted first, therefore it
5107 	    * is included in the sorting routine)
5108 	    */
5109 	   SCIP_CALL( getLiftingSequence(scip, solvals, weights, varsF, varsT2, varsR, nvarsF, nvarsT2, nvarsR) );
5110 	
5111 	   /* lifts extended weight inequality sum_{j in T_1} x_j <= |T_1| valid for
5112 	    *
5113 	    *    S^0 = { x in {0,1}^|T_1| : sum_{j in T_1} a_j x_j <= a_0 - sum_{j in T_2} a_j }
5114 	    *
5115 	    * to a valid inequality sum_{j in T_1} x_j + sum_{j in N\T_1} alpha_j x_j <= |T_1| + sum_{j in T_2} alpha_j for
5116 	    *
5117 	    *      S = { x in {0,1}^|N|   : sum_{j in N}   a_j x_j <= a_0 },
5118 	    *
5119 	    * uses sequential up-lifting for the variables in F, sequential down-lifting for the variable in T_2 and sequential
5120 	    * up-lifting for the variabels in R according to the second level lifting sequence
5121 	    */
5122 	   SCIP_CALL( sequentialUpAndDownLifting(scip, vars, nvars, ntightened, weights, capacity, solvals, varsT1, varsT2, varsF, varsR,
5123 	         nvarsT1, nvarsT2, nvarsF, nvarsR, nvarsT1, liftcoefs, &cutact, &liftrhs) );
5124 	
5125 	   /* checks, if lifting yielded a violated cut */
5126 	   if( SCIPisEfficacious(scip, (cutact - liftrhs)/sqrt((SCIP_Real)MAX(liftrhs, 1))) )
5127 	   {
5128 	      SCIP_ROW* row;
5129 	      char name[SCIP_MAXSTRLEN];
5130 	
5131 	      /* creates LP row */
5132 	      assert( cons == NULL || sepa == NULL );
5133 	      if( cons != NULL )
5134 	      {
5135 	         (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_ewseq%" SCIP_LONGINT_FORMAT "", SCIPconsGetName(cons), SCIPconshdlrGetNCutsFound(SCIPconsGetHdlr(cons)));
5136 	         SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, SCIPconsGetHdlr(cons), name, -SCIPinfinity(scip), (SCIP_Real)liftrhs,
5137 	               cons != NULL ? SCIPconsIsLocal(cons) : FALSE, FALSE,
5138 	               cons != NULL ? SCIPconsIsRemovable(cons) : TRUE) );
5139 	      }
5140 	      else if ( sepa != NULL )
5141 	      {
5142 	         (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_ewseq_%" SCIP_LONGINT_FORMAT "", SCIPsepaGetName(sepa), SCIPsepaGetNCutsFound(sepa));
5143 	         SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &row, sepa, name, -SCIPinfinity(scip), (SCIP_Real)liftrhs, FALSE, FALSE, TRUE) );
5144 	      }
5145 	      else
5146 	      {
5147 	         (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "nn_ewseq_%d", *ncuts);
5148 	         SCIP_CALL( SCIPcreateEmptyRowUnspec(scip, &row, name, -SCIPinfinity(scip), (SCIP_Real)liftrhs, FALSE, FALSE, TRUE) );
5149 	      }
5150 	
5151 	      /* adds all variables in the knapsack constraint with calculated lifting coefficient to the cut */
5152 	      SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
5153 	      assert(nvarsT1 + nvarsT2 + nvarsF + nvarsR == nvars - ntightened);
5154 	      for( j = 0; j < nvarsT1; j++ )
5155 	      {
5156 	         SCIP_CALL( SCIPaddVarToRow(scip, row, vars[varsT1[j]], 1.0) );
5157 	      }
5158 	      for( j = 0; j < nvarsT2; j++ )
5159 	      {
5160 	         if( liftcoefs[varsT2[j]] > 0 )
5161 	         {
5162 	            SCIP_CALL( SCIPaddVarToRow(scip, row, vars[varsT2[j]], (SCIP_Real)liftcoefs[varsT2[j]]) );
5163 	         }
5164 	      }
5165 	      for( j = 0; j < nvarsF; j++ )
5166 	      {
5167 	         if( liftcoefs[varsF[j]] > 0 )
5168 	         {
5169 	            SCIP_CALL( SCIPaddVarToRow(scip, row, vars[varsF[j]], (SCIP_Real)liftcoefs[varsF[j]]) );
5170 	         }
5171 	      }
5172 	      for( j = 0; j < nvarsR; j++ )
5173 	      {
5174 	         if( liftcoefs[varsR[j]] > 0 )
5175 	         {
5176 	            SCIP_CALL( SCIPaddVarToRow(scip, row, vars[varsR[j]], (SCIP_Real)liftcoefs[varsR[j]]) );
5177 	         }
5178 	      }
5179 	      SCIP_CALL( SCIPflushRowExtensions(scip, row) );
5180 	
5181 	      /* checks, if cut is violated enough */
5182 	      if( SCIPisCutEfficacious(scip, sol, row) )
5183 	      {
5184 	         if( cons != NULL )
5185 	         {
5186 	            SCIP_CALL( SCIPresetConsAge(scip, cons) );
5187 	         }
5188 	         SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
5189 	         (*ncuts)++;
5190 	      }
5191 	      SCIP_CALL( SCIPreleaseRow(scip, &row) );
5192 	   }
5193 	
5194 	   /* frees temporary memory */
5195 	   SCIPfreeBufferArray(scip, &liftcoefs);
5196 	   SCIPfreeBufferArray(scip, &varsR);
5197 	   SCIPfreeBufferArray(scip, &varsF);
5198 	   SCIPfreeBufferArray(scip, &varsT2);
5199 	   SCIPfreeBufferArray(scip, &varsT1);
5200 	
5201 	   return SCIP_OKAY;
5202 	}
5203 	
5204 	/** separates lifted minimal cover inequalities using superadditive up-lifting for given knapsack problem */
5205 	static
5206 	SCIP_RETCODE separateSupLiftedMinimalCoverInequality(
5207 	   SCIP*                 scip,               /**< SCIP data structure */
5208 	   SCIP_CONS*            cons,               /**< constraint that originates the knapsack problem, or NULL */
5209 	   SCIP_SEPA*            sepa,               /**< originating separator of the knapsack problem, or NULL */
5210 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
5211 	   int                   nvars,              /**< number of variables in knapsack constraint */
5212 	   int                   ntightened,         /**< number of variables with tightened upper bound */
5213 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
5214 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
5215 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
5216 	   int*                  mincovervars,       /**< mincover variables */
5217 	   int*                  nonmincovervars,    /**< nonmincover variables */
5218 	   int                   nmincovervars,      /**< number of mincover variables */
5219 	   int                   nnonmincovervars,   /**< number of nonmincover variables */
5220 	   SCIP_Longint          mincoverweight,     /**< weight of minimal cover */
5221 	   SCIP_SOL*             sol,                /**< primal SCIP solution to separate, NULL for current LP solution */
5222 	   SCIP_Bool*            cutoff,             /**< whether a cutoff has been detected */
5223 	   int*                  ncuts               /**< pointer to add up the number of found cuts */
5224 	   )
5225 	{
5226 	   SCIP_Real* realliftcoefs;
5227 	   SCIP_Real cutact;
5228 	   int liftrhs;
5229 	
5230 	   assert( cutoff != NULL );
5231 	   *cutoff = FALSE;
5232 	   cutact = 0.0;
5233 	
5234 	   /* allocates temporary memory */
5235 	   SCIP_CALL( SCIPallocBufferArray(scip, &realliftcoefs, nvars) );
5236 	
5237 	   /* lifts minimal cover inequality sum_{j in C} x_j <= |C| - 1 valid for
5238 	    *
5239 	    *    S^0 = { x in {0,1}^|C| : sum_{j in C} a_j x_j <= a_0 }
5240 	    *
5241 	    * to a valid inequality sum_{j in C} x_j + sum_{j in N\C} alpha_j x_j <= |C| - 1 for
5242 	    *
5243 	    *      S = { x in {0,1}^|N|   : sum_{j in N}   a_j x_j <= a_0 },
5244 	    *
5245 	    * uses superadditive up-lifting for the variables in N\C.
5246 	    */
5247 	   SCIP_CALL( superadditiveUpLifting(scip, vars, nvars, ntightened, weights, capacity, solvals, mincovervars,
5248 	         nonmincovervars, nmincovervars, nnonmincovervars, mincoverweight, realliftcoefs, &cutact) );
5249 	   liftrhs = nmincovervars - 1;
5250 	
5251 	   /* checks, if lifting yielded a violated cut */
5252 	   if( SCIPisEfficacious(scip, (cutact - liftrhs)/sqrt((SCIP_Real)MAX(liftrhs, 1))) )
5253 	   {
5254 	      SCIP_ROW* row;
5255 	      char name[SCIP_MAXSTRLEN];
5256 	      int j;
5257 	
5258 	      /* creates LP row */
5259 	      assert( cons == NULL || sepa == NULL );
5260 	      if ( cons != NULL )
5261 	      {
5262 	         (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_mcsup%" SCIP_LONGINT_FORMAT "", SCIPconsGetName(cons), SCIPconshdlrGetNCutsFound(SCIPconsGetHdlr(cons)));
5263 	         SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, SCIPconsGetHdlr(cons), name, -SCIPinfinity(scip), (SCIP_Real)liftrhs,
5264 	               cons != NULL ? SCIPconsIsLocal(cons) : FALSE, FALSE,
5265 	               cons != NULL ? SCIPconsIsRemovable(cons) : TRUE) );
5266 	      }
5267 	      else if ( sepa != NULL )
5268 	      {
5269 	         (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_mcsup%" SCIP_LONGINT_FORMAT "", SCIPsepaGetName(sepa), SCIPsepaGetNCutsFound(sepa));
5270 	         SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &row, sepa, name, -SCIPinfinity(scip), (SCIP_Real)liftrhs, FALSE, FALSE, TRUE) );
5271 	      }
5272 	      else
5273 	      {
5274 	         (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "nn_mcsup_%d", *ncuts);
5275 	         SCIP_CALL( SCIPcreateEmptyRowUnspec(scip, &row, name, -SCIPinfinity(scip), (SCIP_Real)liftrhs, FALSE, FALSE, TRUE) );
5276 	      }
5277 	
5278 	      /* adds all variables in the knapsack constraint with calculated lifting coefficient to the cut */
5279 	      SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
5280 	      assert(nmincovervars + nnonmincovervars == nvars - ntightened);
5281 	      for( j = 0; j < nmincovervars; j++ )
5282 	      {
5283 	         SCIP_CALL( SCIPaddVarToRow(scip, row, vars[mincovervars[j]], 1.0) );
5284 	      }
5285 	      for( j = 0; j < nnonmincovervars; j++ )
5286 	      {
5287 	         assert(SCIPisFeasGE(scip, realliftcoefs[nonmincovervars[j]], 0.0));
5288 	         if( SCIPisFeasGT(scip, realliftcoefs[nonmincovervars[j]], 0.0) )
5289 	         {
5290 	            SCIP_CALL( SCIPaddVarToRow(scip, row, vars[nonmincovervars[j]], realliftcoefs[nonmincovervars[j]]) );
5291 	         }
5292 	      }
5293 	      SCIP_CALL( SCIPflushRowExtensions(scip, row) );
5294 	
5295 	      /* checks, if cut is violated enough */
5296 	      if( SCIPisCutEfficacious(scip, sol, row) )
5297 	      {
5298 	         if( cons != NULL )
5299 	         {
5300 	            SCIP_CALL( SCIPresetConsAge(scip, cons) );
5301 	         }
5302 	         SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
5303 	         (*ncuts)++;
5304 	      }
5305 	      SCIP_CALL( SCIPreleaseRow(scip, &row) );
5306 	   }
5307 	
5308 	   /* frees temporary memory */
5309 	   SCIPfreeBufferArray(scip, &realliftcoefs);
5310 	
5311 	   return SCIP_OKAY;
5312 	}
5313 	
5314 	/** converts given cover C to a minimal cover by removing variables in the reverse order in which the variables were chosen
5315 	 *  to be in C, i.e. in the order of non-increasing (1 - x*_j)/a_j, if the transformed separation problem was used to find
5316 	 *  C and in the order of non-increasing (1 - x*_j), if the modified transformed separation problem was used to find C;
5317 	 *  note that all variables with x*_j = 1 will be removed last
5318 	 */
5319 	static
5320 	SCIP_RETCODE makeCoverMinimal(
5321 	   SCIP*                 scip,               /**< SCIP data structure */
5322 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
5323 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
5324 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
5325 	   int*                  covervars,          /**< pointer to store cover variables */
5326 	   int*                  noncovervars,       /**< pointer to store noncover variables */
5327 	   int*                  ncovervars,         /**< pointer to store number of cover variables */
5328 	   int*                  nnoncovervars,      /**< pointer to store number of noncover variables */
5329 	   SCIP_Longint*         coverweight,        /**< pointer to store weight of cover */
5330 	   SCIP_Bool             modtransused        /**< TRUE if mod trans sepa prob was used to find cover */
5331 	   )
5332 	{
5333 	   SORTKEYPAIR** sortkeypairs;
5334 	   SORTKEYPAIR** sortkeypairssorted;
5335 	   SCIP_Longint minweight;
5336 	   int nsortkeypairs;
5337 	   int minweightidx;
5338 	   int j;
5339 	   int k;
5340 	
5341 	   assert(scip != NULL);
5342 	   assert(covervars != NULL);
5343 	   assert(noncovervars != NULL);
5344 	   assert(ncovervars != NULL);
5345 	   assert(*ncovervars > 0);
5346 	   assert(nnoncovervars != NULL);
5347 	   assert(*nnoncovervars >= 0);
5348 	   assert(coverweight != NULL);
5349 	   assert(*coverweight > 0);
5350 	   assert(*coverweight > capacity);
5351 	
5352 	   /* allocates temporary memory; we need two arrays for the keypairs in order to be able to free them in the correct
5353 	    * order */
5354 	   nsortkeypairs = *ncovervars;
5355 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeypairs, nsortkeypairs) );
5356 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeypairssorted, nsortkeypairs) );
5357 	
5358 	   /* sorts C in the reverse order in which the variables were chosen to be in the cover, i.e.
5359 	    *   such that (1 - x*_1)/a_1 >= ... >= (1 - x*_|C|)/a_|C|,  if          trans separation problem was used to find C
5360 	    *   such that (1 - x*_1)     >= ... >= (1 - x*_|C|),        if modified trans separation problem was used to find C
5361 	    * note that all variables with x*_j = 1 are in the end of the sorted C, so they will be removed last from C
5362 	    */
5363 	   assert(*ncovervars == nsortkeypairs);
5364 	   if( modtransused )
5365 	   {
5366 	      for( j = 0; j < *ncovervars; j++ )
5367 	      {
5368 	         SCIP_CALL( SCIPallocBuffer(scip, &(sortkeypairs[j])) ); /*lint !e866 */
5369 	         sortkeypairssorted[j] = sortkeypairs[j];
5370 	
5371 	         sortkeypairs[j]->key1 = solvals[covervars[j]];
5372 	         sortkeypairs[j]->key2 = (SCIP_Real) weights[covervars[j]];
5373 	      }
5374 	   }
5375 	   else
5376 	   {
5377 	      for( j = 0; j < *ncovervars; j++ )
5378 	      {
5379 	         SCIP_CALL( SCIPallocBuffer(scip, &(sortkeypairs[j])) ); /*lint !e866 */
5380 	         sortkeypairssorted[j] = sortkeypairs[j];
5381 	
5382 	         sortkeypairs[j]->key1 = (solvals[covervars[j]] - 1.0) / ((SCIP_Real) weights[covervars[j]]);
5383 	         sortkeypairs[j]->key2 = (SCIP_Real) (-weights[covervars[j]]);
5384 	      }
5385 	   }
5386 	   SCIPsortPtrInt((void**)sortkeypairssorted, covervars, compSortkeypairs, *ncovervars);
5387 	
5388 	   /* gets j' with a_j' = min{ a_j : j in C } */
5389 	   minweightidx = 0;
5390 	   minweight = weights[covervars[minweightidx]];
5391 	   for( j = 1; j < *ncovervars; j++ )
5392 	   {
5393 	      if( weights[covervars[j]] <= minweight )
5394 	      {
5395 	         minweightidx = j;
5396 	         minweight = weights[covervars[minweightidx]];
5397 	      }
5398 	   }
5399 	   assert(minweightidx >= 0 && minweightidx < *ncovervars);
5400 	   assert(minweight > 0 && minweight <= *coverweight);
5401 	
5402 	   j = 0;
5403 	   /* removes variables from C until the remaining variables form a minimal cover */
5404 	   while( j < *ncovervars && ((*coverweight) - minweight > capacity) )
5405 	   {
5406 	      assert(minweightidx >= j);
5407 	      assert(checkMinweightidx(weights, capacity, covervars, *ncovervars, *coverweight, minweightidx, j));
5408 	
5409 	      /* if sum_{i in C} a_i - a_j <= a_0, j cannot be removed from C */
5410 	      if( (*coverweight) - weights[covervars[j]] <= capacity )
5411 	      {
5412 		 ++j;
5413 	         continue;
5414 	      }
5415 	
5416 	      /* adds j to N\C */
5417 	      noncovervars[*nnoncovervars] = covervars[j];
5418 	      (*nnoncovervars)++;
5419 	
5420 	      /* removes j from C */
5421 	      (*coverweight) -= weights[covervars[j]];
5422 	      for( k = j; k < (*ncovervars) - 1; k++ )
5423 	         covervars[k] = covervars[k+1];
5424 	      (*ncovervars)--;
5425 	
5426 	      /* updates j' with a_j' = min{ a_j : j in C } */
5427 	      if( j == minweightidx )
5428 	      {
5429 	         minweightidx = 0;
5430 	         minweight = weights[covervars[minweightidx]];
5431 	         for( k = 1; k < *ncovervars; k++ )
5432 	         {
5433 	            if( weights[covervars[k]] <= minweight )
5434 	            {
5435 	               minweightidx = k;
5436 	               minweight = weights[covervars[minweightidx]];
5437 	            }
5438 	         }
5439 	         assert(minweight > 0 && minweight <= *coverweight);
5440 	         assert(minweightidx >= 0 && minweightidx < *ncovervars);
5441 	      }
5442 	      else
5443 	      {
5444 	         assert(minweightidx > j);
5445 	         minweightidx--;
5446 	      }
5447 	      /* j needs to stay the same */
5448 	   }
5449 	   assert((*coverweight) > capacity);
5450 	   assert((*coverweight) - minweight <= capacity);
5451 	
5452 	   /* frees temporary memory */
5453 	   for( j = nsortkeypairs-1; j >= 0; j-- )
5454 	      SCIPfreeBuffer(scip, &(sortkeypairs[j])); /*lint !e866 */
5455 	   SCIPfreeBufferArray(scip, &sortkeypairssorted);
5456 	   SCIPfreeBufferArray(scip, &sortkeypairs);
5457 	
5458 	   return SCIP_OKAY;
5459 	}
5460 	
5461 	/** converts given initial cover C_init to a feasible set by removing variables in the reverse order in which
5462 	 *  they were chosen to be in C_init:
5463 	 *   non-increasing (1 - x*_j)/a_j,   if          transformed separation problem was used to find C_init
5464 	 *   non-increasing (1 - x*_j),       if modified transformed separation problem was used to find C_init.
5465 	 *  separates lifted extended weight inequalities using sequential up- and down-lifting for this feasible set
5466 	 *  and all subsequent feasible sets.
5467 	 */
5468 	static
5469 	SCIP_RETCODE getFeasibleSet(
5470 	   SCIP*                 scip,               /**< SCIP data structure */
5471 	   SCIP_CONS*            cons,               /**< constraint that originates the knapsack problem */
5472 	   SCIP_SEPA*            sepa,               /**< originating separator of the knapsack problem, or NULL */
5473 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
5474 	   int                   nvars,              /**< number of variables in knapsack constraint */
5475 	   int                   ntightened,         /**< number of variables with tightened upper bound */
5476 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
5477 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
5478 	   SCIP_Real*            solvals,            /**< solution values of all problem variables */
5479 	   int*                  covervars,          /**< pointer to store cover variables */
5480 	   int*                  noncovervars,       /**< pointer to store noncover variables */
5481 	   int*                  ncovervars,         /**< pointer to store number of cover variables */
5482 	   int*                  nnoncovervars,      /**< pointer to store number of noncover variables */
5483 	   SCIP_Longint*         coverweight,        /**< pointer to store weight of cover */
5484 	   SCIP_Bool             modtransused,       /**< TRUE if mod trans sepa prob was used to find cover */
5485 	   SCIP_SOL*             sol,                /**< primal SCIP solution to separate, NULL for current LP solution */
5486 	   SCIP_Bool*            cutoff,             /**< whether a cutoff has been detected */
5487 	   int*                  ncuts               /**< pointer to add up the number of found cuts */
5488 	   )
5489 	{
5490 	   SCIP_Real* sortkeys;
5491 	   int j;
5492 	   int k;
5493 	
5494 	   assert(scip != NULL);
5495 	   assert(covervars != NULL);
5496 	   assert(noncovervars != NULL);
5497 	   assert(ncovervars != NULL);
5498 	   assert(*ncovervars > 0);
5499 	   assert(nnoncovervars != NULL);
5500 	   assert(*nnoncovervars >= 0);
5501 	   assert(coverweight != NULL);
5502 	   assert(*coverweight > 0);
5503 	   assert(*coverweight > capacity);
5504 	   assert(*ncovervars + *nnoncovervars == nvars - ntightened);
5505 	   assert(cutoff != NULL);
5506 	
5507 	   *cutoff = FALSE;
5508 	
5509 	   /* allocates temporary memory */
5510 	   SCIP_CALL( SCIPallocBufferArray(scip, &sortkeys, *ncovervars) );
5511 	
5512 	   /* sorts C in the reverse order in which the variables were chosen to be in the cover, i.e.
5513 	    *   such that (1 - x*_1)/a_1 >= ... >= (1 - x*_|C|)/a_|C|,  if          trans separation problem was used to find C
5514 	    *   such that (1 - x*_1)     >= ... >= (1 - x*_|C|),        if modified trans separation problem was used to find C
5515 	    * note that all variables with x*_j = 1 are in the end of the sorted C, so they will be removed last from C
5516 	    */
5517 	   if( modtransused )
5518 	   {
5519 	      for( j = 0; j < *ncovervars; j++ )
5520 	      {
5521 	         sortkeys[j] = solvals[covervars[j]];
5522 	         assert(SCIPisFeasGE(scip, sortkeys[j], 0.0));
5523 	      }
5524 	   }
5525 	   else
5526 	   {
5527 	      for( j = 0; j < *ncovervars; j++ )
5528 	      {
5529 	         sortkeys[j] = (solvals[covervars[j]] - 1.0) / ((SCIP_Real) weights[covervars[j]]);
5530 	         assert(SCIPisFeasLE(scip, sortkeys[j], 0.0));
5531 	      }
5532 	   }
5533 	   SCIPsortRealInt(sortkeys, covervars, *ncovervars);
5534 	
5535 	   /* removes variables from C_init and separates lifted extended weight inequalities using sequential up- and down-lifting;
5536 	    * in addition to an extended weight inequality this gives cardinality inequalities */
5537 	   while( *ncovervars >= 2 )
5538 	   {
5539 	      /* adds first element of C_init to N\C_init */
5540 	      noncovervars[*nnoncovervars] = covervars[0];
5541 	      (*nnoncovervars)++;
5542 	
5543 	      /* removes first element from C_init */
5544 	      (*coverweight) -= weights[covervars[0]];
5545 	      for( k = 0; k < (*ncovervars) - 1; k++ )
5546 	         covervars[k] = covervars[k+1];
5547 	      (*ncovervars)--;
5548 	
5549 	      assert(*ncovervars + *nnoncovervars == nvars - ntightened);
5550 	      if( (*coverweight) <= capacity )
5551 	      {
5552 	         SCIP_CALL( separateSequLiftedExtendedWeightInequality(scip, cons, sepa, vars, nvars, ntightened, weights, capacity, solvals,
5553 	               covervars, noncovervars, *ncovervars, *nnoncovervars, sol, cutoff, ncuts) );
5554 	      }
5555 	
5556 	      /* stop if cover is too large */
5557 	      if ( *ncovervars >= MAXCOVERSIZEITERLEWI )
5558 	         break;
5559 	   }
5560 	
5561 	   /* frees temporary memory */
5562 	   SCIPfreeBufferArray(scip, &sortkeys);
5563 	
5564 	   return SCIP_OKAY;
5565 	}
5566 	
5567 	/** separates different classes of valid inequalities for the 0-1 knapsack problem */
5568 	SCIP_RETCODE SCIPseparateKnapsackCuts(
5569 	   SCIP*                 scip,               /**< SCIP data structure */
5570 	   SCIP_CONS*            cons,               /**< originating constraint of the knapsack problem, or NULL */
5571 	   SCIP_SEPA*            sepa,               /**< originating separator of the knapsack problem, or NULL */
5572 	   SCIP_VAR**            vars,               /**< variables in knapsack constraint */
5573 	   int                   nvars,              /**< number of variables in knapsack constraint */
5574 	   SCIP_Longint*         weights,            /**< weights of variables in knapsack constraint */
5575 	   SCIP_Longint          capacity,           /**< capacity of knapsack */
5576 	   SCIP_SOL*             sol,                /**< primal SCIP solution to separate, NULL for current LP solution */
5577 	   SCIP_Bool             usegubs,            /**< should GUB information be used for separation? */
5578 	   SCIP_Bool*            cutoff,             /**< pointer to store whether a cutoff has been detected */
5579 	   int*                  ncuts               /**< pointer to add up the number of found cuts */
5580 	   )
5581 	{
5582 	   SCIP_Real* solvals;
5583 	   int* covervars;
5584 	   int* noncovervars;
5585 	   SCIP_Bool coverfound;
5586 	   SCIP_Bool fractional;
5587 	   SCIP_Bool modtransused;
5588 	   SCIP_Longint coverweight;
5589 	   int ncovervars;
5590 	   int nnoncovervars;
5591 	   int ntightened;
5592 	
5593 	   assert(scip != NULL);
5594 	   assert(capacity >= 0);
5595 	   assert(cutoff != NULL);
5596 	   assert(ncuts != NULL);
5597 	
5598 	   *cutoff = FALSE;
5599 	
5600 	   if( nvars == 0 )
5601 	      return SCIP_OKAY;
5602 	
5603 	   assert(vars != NULL);
5604 	   assert(nvars > 0);
5605 	   assert(weights != NULL);
5606 	
5607 	   /* increase age of constraint (age is reset to zero, if a cut was found) */
5608 	   if( cons != NULL )
5609 	   {
5610 	      SCIP_CALL( SCIPincConsAge(scip, cons) );
5611 	   }
5612 	
5613 	   /* allocates temporary memory */
5614 	   SCIP_CALL( SCIPallocBufferArray(scip, &solvals, nvars) );
5615 	   SCIP_CALL( SCIPallocBufferArray(scip, &covervars, nvars) );
5616 	   SCIP_CALL( SCIPallocBufferArray(scip, &noncovervars, nvars) );
5617 	
5618 	   /* gets solution values of all problem variables */
5619 	   SCIP_CALL( SCIPgetSolVals(scip, sol, nvars, vars, solvals) );
5620 	
5621 	#ifdef SCIP_DEBUG
5622 	   {
5623 	      int i;
5624 	
5625 	      SCIPdebugMsg(scip, "separate cuts for knapsack constraint originated by cons <%s>:\n",
5626 	         cons == NULL ? "-" : SCIPconsGetName(cons));
5627 	      for( i = 0; i < nvars; ++i )
5628 	      {
5629 	         SCIPdebugMsgPrint(scip, "%+" SCIP_LONGINT_FORMAT "<%s>(%g)", weights[i], SCIPvarGetName(vars[i]), solvals[i]);
5630 	      }
5631 	      SCIPdebugMsgPrint(scip, " <= %" SCIP_LONGINT_FORMAT "\n", capacity);
5632 	   }
5633 	#endif
5634 	
5635 	   /* LMCI1 (lifted minimal cover inequalities using sequential up- and down-lifting) using GUB information
5636 	    */
5637 	   if( usegubs )
5638 	   {
5639 	      SCIP_GUBSET* gubset;
5640 	
5641 	      SCIPdebugMsg(scip, "separate LMCI1-GUB cuts:\n");
5642 	
5643 	      /* initializes partion of knapsack variables into nonoverlapping GUB constraints */
5644 	      SCIP_CALL( GUBsetCreate(scip, &gubset, nvars, weights, capacity) );
5645 	
5646 	      /* constructs sophisticated partition of knapsack variables into nonoverlapping GUBs */
5647 	      SCIP_CALL( GUBsetGetCliquePartition(scip, gubset, vars, solvals) );
5648 	      assert(gubset->ngubconss <= nvars);
5649 	
5650 	      /* gets a most violated initial cover C_init ( sum_{j in C_init} a_j > a_0 ) by using the
5651 	       * MODIFIED transformed separation problem and taking into account the following fixing:
5652 	       *   j in C_init,           if j in N_1 = {j in N : x*_j = 1} and
5653 	       *   j in N\C_init,         if j in N_0 = {j in N : x*_j = 0},
5654 	       * if one exists
5655 	       */
5656 	      modtransused = TRUE;
5657 	      SCIP_CALL( getCover(scip, vars, nvars, weights, capacity, solvals, covervars, noncovervars, &ncovervars,
5658 	            &nnoncovervars, &coverweight, &coverfound, modtransused, &ntightened, &fractional) );
5659 	
5660 	      assert(!coverfound || !fractional || ncovervars + nnoncovervars == nvars - ntightened);
5661 	
5662 	      /* if x* is not fractional we stop the separation routine */
5663 	      if( !fractional )
5664 	      {
5665 	         SCIPdebugMsg(scip, "   LMCI1-GUB terminated by no variable with fractional LP value.\n");
5666 	
5667 	         /* frees memory for GUB set data structure */
5668 	         GUBsetFree(scip, &gubset);
5669 	
5670 	         goto TERMINATE;
5671 	      }
5672 	
5673 	      /* if no cover was found we stop the separation routine for lifted minimal cover inequality */
5674 	      if( coverfound )
5675 	      {
5676 	         /* converts initial cover C_init to a minimal cover C by removing variables in the reverse order in which the
5677 	          * variables were chosen to be in C_init; note that variables with x*_j = 1 will be removed last
5678 	          */
5679 	         SCIP_CALL( makeCoverMinimal(scip, weights, capacity, solvals, covervars, noncovervars, &ncovervars,
5680 	               &nnoncovervars, &coverweight, modtransused) );
5681 	
5682 	         /* only separate with GUB information if we have at least one nontrivial GUB (with more than one variable) */
5683 	         if( gubset->ngubconss < nvars )
5684 	         {
5685 	            /* separates lifted minimal cover inequalities using sequential up- and down-lifting and GUB information */
5686 	            SCIP_CALL( separateSequLiftedMinimalCoverInequality(scip, cons, sepa, vars, nvars, ntightened, weights, capacity,
5687 	                  solvals, covervars, noncovervars, ncovervars, nnoncovervars, sol, gubset, cutoff, ncuts) );
5688 	         }
5689 	         else
5690 	         {
5691 	            /* separates lifted minimal cover inequalities using sequential up- and down-lifting, but do not use trivial
5692 	             * GUB information
5693 	             */
5694 	            SCIP_CALL( separateSequLiftedMinimalCoverInequality(scip, cons, sepa, vars, nvars, ntightened, weights, capacity,
5695 	                  solvals, covervars, noncovervars, ncovervars, nnoncovervars, sol, NULL, cutoff, ncuts) );
5696 	         }
5697 	      }
5698 	
5699 	      /* frees memory for GUB set data structure */
5700 	      GUBsetFree(scip, &gubset);
5701 	   }
5702 	   else
5703 	   {
5704 	      /* LMCI1 (lifted minimal cover inequalities using sequential up- and down-lifting)
5705 	       * (and LMCI2 (lifted minimal cover inequalities using superadditive up-lifting))
5706 	       */
5707 	
5708 	      /* gets a most violated initial cover C_init ( sum_{j in C_init} a_j > a_0 ) by using the
5709 	       * MODIFIED transformed separation problem and taking into account the following fixing:
5710 	       *   j in C_init,           if j in N_1 = {j in N : x*_j = 1} and
5711 	       *   j in N\C_init,         if j in N_0 = {j in N : x*_j = 0},
5712 	       * if one exists
5713 	       */
5714 	      SCIPdebugMsg(scip, "separate LMCI1 cuts:\n");
5715 	      modtransused = TRUE;
5716 	      SCIP_CALL( getCover(scip, vars, nvars, weights, capacity, solvals, covervars, noncovervars, &ncovervars,
5717 	            &nnoncovervars, &coverweight, &coverfound, modtransused, &ntightened, &fractional) );
5718 	      assert(!coverfound || !fractional || ncovervars + nnoncovervars == nvars - ntightened);
5719 	
5720 	      /* if x* is not fractional we stop the separation routine */
5721 	      if( !fractional )
5722 	         goto TERMINATE;
5723 	
5724 	      /* if no cover was found we stop the separation routine for lifted minimal cover inequality */
5725 	      if( coverfound )
5726 	      {
5727 	         /* converts initial cover C_init to a minimal cover C by removing variables in the reverse order in which the
5728 	          * variables were chosen to be in C_init; note that variables with x*_j = 1 will be removed last
5729 	          */
5730 	         SCIP_CALL( makeCoverMinimal(scip, weights, capacity, solvals, covervars, noncovervars, &ncovervars,
5731 	               &nnoncovervars, &coverweight, modtransused) );
5732 	
5733 	         /* separates lifted minimal cover inequalities using sequential up- and down-lifting */
5734 	         SCIP_CALL( separateSequLiftedMinimalCoverInequality(scip, cons, sepa, vars, nvars, ntightened, weights, capacity,
5735 	               solvals, covervars, noncovervars, ncovervars, nnoncovervars, sol, NULL, cutoff, ncuts) );
5736 	
5737 	         if( USESUPADDLIFT ) /*lint !e506 !e774*/
5738 	         {
5739 	            SCIPdebugMsg(scip, "separate LMCI2 cuts:\n");
5740 	            /* separates lifted minimal cover inequalities using superadditive up-lifting */
5741 	            SCIP_CALL( separateSupLiftedMinimalCoverInequality(scip, cons, sepa, vars, nvars, ntightened, weights, capacity,
5742 	                  solvals, covervars, noncovervars, ncovervars, nnoncovervars, coverweight, sol, cutoff, ncuts) );
5743 	         }
5744 	      }
5745 	   }
5746 	
5747 	   /* LEWI (lifted extended weight inequalities using sequential up- and down-lifting) */
5748 	   if ( ! (*cutoff) )
5749 	   {
5750 	      /* gets a most violated initial cover C_init ( sum_{j in C_init} a_j > a_0 ) by using the
5751 	       * transformed separation problem and taking into account the following fixing:
5752 	       *   j in C_init,           if j in N_1 = {j in N : x*_j = 1} and
5753 	       *   j in N\C_init,         if j in N_0 = {j in N : x*_j = 0},
5754 	       * if one exists
5755 	       */
5756 	      SCIPdebugMsg(scip, "separate LEWI cuts:\n");
5757 	      modtransused = FALSE;
5758 	      SCIP_CALL( getCover(scip, vars, nvars, weights, capacity, solvals, covervars, noncovervars, &ncovervars,
5759 	            &nnoncovervars, &coverweight, &coverfound, modtransused, &ntightened, &fractional) );
5760 	      assert(fractional);
5761 	      assert(!coverfound || ncovervars + nnoncovervars == nvars - ntightened);
5762 	
5763 	      /* if no cover was found we stop the separation routine */
5764 	      if( coverfound )
5765 	      {
5766 	         /* converts initial cover C_init to a feasible set by removing variables in the reverse order in which
5767 	          * they were chosen to be in C_init and separates lifted extended weight inequalities using sequential
5768 	          * up- and down-lifting for this feasible set and all subsequent feasible sets.
5769 	          */
5770 	         SCIP_CALL( getFeasibleSet(scip, cons, sepa, vars, nvars, ntightened, weights, capacity, solvals, covervars, noncovervars,
5771 	               &ncovervars, &nnoncovervars, &coverweight, modtransused, sol, cutoff, ncuts) );
5772 	      }
5773 	   }
5774 	
5775 	 TERMINATE:
5776 	   /* frees temporary memory */
5777 	   SCIPfreeBufferArray(scip, &noncovervars);
5778 	   SCIPfreeBufferArray(scip, &covervars);
5779 	   SCIPfreeBufferArray(scip, &solvals);
5780 	
5781 	   return SCIP_OKAY;
5782 	}
5783 	
5784 	/* relaxes given general linear constraint into a knapsack constraint and separates lifted knapsack cover inequalities */
5785 	SCIP_RETCODE SCIPseparateRelaxedKnapsack(
5786 	   SCIP*                 scip,               /**< SCIP data structure */
5787 	   SCIP_CONS*            cons,               /**< originating constraint of the knapsack problem, or NULL */
5788 	   SCIP_SEPA*            sepa,               /**< originating separator of the knapsack problem, or NULL */
5789 	   int                   nknapvars,          /**< number of variables in the continuous knapsack constraint */
5790 	   SCIP_VAR**            knapvars,           /**< variables in the continuous knapsack constraint */
5791 	   SCIP_Real*            knapvals,           /**< coefficients of the variables in the continuous knapsack constraint */
5792 	   SCIP_Real             valscale,           /**< -1.0 if lhs of row is used as rhs of c. k. constraint, +1.0 otherwise */
5793 	   SCIP_Real             rhs,                /**< right hand side of the continuous knapsack constraint */
5794 	   SCIP_SOL*             sol,                /**< primal CIP solution, NULL for current LP solution */
5795 	   SCIP_Bool*            cutoff,             /**< pointer to store whether a cutoff was found */
5796 	   int*                  ncuts               /**< pointer to add up the number of found cuts */
5797 	   )
5798 	{
5799 	   SCIP_VAR** binvars;
5800 	   SCIP_VAR** consvars;
5801 	   SCIP_Real* binvals;
5802 	   SCIP_Longint* consvals;
5803 	   SCIP_Longint minact;
5804 	   SCIP_Longint maxact;
5805 	   SCIP_Real intscalar;
5806 	   SCIP_Bool success;
5807 	   int nbinvars;
5808 	   int nconsvars;
5809 	   int i;
5810 	
5811 	   int* tmpindices;
5812 	   int tmp;
5813 	   SCIP_CONSHDLR* conshdlr;
5814 	   SCIP_CONSHDLRDATA* conshdlrdata;
5815 	   SCIP_Bool noknapsackconshdlr;
5816 	   SCIP_Bool usegubs;
5817 	
5818 	   assert(nknapvars > 0);
5819 	   assert(knapvars != NULL);
5820 	   assert(cutoff != NULL);
5821 	
5822 	   tmpindices = NULL;
5823 	
5824 	   SCIPdebugMsg(scip, "separate linear constraint <%s> relaxed to knapsack\n", cons != NULL ? SCIPconsGetName(cons) : "-");
5825 	   SCIPdebug( if( cons != NULL ) { SCIPdebugPrintCons(scip, cons, NULL); } );
5826 	
5827 	   binvars = SCIPgetVars(scip);
5828 	
5829 	   /* all variables which are of integral type can be potentially of binary type; this can be checked via the method SCIPvarIsBinary(var) */
5830 	   nbinvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
5831 	
5832 	   *cutoff = FALSE;
5833 	
5834 	   if( nbinvars == 0 )
5835 	      return SCIP_OKAY;
5836 	
5837 	   /* set up data structures */
5838 	   SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nbinvars) );
5839 	   SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nbinvars) );
5840 	
5841 	   /* get conshdlrdata to use cleared memory */
5842 	   conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
5843 	   if( conshdlr == NULL )
5844 	   {
5845 	      noknapsackconshdlr = TRUE;
5846 	      usegubs = DEFAULT_USEGUBS;
5847 	
5848 	      SCIP_CALL( SCIPallocBufferArray(scip, &binvals, nbinvars) );
5849 	      BMSclearMemoryArray(binvals, nbinvars);
5850 	   }
5851 	   else
5852 	   {
5853 	      noknapsackconshdlr = FALSE;
5854 	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
5855 	      assert(conshdlrdata != NULL);
5856 	      usegubs = conshdlrdata->usegubs;
5857 	
5858 	      SCIP_CALL( SCIPallocBufferArray(scip, &tmpindices, nknapvars) );
5859 	
5860 	      /* increase array size to avoid an endless loop in the next block; this might happen if continuous variables
5861 	       * change their types to SCIP_VARTYPE_BINARY during presolving
5862 	       */
5863 	      if( conshdlrdata->reals1size == 0 )
5864 	      {
5865 	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->reals1, conshdlrdata->reals1size, 1) );
5866 	         conshdlrdata->reals1size = 1;
5867 	         conshdlrdata->reals1[0] = 0.0;
5868 	      }
5869 	
5870 	      assert(conshdlrdata->reals1size > 0);
5871 	
5872 	      /* next if condition should normally not be true, because it means that presolving has created more binary
5873 	       * variables than binary + integer variables existed at the constraint initialization method, but for example if you would
5874 	       * transform all integers into their binary representation then it maybe happens
5875 	       */
5876 	      if( conshdlrdata->reals1size < nbinvars )
5877 	      {
5878 	         int oldsize = conshdlrdata->reals1size;
5879 	
5880 	         conshdlrdata->reals1size = nbinvars;
5881 	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->reals1, oldsize, conshdlrdata->reals1size) );
5882 	         BMSclearMemoryArray(&(conshdlrdata->reals1[oldsize]), conshdlrdata->reals1size - oldsize); /*lint !e866 */
5883 	      }
5884 	      binvals = conshdlrdata->reals1;
5885 	
5886 	      /* check for cleared array, all entries have to be zero */
5887 	#ifndef NDEBUG
5888 	      for( tmp = nbinvars - 1; tmp >= 0; --tmp )
5889 	      {
5890 	         assert(binvals[tmp] == 0);
5891 	      }
5892 	#endif
5893 	   }
5894 	
5895 	   tmp = 0;
5896 	
5897 	   /* relax continuous knapsack constraint:
5898 	    * 1. make all variables binary:
5899 	    *    if x_j is continuous or integer variable substitute:
5900 	    *      - a_j < 0: x_j = lb  or  x_j = b*z + d with variable lower bound b*z + d with binary variable z
5901 	    *      - a_j > 0: x_j = ub  or  x_j = b*z + d with variable upper bound b*z + d with binary variable z
5902 	    * 2. convert coefficients of all variables to positive integers:
5903 	    *      - scale all coefficients a_j to a~_j integral
5904 	    *      - substitute  x~_j = 1 - x_j if a~_j < 0
5905 	    */
5906 	
5907 	   /* replace integer and continuous variables with binary variables */
5908 	   for( i = 0; i < nknapvars; i++ )
5909 	   {
5910 	      SCIP_VAR* var;
5911 	
5912 	      var = knapvars[i];
5913 	
5914 	      if( SCIPvarIsBinary(var) && SCIPvarIsActive(var) )
5915 	      {
5916 	         SCIP_Real solval;
5917 	         assert(0 <= SCIPvarGetProbindex(var) && SCIPvarGetProbindex(var) < nbinvars);
5918 	
5919 	         solval = SCIPgetSolVal(scip, sol, var);
5920 	
5921 	         /* knapsack relaxation assumes solution values between 0.0 and 1.0 for binary variables */
5922 	         if( SCIPisFeasLT(scip, solval, 0.0 )
5923 	               || SCIPisFeasGT(scip, solval, 1.0) )
5924 	         {
5925 	            SCIPdebugMsg(scip, "Solution value %.15g <%s> outside domain [0.0, 1.0]\n",
5926 	                  solval, SCIPvarGetName(var));
5927 	            goto TERMINATE;
5928 	         }
5929 	
5930 	         binvals[SCIPvarGetProbindex(var)] += valscale * knapvals[i];
5931 	         if( !noknapsackconshdlr )
5932 	         {
5933 	            assert(tmpindices != NULL);
5934 	
5935 	            tmpindices[tmp] = SCIPvarGetProbindex(var);
5936 	            ++tmp;
5937 	         }
5938 	         SCIPdebugMsg(scip, " -> binary variable %+.15g<%s>(%.15g)\n", valscale * knapvals[i], SCIPvarGetName(var), SCIPgetSolVal(scip, sol, var));
5939 	      }
5940 	      else if( valscale * knapvals[i] > 0.0 )
5941 	      {
5942 	         SCIP_VAR** zvlb;
5943 	         SCIP_Real* bvlb;
5944 	         SCIP_Real* dvlb;
5945 	         SCIP_Real bestlbsol;
5946 	         int bestlbtype;
5947 	         int nvlb;
5948 	         int j;
5949 	
5950 	         /* a_j > 0: substitution with lb or vlb */
5951 	         nvlb = SCIPvarGetNVlbs(var);
5952 	         zvlb = SCIPvarGetVlbVars(var);
5953 	         bvlb = SCIPvarGetVlbCoefs(var);
5954 	         dvlb = SCIPvarGetVlbConstants(var);
5955 	
5956 	         /* search for lb or vlb with maximal bound value */
5957 	         bestlbsol = SCIPvarGetLbGlobal(var);
5958 	         bestlbtype = -1;
5959 	         for( j = 0; j < nvlb; j++ )
5960 	         {
5961 	            /* use only numerical stable vlb with binary variable z */
5962 	            if( SCIPvarIsBinary(zvlb[j]) && SCIPvarIsActive(zvlb[j]) && REALABS(bvlb[j]) <= MAXABSVBCOEF )
5963 	            {
5964 	               SCIP_Real vlbsol;
5965 	
5966 	               if( (bvlb[j] >= 0.0 && SCIPisGT(scip, bvlb[j] * SCIPvarGetLbLocal(zvlb[j]) + dvlb[j], SCIPvarGetUbLocal(var))) ||
5967 	                   (bvlb[j] <= 0.0 && SCIPisGT(scip, bvlb[j] * SCIPvarGetUbLocal(zvlb[j]) + dvlb[j], SCIPvarGetUbLocal(var))) )
5968 	               {
5969 	                  *cutoff = TRUE;
5970 	                  SCIPdebugMsg(scip, "variable bound <%s>[%g,%g] >= %g<%s>[%g,%g] + %g implies local cutoff\n",
5971 	                     SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
5972 	                     bvlb[j], SCIPvarGetName(zvlb[j]), SCIPvarGetLbLocal(zvlb[j]), SCIPvarGetUbLocal(zvlb[j]), dvlb[j]);
5973 	                  goto TERMINATE;
5974 	               }
5975 	
5976 	               assert(0 <= SCIPvarGetProbindex(zvlb[j]) && SCIPvarGetProbindex(zvlb[j]) < nbinvars);
5977 	               vlbsol = bvlb[j] * SCIPgetSolVal(scip, sol, zvlb[j]) + dvlb[j];
5978 	               if( SCIPisGE(scip, vlbsol, bestlbsol) )
5979 	               {
5980 	                  bestlbsol = vlbsol;
5981 	                  bestlbtype = j;
5982 	               }
5983 	            }
5984 	         }
5985 	
5986 	         /* if no lb or vlb with binary variable was found, we have to abort */
5987 	         if( SCIPisInfinity(scip, -bestlbsol) )
5988 	            goto TERMINATE;
5989 	
5990 	         if( bestlbtype == -1 )
5991 	         {
5992 	            rhs -= valscale * knapvals[i] * bestlbsol;
5993 	            SCIPdebugMsg(scip, " -> non-binary variable %+.15g<%s>(%.15g) replaced with lower bound %.15g (rhs=%.15g)\n",
5994 	               valscale * knapvals[i], SCIPvarGetName(var), SCIPgetSolVal(scip, sol, var), SCIPvarGetLbGlobal(var), rhs);
5995 	         }
5996 	         else
5997 	         {
5998 	            assert(0 <= SCIPvarGetProbindex(zvlb[bestlbtype]) && SCIPvarGetProbindex(zvlb[bestlbtype]) < nbinvars);
5999 	            rhs -= valscale * knapvals[i] * dvlb[bestlbtype];
6000 	            binvals[SCIPvarGetProbindex(zvlb[bestlbtype])] += valscale * knapvals[i] * bvlb[bestlbtype];
6001 	
6002 	            if( SCIPisInfinity(scip, REALABS(binvals[SCIPvarGetProbindex(zvlb[bestlbtype])])) )
6003 	               goto TERMINATE;
6004 	
6005 	            if( !noknapsackconshdlr )
6006 	            {
6007 	               assert(tmpindices != NULL);
6008 	
6009 	               tmpindices[tmp] = SCIPvarGetProbindex(zvlb[bestlbtype]);
6010 	               ++tmp;
6011 	            }
6012 	            SCIPdebugMsg(scip, " -> non-binary variable %+.15g<%s>(%.15g) replaced with variable lower bound %+.15g<%s>(%.15g) %+.15g (rhs=%.15g)\n",
6013 	               valscale * knapvals[i], SCIPvarGetName(var), SCIPgetSolVal(scip, sol, var),
6014 	               bvlb[bestlbtype], SCIPvarGetName(zvlb[bestlbtype]),
6015 	               SCIPgetSolVal(scip, sol, zvlb[bestlbtype]), dvlb[bestlbtype], rhs);
6016 	         }
6017 	      }
6018 	      else
6019 	      {
6020 	         SCIP_VAR** zvub;
6021 	         SCIP_Real* bvub;
6022 	         SCIP_Real* dvub;
6023 	         SCIP_Real bestubsol;
6024 	         int bestubtype;
6025 	         int nvub;
6026 	         int j;
6027 	
6028 	         assert(valscale * knapvals[i] < 0.0);
6029 	
6030 	         /* a_j < 0: substitution with ub or vub */
6031 	         nvub = SCIPvarGetNVubs(var);
6032 	         zvub = SCIPvarGetVubVars(var);
6033 	         bvub = SCIPvarGetVubCoefs(var);
6034 	         dvub = SCIPvarGetVubConstants(var);
6035 	
6036 	         /* search for ub or vub with minimal bound value */
6037 	         bestubsol = SCIPvarGetUbGlobal(var);
6038 	         bestubtype = -1;
6039 	         for( j = 0; j < nvub; j++ )
6040 	         {
6041 	            /* use only numerical stable vub with active binary variable z */
6042 	            if( SCIPvarIsBinary(zvub[j]) && SCIPvarIsActive(zvub[j]) && REALABS(bvub[j]) <= MAXABSVBCOEF )
6043 	            {
6044 	               SCIP_Real vubsol;
6045 	
6046 	               if( (bvub[j] >= 0.0 && SCIPisLT(scip, bvub[j] * SCIPvarGetUbLocal(zvub[j]) + dvub[j], SCIPvarGetLbLocal(var))) ||
6047 	                  (bvub[j] <= 0.0 && SCIPisLT(scip, bvub[j] * SCIPvarGetLbLocal(zvub[j]) + dvub[j], SCIPvarGetLbLocal(var))) )
6048 	               {
6049 	                  *cutoff = TRUE;
6050 	                  SCIPdebugMsg(scip, "variable bound <%s>[%g,%g] <= %g<%s>[%g,%g] + %g implies local cutoff\n",
6051 	                     SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
6052 	                     bvub[j], SCIPvarGetName(zvub[j]), SCIPvarGetLbLocal(zvub[j]), SCIPvarGetUbLocal(zvub[j]), dvub[j]);
6053 	                  goto TERMINATE;
6054 	               }
6055 	
6056 	               assert(0 <= SCIPvarGetProbindex(zvub[j]) && SCIPvarGetProbindex(zvub[j]) < nbinvars);
6057 	               vubsol = bvub[j] * SCIPgetSolVal(scip, sol, zvub[j]) + dvub[j];
6058 	               if( SCIPisLE(scip, vubsol, bestubsol) )
6059 	               {
6060 	                  bestubsol = vubsol;
6061 	                  bestubtype = j;
6062 	               }
6063 	            }
6064 	         }
6065 	
6066 	         /* if no ub or vub with binary variable was found, we have to abort */
6067 	         if( SCIPisInfinity(scip, bestubsol) )
6068 	            goto TERMINATE;
6069 	
6070 	         if( bestubtype == -1 )
6071 	         {
6072 	            rhs -= valscale * knapvals[i] * bestubsol;
6073 	            SCIPdebugMsg(scip, " -> non-binary variable %+.15g<%s>(%.15g) replaced with upper bound %.15g (rhs=%.15g)\n",
6074 	               valscale * knapvals[i], SCIPvarGetName(var), SCIPgetSolVal(scip, sol, var), SCIPvarGetUbGlobal(var), rhs);
6075 	         }
6076 	         else
6077 	         {
6078 	            assert(0 <= SCIPvarGetProbindex(zvub[bestubtype]) && SCIPvarGetProbindex(zvub[bestubtype]) < nbinvars);
6079 	            rhs -= valscale * knapvals[i] * dvub[bestubtype];
6080 	            binvals[SCIPvarGetProbindex(zvub[bestubtype])] += valscale * knapvals[i] * bvub[bestubtype];
6081 	
6082 	            if( SCIPisInfinity(scip, REALABS(binvals[SCIPvarGetProbindex(zvub[bestubtype])])) )
6083 	               goto TERMINATE;
6084 	
6085 	            if( !noknapsackconshdlr )
6086 	            {
6087 	               assert(tmpindices != NULL);
6088 	
6089 	               tmpindices[tmp] = SCIPvarGetProbindex(zvub[bestubtype]);
6090 	               ++tmp;
6091 	            }
6092 	            SCIPdebugMsg(scip, " -> non-binary variable %+.15g<%s>(%.15g) replaced with variable upper bound %+.15g<%s>(%.15g) %+.15g (rhs=%.15g)\n",
6093 	               valscale * knapvals[i], SCIPvarGetName(var), SCIPgetSolVal(scip, sol, var),
6094 	               bvub[bestubtype], SCIPvarGetName(zvub[bestubtype]),
6095 	               SCIPgetSolVal(scip, sol, zvub[bestubtype]), dvub[bestubtype], rhs);
6096 	         }
6097 	      }
6098 	   }
6099 	
6100 	   /* convert coefficients of all (now binary) variables to positive integers:
6101 	    *   - make all coefficients integral
6102 	    *   - make all coefficients positive (substitute negated variable)
6103 	    */
6104 	   nconsvars = 0;
6105 	
6106 	   /* calculate scalar which makes all coefficients integral in relative allowed difference in between
6107 	    * -SCIPepsilon(scip) and KNAPSACKRELAX_MAXDELTA
6108 	    */
6109 	   SCIP_CALL( SCIPcalcIntegralScalar(binvals, nbinvars, -SCIPepsilon(scip), KNAPSACKRELAX_MAXDELTA,
6110 	         KNAPSACKRELAX_MAXDNOM, KNAPSACKRELAX_MAXSCALE, &intscalar, &success) );
6111 	   SCIPdebugMsg(scip, " -> intscalar = %.15g\n", intscalar);
6112 	
6113 	   /* if coefficients cannot be made integral, we have to use a scalar of 1.0 and only round fractional coefficients down */
6114 	   if( !success )
6115 	      intscalar = 1.0;
6116 	
6117 	   /* make all coefficients integral and positive:
6118 	    *  - scale a~_j = a_j * intscalar
6119 	    *  - substitute x~_j = 1 - x_j if a~_j < 0
6120 	    */
6121 	   rhs = rhs * intscalar;
6122 	
6123 	   SCIPdebugMsg(scip, " -> rhs = %.15g\n", rhs);
6124 	   minact = 0;
6125 	   maxact = 0;
6126 	   for( i = 0; i < nbinvars; i++ )
6127 	   {
6128 	      SCIP_VAR* var;
6129 	      SCIP_Longint val;
6130 	
6131 	      val = (SCIP_Longint)SCIPfloor(scip, binvals[i] * intscalar);
6132 	      if( val == 0 )
6133 	         continue;
6134 	
6135 	      if( val > 0 )
6136 	      {
6137 	         var = binvars[i];
6138 	         SCIPdebugMsg(scip, " -> positive scaled binary variable %+" SCIP_LONGINT_FORMAT "<%s> (unscaled %.15g): not changed (rhs=%.15g)\n",
6139 	            val, SCIPvarGetName(var), binvals[i], rhs);
6140 	      }
6141 	      else
6142 	      {
6143 	         assert(val < 0);
6144 	
6145 	         SCIP_CALL( SCIPgetNegatedVar(scip, binvars[i], &var) );
6146 	         val = -val;  /*lint !e2704*/
6147 	         rhs += val;
6148 	         SCIPdebugMsg(scip, " -> negative scaled binary variable %+" SCIP_LONGINT_FORMAT "<%s> (unscaled %.15g): substituted by (1 - <%s>) (rhs=%.15g)\n",
6149 	            -val, SCIPvarGetName(binvars[i]), binvals[i], SCIPvarGetName(var), rhs);
6150 	      }
6151 	
6152 	      if( SCIPvarGetLbLocal(var) > 0.5 )
6153 	         minact += val;
6154 	      if( SCIPvarGetUbLocal(var) > 0.5 )
6155 	         maxact += val;
6156 	      consvals[nconsvars] = val;
6157 	      consvars[nconsvars] = var;
6158 	      nconsvars++;
6159 	   }
6160 	
6161 	   if( nconsvars > 0 )
6162 	   {
6163 	      SCIP_Longint capacity;
6164 	
6165 	      assert(consvars != NULL);
6166 	      assert(consvals != NULL);
6167 	      capacity = (SCIP_Longint)SCIPfeasFloor(scip, rhs);
6168 	
6169 	#ifdef SCIP_DEBUG
6170 	      {
6171 	         SCIP_Real act;
6172 	
6173 	         SCIPdebugMsg(scip, " -> linear constraint <%s> relaxed to knapsack:", cons != NULL ? SCIPconsGetName(cons) : "-");
6174 	         act = 0.0;
6175 	         for( i = 0; i < nconsvars; ++i )
6176 	         {
6177 	            SCIPdebugMsgPrint(scip, " %+" SCIP_LONGINT_FORMAT "<%s>(%.15g)", consvals[i], SCIPvarGetName(consvars[i]),
6178 	               SCIPgetSolVal(scip, sol, consvars[i]));
6179 	            act += consvals[i] * SCIPgetSolVal(scip, sol, consvars[i]);
6180 	         }
6181 	         SCIPdebugMsgPrint(scip, " <= %" SCIP_LONGINT_FORMAT " (%.15g) [act: %.15g, min: %" SCIP_LONGINT_FORMAT " max: %" SCIP_LONGINT_FORMAT "]\n",
6182 	            capacity, rhs, act, minact, maxact);
6183 	      }
6184 	#endif
6185 	
6186 	      if( minact > capacity )
6187 	      {
6188 	         SCIPdebugMsg(scip, "minactivity of knapsack relaxation implies local cutoff\n");
6189 	         *cutoff = TRUE;
6190 	         goto TERMINATE;
6191 	      }
6192 	
6193 	      if( maxact > capacity )
6194 	      {
6195 	         /* separate lifted cut from relaxed knapsack constraint */
6196 	         SCIP_CALL( SCIPseparateKnapsackCuts(scip, cons, sepa, consvars, nconsvars, consvals, capacity, sol, usegubs, cutoff, ncuts) );
6197 	      }
6198 	   }
6199 	
6200 	 TERMINATE:
6201 	   /* free data structures */
6202 	   if( noknapsackconshdlr)
6203 	   {
6204 	      SCIPfreeBufferArray(scip, &binvals);
6205 	   }
6206 	   else
6207 	   {
6208 	      /* clear binvals */
6209 	      for( --tmp; tmp >= 0; --tmp)
6210 	      {
6211 	         assert(tmpindices != NULL);
6212 	         binvals[tmpindices[tmp]] = 0;
6213 	      }
6214 	      SCIPfreeBufferArray(scip, &tmpindices);
6215 	   }
6216 	   SCIPfreeBufferArray(scip, &consvals);
6217 	   SCIPfreeBufferArray(scip, &consvars);
6218 	
6219 	   return SCIP_OKAY;
6220 	}
6221 	
6222 	/** separates given knapsack constraint */
6223 	static
6224 	SCIP_RETCODE separateCons(
6225 	   SCIP*                 scip,               /**< SCIP data structure */
6226 	   SCIP_CONS*            cons,               /**< knapsack constraint */
6227 	   SCIP_SOL*             sol,                /**< primal SCIP solution, NULL for current LP solution */
6228 	   SCIP_Bool             sepacuts,           /**< should knapsack cuts be separated? */
6229 	   SCIP_Bool             usegubs,            /**< should GUB information be used for separation? */
6230 	   SCIP_Bool*            cutoff,             /**< whether a cutoff has been detected */
6231 	   int*                  ncuts               /**< pointer to add up the number of found cuts */
6232 	   )
6233 	{
6234 	   SCIP_CONSDATA* consdata;
6235 	   SCIP_Bool violated;
6236 	
6237 	   assert(ncuts != NULL);
6238 	   assert(cutoff != NULL);
6239 	   *cutoff = FALSE;
6240 	
6241 	   consdata = SCIPconsGetData(cons);
6242 	   assert(consdata != NULL);
6243 	
6244 	   SCIPdebugMsg(scip, "separating knapsack constraint <%s>\n", SCIPconsGetName(cons));
6245 	
6246 	   /* check knapsack constraint itself for feasibility */
6247 	   SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), FALSE, &violated) );
6248 	
6249 	   if( violated )
6250 	   {
6251 	      /* add knapsack constraint as LP row to the LP */
6252 	      SCIP_CALL( addRelaxation(scip, cons, cutoff) );
6253 	      (*ncuts)++;
6254 	   }
6255 	   else if( sepacuts )
6256 	   {
6257 	      SCIP_CALL( SCIPseparateKnapsackCuts(scip, cons, NULL, consdata->vars, consdata->nvars, consdata->weights,
6258 	            consdata->capacity, sol, usegubs, cutoff, ncuts) );
6259 	   }
6260 	
6261 	   return SCIP_OKAY;
6262 	}
6263 	
6264 	/** adds coefficient to constraint data */
6265 	static
6266 	SCIP_RETCODE addCoef(
6267 	   SCIP*                 scip,               /**< SCIP data structure */
6268 	   SCIP_CONS*            cons,               /**< knapsack constraint */
6269 	   SCIP_VAR*             var,                /**< variable to add to knapsack */
6270 	   SCIP_Longint          weight              /**< weight of variable in knapsack */
6271 	   )
6272 	{
6273 	   SCIP_CONSDATA* consdata;
6274 	
6275 	   consdata = SCIPconsGetData(cons);
6276 	   assert(consdata != NULL);
6277 	   assert(SCIPvarIsBinary(var));
6278 	   assert(weight > 0);
6279 	
6280 	   /* add the new coefficient to the LP row */
6281 	   if( consdata->row != NULL )
6282 	   {
6283 	      SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, (SCIP_Real)weight) );
6284 	   }
6285 	
6286 	   /* check for fixed variable */
6287 	   if( SCIPvarGetLbGlobal(var) > 0.5 )
6288 	   {
6289 	      /* variable is fixed to one: reduce capacity */
6290 	      consdata->capacity -= weight;
6291 	   }
6292 	   else if( SCIPvarGetUbGlobal(var) > 0.5 )
6293 	   {
6294 	      SCIP_Bool negated;
6295 	
6296 	      /* get binary representative of variable */
6297 	      SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &var, &negated) );
6298 	
6299 	      /* insert coefficient */
6300 	      SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1, SCIPconsIsTransformed(cons)) );
6301 	      consdata->vars[consdata->nvars] = var;
6302 	      consdata->weights[consdata->nvars] = weight;
6303 	      consdata->nvars++;
6304 	
6305 	      /* capture variable */
6306 	      SCIP_CALL( SCIPcaptureVar(scip, var) );
6307 	
6308 	      /* install the rounding locks of variable */
6309 	      SCIP_CALL( lockRounding(scip, cons, var) );
6310 	
6311 	      /* catch events */
6312 	      if( SCIPconsIsTransformed(cons) )
6313 	      {
6314 	         SCIP_CONSHDLRDATA* conshdlrdata;
6315 	
6316 	         conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
6317 	         assert(conshdlrdata != NULL);
6318 	         SCIP_CALL( eventdataCreate(scip, &consdata->eventdata[consdata->nvars-1], cons, weight) );
6319 	         SCIP_CALL( SCIPcatchVarEvent(scip, var, EVENTTYPE_KNAPSACK,
6320 	               conshdlrdata->eventhdlr, consdata->eventdata[consdata->nvars-1],
6321 	               &consdata->eventdata[consdata->nvars-1]->filterpos) );
6322 	
6323 	         if( !consdata->existmultaggr && SCIPvarGetStatus(SCIPvarGetProbvar(var)) == SCIP_VARSTATUS_MULTAGGR )
6324 	            consdata->existmultaggr = TRUE;
6325 	
6326 	         /* mark constraint to be propagated and presolved */
6327 	         SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
6328 	         consdata->presolvedtiming = 0;
6329 	         consdata->cliquesadded = FALSE; /* new coefficient might lead to larger cliques */
6330 	      }
6331 	
6332 	      /* update weight sums */
6333 	      updateWeightSums(consdata, var, weight);
6334 	
6335 	      consdata->sorted = FALSE;
6336 	      consdata->cliquepartitioned = FALSE;
6337 	      consdata->negcliquepartitioned = FALSE;
6338 	      consdata->merged = FALSE;
6339 	   }
6340 	
6341 	   return SCIP_OKAY;
6342 	}
6343 	
6344 	/** deletes coefficient at given position from constraint data */
6345 	static
6346 	SCIP_RETCODE delCoefPos(
6347 	   SCIP*                 scip,               /**< SCIP data structure */
6348 	   SCIP_CONS*            cons,               /**< knapsack constraint */
6349 	   int                   pos                 /**< position of coefficient to delete */
6350 	   )
6351 	{
6352 	   SCIP_CONSDATA* consdata;
6353 	   SCIP_VAR* var;
6354 	
6355 	   consdata = SCIPconsGetData(cons);
6356 	   assert(consdata != NULL);
6357 	   assert(0 <= pos && pos < consdata->nvars);
6358 	
6359 	   var = consdata->vars[pos];
6360 	   assert(var != NULL);
6361 	   assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
6362 	
6363 	   /* delete the coefficient from the LP row */
6364 	   if( consdata->row != NULL )
6365 	   {
6366 	      SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -(SCIP_Real)consdata->weights[pos]) );
6367 	   }
6368 	
6369 	   /* remove the rounding locks of variable */
6370 	   SCIP_CALL( unlockRounding(scip, cons, var) );
6371 	
6372 	   /* drop events and mark constraint to be propagated and presolved */
6373 	   if( SCIPconsIsTransformed(cons) )
6374 	   {
6375 	      SCIP_CONSHDLRDATA* conshdlrdata;
6376 	
6377 	      conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
6378 	      assert(conshdlrdata != NULL);
6379 	      SCIP_CALL( SCIPdropVarEvent(scip, var, EVENTTYPE_KNAPSACK,
6380 	            conshdlrdata->eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
6381 	      SCIP_CALL( eventdataFree(scip, &consdata->eventdata[pos]) );
6382 	
6383 	      SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
6384 	      consdata->presolvedtiming = 0;
6385 	      consdata->sorted = (consdata->sorted && pos == consdata->nvars - 1);
6386 	   }
6387 	
6388 	   /* decrease weight sums */
6389 	   updateWeightSums(consdata, var, -consdata->weights[pos]);
6390 	
6391 	   /* move the last variable to the free slot */
6392 	   consdata->vars[pos] = consdata->vars[consdata->nvars-1];
6393 	   consdata->weights[pos] = consdata->weights[consdata->nvars-1];
6394 	   if( consdata->eventdata != NULL )
6395 	      consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
6396 	
6397 	   /* release variable */
6398 	   SCIP_CALL( SCIPreleaseVar(scip, &var) );
6399 	
6400 	   /* try to use old clique partitions */
6401 	   if( consdata->cliquepartitioned )
6402 	   {
6403 	      assert(consdata->cliquepartition != NULL);
6404 	      /* if the clique number is equal to the number of variables we have only cliques with one element, so we don't
6405 	       * change the clique number */
6406 	      if( consdata->cliquepartition[consdata->nvars - 1] != consdata->nvars - 1 )
6407 	      {
6408 	         int oldcliqenum;
6409 	
6410 	         oldcliqenum = consdata->cliquepartition[pos];
6411 	         consdata->cliquepartition[pos] = consdata->cliquepartition[consdata->nvars-1];
6412 	
6413 	         /* the following if and else cases assure that we have increasing clique numbers */
6414 	         if( consdata->cliquepartition[pos] > pos )
6415 	            consdata->cliquepartitioned = FALSE; /* recalculate the clique partition after a coefficient was removed */
6416 	         else
6417 	         {
6418 	            int i;
6419 	            int cliquenumbefore;
6420 	
6421 	            /* if the old clique number was greater than the new one we have to check that before a bigger clique number
6422 	             * occurs the same as the old one is still in the cliquepartition */
6423 	            if( oldcliqenum > consdata->cliquepartition[pos] )
6424 	            {
6425 	               for( i = 0; i < consdata->nvars; ++i )
6426 	                  if( oldcliqenum == consdata->cliquepartition[i] )
6427 	                     break;
6428 	                  else if( oldcliqenum < consdata->cliquepartition[i] )
6429 	                  {
6430 	                     consdata->cliquepartitioned = FALSE; /* recalculate the clique partition after a coefficient was removed */
6431 	                     break;
6432 	                  }
6433 	               /* if we reached the end in the for loop, it means we have deleted the last element of the clique with
6434 	                * the biggest index, so decrease the number of cliques
6435 	                */
6436 	               if( i == consdata->nvars )
6437 	                  --(consdata->ncliques);
6438 	            }
6439 	            /* if the old clique number was smaller than the new one we have to check the front for an element with
6440 	             * clique number minus 1 */
6441 	            else if( oldcliqenum < consdata->cliquepartition[pos] )
6442 	            {
6443 	               cliquenumbefore = consdata->cliquepartition[pos] - 1;
6444 	               for( i = pos - 1; i >= 0 && i >= cliquenumbefore && consdata->cliquepartition[i] < cliquenumbefore; --i ); /*lint !e722*/
6445 	
6446 	               if( i < cliquenumbefore )
6447 	                  consdata->cliquepartitioned = FALSE; /* recalculate the clique partition after a coefficient was removed */
6448 	            }
6449 	            /* if we deleted the last element of the clique with biggest index, we have to decrease the clique number */
6450 	            else if( pos == consdata->nvars - 1)
6451 	            {
6452 	               cliquenumbefore = consdata->cliquepartition[pos];
6453 	               for( i = pos - 1; i >= 0 && i >= cliquenumbefore && consdata->cliquepartition[i] < cliquenumbefore; --i ); /*lint !e722*/
6454 	
6455 	               if( i < cliquenumbefore )
6456 	                  --(consdata->ncliques);
6457 	            }
6458 	            /* if the old clique number is equal to the new one the cliquepartition should be ok */
6459 	         }
6460 	      }
6461 	      else
6462 	         --(consdata->ncliques);
6463 	   }
6464 	
6465 	   if( consdata->negcliquepartitioned )
6466 	   {
6467 	      assert(consdata->negcliquepartition != NULL);
6468 	      /* if the clique number is equal to the number of variables we have only cliques with one element, so we don't
6469 	       * change the clique number */
6470 	      if( consdata->negcliquepartition[consdata->nvars-1] != consdata->nvars - 1 )
6471 	      {
6472 	         int oldcliqenum;
6473 	
6474 	         oldcliqenum = consdata->negcliquepartition[pos];
6475 	         consdata->negcliquepartition[pos] = consdata->negcliquepartition[consdata->nvars-1];
6476 	
6477 	         /* the following if and else cases assure that we have increasing clique numbers */
6478 	         if( consdata->negcliquepartition[pos] > pos )
6479 	            consdata->negcliquepartitioned = FALSE; /* recalculate the clique partition after a coefficient was removed */
6480 	         else
6481 	         {
6482 	            int i;
6483 	            int cliquenumbefore;
6484 	
6485 	            /* if the old clique number was greater than the new one we have to check that, before a bigger clique number
6486 	             * occurs, the same as the old one occurs */
6487 	            if( oldcliqenum > consdata->negcliquepartition[pos] )
6488 	            {
6489 	               for( i = 0; i < consdata->nvars; ++i )
6490 	                  if( oldcliqenum == consdata->negcliquepartition[i] )
6491 	                     break;
6492 	                  else if( oldcliqenum < consdata->negcliquepartition[i] )
6493 	                  {
6494 	                     consdata->negcliquepartitioned = FALSE; /* recalculate the negated clique partition after a coefficient was removed */
6495 	                     break;
6496 	                  }
6497 	               /* if we reached the end in the for loop, it means we have deleted the last element of the clique with
6498 	                * the biggest index, so decrease the number of negated cliques
6499 	                */
6500 	               if( i == consdata->nvars )
6501 	                  --(consdata->nnegcliques);
6502 	            }
6503 	            /* if the old clique number was smaller than the new one we have to check the front for an element with
6504 	             * clique number minus 1 */
6505 	            else if( oldcliqenum < consdata->negcliquepartition[pos] )
6506 	            {
6507 	               cliquenumbefore = consdata->negcliquepartition[pos] - 1;
6508 	               for( i = pos - 1; i >= 0 && i >= cliquenumbefore && consdata->negcliquepartition[i] < cliquenumbefore; --i ); /*lint !e722*/
6509 	
6510 	               if( i < cliquenumbefore )
6511 	                  consdata->negcliquepartitioned = FALSE; /* recalculate the negated clique partition after a coefficient was removed */
6512 	            }
6513 	            /* if we deleted the last element of the clique with biggest index, we have to decrease the clique number */
6514 	            else if( pos == consdata->nvars - 1)
6515 	            {
6516 	               cliquenumbefore = consdata->negcliquepartition[pos];
6517 	               for( i = pos - 1; i >= 0 && i >= cliquenumbefore && consdata->negcliquepartition[i] < cliquenumbefore; --i ); /*lint !e722*/
6518 	
6519 	               if( i < cliquenumbefore )
6520 	                  --(consdata->nnegcliques);
6521 	            }
6522 	            /* otherwise if the old clique number is equal to the new one the cliquepartition should be ok */
6523 	         }
6524 	      }
6525 	      else
6526 	         --(consdata->nnegcliques);
6527 	   }
6528 	
6529 	   --(consdata->nvars);
6530 	
6531 	   return SCIP_OKAY;
6532 	}
6533 	
6534 	/** removes all items with weight zero from knapsack constraint */
6535 	static
6536 	SCIP_RETCODE removeZeroWeights(
6537 	   SCIP*                 scip,               /**< SCIP data structure */
6538 	   SCIP_CONS*            cons                /**< knapsack constraint */
6539 	   )
6540 	{
6541 	   SCIP_CONSDATA* consdata;
6542 	   int v;
6543 	
6544 	   consdata = SCIPconsGetData(cons);
6545 	   assert(consdata != NULL);
6546 	
6547 	   for( v = consdata->nvars-1; v >= 0; --v )
6548 	   {
6549 	      if( consdata->weights[v] == 0 )
6550 	      {
6551 	         SCIP_CALL( delCoefPos(scip, cons, v) );
6552 	      }
6553 	   }
6554 	
6555 	   return SCIP_OKAY;
6556 	}
6557 	
6558 	/* perform deletion of variables in all constraints of the constraint handler */
6559 	static
6560 	SCIP_RETCODE performVarDeletions(
6561 	   SCIP*                 scip,               /**< SCIP data structure */
6562 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
6563 	   SCIP_CONS**           conss,              /**< array of constraints */
6564 	   int                   nconss              /**< number of constraints */
6565 	   )
6566 	{
6567 	   SCIP_CONSDATA* consdata;
6568 	   int i;
6569 	   int v;
6570 	
6571 	   assert(scip != NULL);
6572 	   assert(conshdlr != NULL);
6573 	   assert(conss != NULL);
6574 	   assert(nconss >= 0);
6575 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
6576 	
6577 	   /* iterate over all constraints */
6578 	   for( i = 0; i < nconss; i++ )
6579 	   {
6580 	      consdata = SCIPconsGetData(conss[i]);
6581 	
6582 	      /* constraint is marked, that some of its variables were deleted */
6583 	      if( consdata->varsdeleted )
6584 	      {
6585 	         /* iterate over all variables of the constraint and delete them from the constraint */
6586 	         for( v = consdata->nvars - 1; v >= 0; --v )
6587 	         {
6588 	            if( SCIPvarIsDeleted(consdata->vars[v]) )
6589 	            {
6590 	               SCIP_CALL( delCoefPos(scip, conss[i], v) );
6591 	            }
6592 	         }
6593 	         consdata->varsdeleted = FALSE;
6594 	      }
6595 	   }
6596 	
6597 	   return SCIP_OKAY;
6598 	}
6599 	
6600 	/** replaces multiple occurrences of a variable or its negation by a single coefficient */
6601 	static
6602 	SCIP_RETCODE mergeMultiples(
6603 	   SCIP*                 scip,               /**< SCIP data structure */
6604 	   SCIP_CONS*            cons,               /**< knapsack constraint */
6605 	   SCIP_Bool*            cutoff              /**< pointer to store whether the node can be cut off */
6606 	   )
6607 	{
6608 	   SCIP_CONSDATA* consdata;
6609 	   int v;
6610 	   int prev;
6611 	
6612 	   assert(scip != NULL);
6613 	   assert(cons != NULL);
6614 	   assert(cutoff != NULL);
6615 	
6616 	   consdata = SCIPconsGetData(cons);
6617 	   assert(consdata != NULL);
6618 	
6619 	   *cutoff = FALSE;
6620 	
6621 	   if( consdata->merged )
6622 	      return SCIP_OKAY;
6623 	
6624 	   if( consdata->nvars <= 1 )
6625 	   {
6626 	      consdata->merged = TRUE;
6627 	      return SCIP_OKAY;
6628 	   }
6629 	
6630 	   assert(consdata->vars != NULL || consdata->nvars == 0);
6631 	
6632 	   /* sorting array after indices of variables, that's only for faster merging */
6633 	   SCIPsortPtrPtrLongIntInt((void**)consdata->vars, (void**)consdata->eventdata, consdata->weights,
6634 	      consdata->cliquepartition, consdata->negcliquepartition, SCIPvarCompActiveAndNegated, consdata->nvars);
6635 	
6636 	   /* knapsack-sorting (decreasing weights) now lost */
6637 	   consdata->sorted = FALSE;
6638 	
6639 	   v = consdata->nvars - 1;
6640 	   prev = v - 1;
6641 	   /* loop backwards through the items: deletion only affects rear items */
6642 	   while( prev >= 0 )
6643 	   {
6644 	      SCIP_VAR* var1;
6645 	      SCIP_VAR* var2;
6646 	      SCIP_Bool negated1;
6647 	      SCIP_Bool negated2;
6648 	
6649 	      negated1 = FALSE;
6650 	      negated2 = FALSE;
6651 	
6652 	      var1 = consdata->vars[v];
6653 	      assert(SCIPvarIsBinary(var1));
6654 	      assert(SCIPvarIsActive(var1) || SCIPvarGetStatus(var1) == SCIP_VARSTATUS_NEGATED);
6655 	      if( SCIPvarGetStatus(var1) == SCIP_VARSTATUS_NEGATED )
6656 	      {
6657 	         var1 = SCIPvarGetNegatedVar(var1);
6658 	         negated1 = TRUE;
6659 	      }
6660 	      assert(var1 != NULL);
6661 	
6662 	      var2 = consdata->vars[prev];
6663 	      assert(SCIPvarIsBinary(var2));
6664 	      assert(SCIPvarIsActive(var2) || SCIPvarGetStatus(var2) == SCIP_VARSTATUS_NEGATED);
6665 	      if( SCIPvarGetStatus(var2) == SCIP_VARSTATUS_NEGATED )
6666 	      {
6667 	         var2 = SCIPvarGetNegatedVar(var2);
6668 	         negated2 = TRUE;
6669 	      }
6670 	      assert(var2 != NULL);
6671 	
6672 	      if( var1 == var2 )
6673 	      {
6674 	         /* both variables are either active or negated */
6675 	         if( negated1 == negated2 )
6676 	         {
6677 	            /* variables var1 and var2 are equal: add weight of var1 to var2, and delete var1 */
6678 	            consdataChgWeight(consdata, prev, consdata->weights[v] + consdata->weights[prev]);
6679 	            SCIP_CALL( delCoefPos(scip, cons, v) );
6680 	         }
6681 	         /* variables var1 and var2 are opposite: subtract smaller weight from larger weight, reduce capacity,
6682 	          * and delete item of smaller weight
6683 	          */
6684 	         else if( consdata->weights[v] == consdata->weights[prev] )
6685 	         {
6686 	            /* both variables eliminate themselves: w*x + w*(1-x) == w */
6687 	            consdata->capacity -= consdata->weights[v];
6688 	            SCIP_CALL( delCoefPos(scip, cons, v) ); /* this does not affect var2, because var2 stands before var1 */
6689 	            SCIP_CALL( delCoefPos(scip, cons, prev) );
6690 	
6691 	            --prev;
6692 	         }
6693 	         else if( consdata->weights[v] < consdata->weights[prev] )
6694 	         {
6695 	            consdata->capacity -= consdata->weights[v];
6696 	            consdataChgWeight(consdata, prev, consdata->weights[prev] - consdata->weights[v]);
6697 	            assert(consdata->weights[prev] > 0);
6698 	            SCIP_CALL( delCoefPos(scip, cons, v) ); /* this does not affect var2, because var2 stands before var1 */
6699 	         }
6700 	         else
6701 	         {
6702 	            consdata->capacity -= consdata->weights[prev];
6703 	            consdataChgWeight(consdata, v, consdata->weights[v] - consdata->weights[prev]);
6704 	            assert(consdata->weights[v] > 0);
6705 	            SCIP_CALL( delCoefPos(scip, cons, prev) ); /* attention: normally we lose our order */
6706 	            /* restore order iff necessary */
6707 	            if( consdata->nvars != v ) /* otherwise the order still stands */
6708 	            {
6709 	               assert(prev == 0 || ((prev > 0) && (SCIPvarIsActive(consdata->vars[prev - 1]) || SCIPvarGetStatus(consdata->vars[prev - 1]) == SCIP_VARSTATUS_NEGATED)) );
6710 	               /* either that was the last pair or both, the negated and "normal" variable in front doesn't match var1, so the order is irrelevant */
6711 	               if( prev == 0 || (var1 != consdata->vars[prev - 1] && var1 != SCIPvarGetNegatedVar(consdata->vars[prev - 1])) )
6712 	                  --prev;
6713 	               else /* we need to let v at the same position*/
6714 	               {
6715 	                  consdata->cliquesadded = FALSE; /* reduced capacity might lead to larger cliques */
6716 	                  /* don't decrease v, the same variable may exist up front */
6717 	                  --prev;
6718 	                  continue;
6719 	               }
6720 	            }
6721 	         }
6722 	         consdata->cliquesadded = FALSE; /* reduced capacity might lead to larger cliques */
6723 	      }
6724 	      v = prev;
6725 	      --prev;
6726 	   }
6727 	
6728 	   consdata->merged = TRUE;
6729 	
6730 	   /* check infeasibility */
6731 	   if( consdata->onesweightsum > consdata->capacity )
6732 	   {
6733 	      SCIPdebugMsg(scip, "merge multiples detected cutoff.\n");
6734 	      *cutoff = TRUE;
6735 	      return SCIP_OKAY;
6736 	   }
6737 	
6738 	   return SCIP_OKAY;
6739 	}
6740 	
6741 	/** in case the knapsack constraint is independent of every else, solve the knapsack problem (exactly) and apply the
6742 	 *  fixings (dual reductions)
6743 	 */
6744 	static
6745 	SCIP_RETCODE dualPresolving(
6746 	   SCIP*                 scip,               /**< SCIP data structure */
6747 	   SCIP_CONS*            cons,               /**< knapsack constraint */
6748 	   int*                  nfixedvars,         /**< pointer to count number of fixings */
6749 	   int*                  ndelconss,          /**< pointer to count number of deleted constraints  */
6750 	   SCIP_Bool*            deleted             /**< pointer to store if the constraint is deleted */
6751 	   )
6752 	{
6753 	   SCIP_CONSDATA* consdata;
6754 	   SCIP_VAR** vars;
6755 	   SCIP_Real* profits;
6756 	   int* solitems;
6757 	   int* nonsolitems;
6758 	   int* items;
6759 	   SCIP_Real solval;
6760 	   SCIP_Bool infeasible;
6761 	   SCIP_Bool tightened;
6762 	   SCIP_Bool applicable;
6763 	   int nsolitems;
6764 	   int nnonsolitems;
6765 	   int nvars;
6766 	   int v;
6767 	
6768 	   assert(!SCIPconsIsModifiable(cons));
6769 	
6770 	   /* constraints for which the check flag is set to FALSE, did not contribute to the lock numbers; therefore, we cannot
6771 	    * use the locks to decide for a dual reduction using this constraint; for example after a restart the cuts which are
6772 	    * added to the problems have the check flag set to FALSE
6773 	    */
6774 	   if( !SCIPconsIsChecked(cons) )
6775 	      return SCIP_OKAY;
6776 	
6777 	   consdata = SCIPconsGetData(cons);
6778 	   assert(consdata != NULL);
6779 	
6780 	   nvars = consdata->nvars;
6781 	   vars = consdata->vars;
6782 	
6783 	   SCIP_CALL( SCIPallocBufferArray(scip, &profits, nvars) );
6784 	   SCIP_CALL( SCIPallocBufferArray(scip, &items, nvars) );
6785 	   SCIP_CALL( SCIPallocBufferArray(scip, &solitems, nvars) );
6786 	   SCIP_CALL( SCIPallocBufferArray(scip, &nonsolitems, nvars) );
6787 	
6788 	   applicable = TRUE;
6789 	
6790 	   /* check if we can apply the dual reduction; this can be done if the knapsack has the only locks on this constraint;
6791 	    * collect object values which are the profits of the knapsack problem
6792 	    */
6793 	   for( v = 0; v < nvars; ++v )
6794 	   {
6795 	      SCIP_VAR* var;
6796 	      SCIP_Bool negated;
6797 	
6798 	      var = vars[v];
6799 	      assert(var != NULL);
6800 	
6801 	      /* the variable should not be (globally) fixed */
6802 	      assert(SCIPvarGetLbGlobal(var) < 0.5 && SCIPvarGetUbGlobal(var) > 0.5);
6803 	
6804 	      if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) > 0
6805 	         || SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) > 1 )
6806 	      {
6807 	         applicable = FALSE;
6808 	         break;
6809 	      }
6810 	
6811 	      negated = FALSE;
6812 	
6813 	      /* get the active variable */
6814 	      SCIP_CALL( SCIPvarGetProbvarBinary(&var, &negated) );
6815 	      assert(SCIPvarIsActive(var));
6816 	
6817 	      if( negated )
6818 	         profits[v] = SCIPvarGetObj(var);
6819 	      else
6820 	         profits[v] = -SCIPvarGetObj(var);
6821 	
6822 	      SCIPdebugMsg(scip, "variable <%s> -> item size %" SCIP_LONGINT_FORMAT ", profit <%g>\n",
6823 	         SCIPvarGetName(vars[v]), consdata->weights[v], profits[v]);
6824 	      items[v] = v;
6825 	   }
6826 	
6827 	   if( applicable )
6828 	   {
6829 	      SCIP_Bool success;
6830 	
6831 	      SCIPdebugMsg(scip, "the knapsack constraint <%s> is independent to rest of the problem\n", SCIPconsGetName(cons));
6832 	      SCIPdebugPrintCons(scip, cons, NULL);
6833 	
6834 	      /* solve knapsack problem exactly */
6835 	      SCIP_CALL( SCIPsolveKnapsackExactly(scip, consdata->nvars, consdata->weights, profits, consdata->capacity,
6836 	            items, solitems, nonsolitems, &nsolitems, &nnonsolitems, &solval, &success) );
6837 	
6838 	      if( success )
6839 	      {
6840 	         SCIP_VAR* var;
6841 	
6842 	         /* apply solution of the knapsack as dual reductions */
6843 	         for( v = 0; v < nsolitems; ++v )
6844 	         {
6845 	            var = vars[solitems[v]];
6846 	            assert(var != NULL);
6847 	
6848 	            SCIPdebugMsg(scip, "variable <%s> only locked up in knapsack constraints: dual presolve <%s>[%.15g,%.15g] >= 1.0\n",
6849 	               SCIPvarGetName(var), SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var));
6850 	            SCIP_CALL( SCIPtightenVarLb(scip, var, 1.0, TRUE, &infeasible, &tightened) );
6851 	            assert(!infeasible);
6852 	            assert(tightened);
6853 	            (*nfixedvars)++;
6854 	         }
6855 	
6856 	         for( v = 0; v < nnonsolitems; ++v )
6857 	         {
6858 	            var = vars[nonsolitems[v]];
6859 	            assert(var != NULL);
6860 	
6861 	            SCIPdebugMsg(scip, "variable <%s> has no down locks: dual presolve <%s>[%.15g,%.15g] <= 0.0\n",
6862 	               SCIPvarGetName(var), SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var));
6863 	            SCIP_CALL( SCIPtightenVarUb(scip, var, 0.0, TRUE, &infeasible, &tightened) );
6864 	            assert(!infeasible);
6865 	            assert(tightened);
6866 	            (*nfixedvars)++;
6867 	         }
6868 	
6869 	         SCIP_CALL( SCIPdelCons(scip, cons) );
6870 	         (*ndelconss)++;
6871 	         (*deleted) = TRUE;
6872 	      }
6873 	   }
6874 	
6875 	   SCIPfreeBufferArray(scip, &nonsolitems);
6876 	   SCIPfreeBufferArray(scip, &solitems);
6877 	   SCIPfreeBufferArray(scip, &items);
6878 	   SCIPfreeBufferArray(scip, &profits);
6879 	
6880 	   return SCIP_OKAY;
6881 	}
6882 	
6883 	/** check if the knapsack constraint is parallel to objective function; if so update the cutoff bound and avoid that the
6884 	 *  constraint enters the LP by setting the initial and separated flag to FALSE
6885 	 */
6886 	static
6887 	SCIP_RETCODE checkParallelObjective(
6888 	   SCIP*                 scip,               /**< SCIP data structure */
6889 	   SCIP_CONS*            cons,               /**< knapsack constraint */
6890 	   SCIP_CONSHDLRDATA*    conshdlrdata        /**< knapsack constraint handler data */
6891 	   )
6892 	{
6893 	   SCIP_CONSDATA* consdata;
6894 	   SCIP_VAR** vars;
6895 	   SCIP_VAR* var;
6896 	   SCIP_Real offset;
6897 	   SCIP_Real scale;
6898 	   SCIP_Real objval;
6899 	   SCIP_Bool applicable;
6900 	   SCIP_Bool negated;
6901 	   int nobjvars;
6902 	   int nvars;
6903 	   int v;
6904 	
6905 	   assert(scip != NULL);
6906 	   assert(cons != NULL);
6907 	   assert(conshdlrdata != NULL);
6908 	
6909 	   consdata = SCIPconsGetData(cons);
6910 	   assert(consdata != NULL);
6911 	
6912 	   nvars = consdata->nvars;
6913 	   nobjvars = SCIPgetNObjVars(scip);
6914 	
6915 	   /* check if the knapsack constraints has the same number of variables as the objective function and if the initial
6916 	    * and/or separated flag is set to FALSE
6917 	    */
6918 	   if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
6919 	      return SCIP_OKAY;
6920 	
6921 	   /* There are no variables in the ojective function and in the constraint. Thus, the constraint is redundant. Since we
6922 	    * have a pure feasibility problem, we do not want to set a cutoff or lower bound.
6923 	    */
6924 	   if( nobjvars == 0 )
6925 	      return SCIP_OKAY;
6926 	
6927 	   vars = consdata->vars;
6928 	   assert(vars != NULL);
6929 	
6930 	   applicable = TRUE;
6931 	   offset = 0.0;
6932 	   scale = 1.0;
6933 	
6934 	   for( v = 0; v < nvars && applicable; ++v )
6935 	   {
6936 	      negated = FALSE;
6937 	      var = vars[v];
6938 	      assert(var != NULL);
6939 	
6940 	      if( SCIPvarIsNegated(var) )
6941 	      {
6942 	         negated = TRUE;
6943 	         var = SCIPvarGetNegatedVar(var);
6944 	         assert(var != NULL);
6945 	      }
6946 	
6947 	      objval = SCIPvarGetObj(var);
6948 	
6949 	      /* if a variable has a zero objective coefficient the knapsack constraint is not parallel to objective function */
6950 	      if( SCIPisZero(scip, objval) )
6951 	         applicable = FALSE;
6952 	      else
6953 	      {
6954 	         SCIP_Real weight;
6955 	
6956 	         weight = (SCIP_Real)consdata->weights[v];
6957 	
6958 	         if( negated )
6959 	         {
6960 	            if( v == 0 )
6961 	            {
6962 	               /* the first variable defines the scale */
6963 	               scale = weight / -objval;
6964 	
6965 	               offset += weight;
6966 	            }
6967 	            else if( SCIPisEQ(scip, -objval * scale, weight) )
6968 	               offset += weight;
6969 	            else
6970 	               applicable = FALSE;
6971 	         }
6972 	         else if( v == 0 )
6973 	         {
6974 	            /* the first variable define the scale */
6975 	            scale = weight / objval;
6976 	         }
6977 	         else if( !SCIPisEQ(scip, objval * scale, weight) )
6978 	            applicable = FALSE;
6979 	      }
6980 	   }
6981 	
6982 	   if( applicable )
6983 	   {
6984 	      if( SCIPisPositive(scip, scale) && conshdlrdata->detectcutoffbound )
6985 	      {
6986 	         SCIP_Real cutoffbound;
6987 	
6988 	         /* avoid that the knapsack constraint enters the LP since it is parallel to the objective function */
6989 	         SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
6990 	         SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
6991 	
6992 	         cutoffbound = (consdata->capacity - offset) / scale;
6993 	
6994 	         SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provids a cutoff bound <%g>\n",
6995 	            SCIPconsGetName(cons), cutoffbound);
6996 	
6997 	         /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are
6998 	          * still excepted
6999 	          */
7000 	         cutoffbound += SCIPcutoffbounddelta(scip);
7001 	
7002 	         SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provids a cutoff bound <%g>\n",
7003 	            SCIPconsGetName(cons), cutoffbound);
7004 	
7005 	         if( cutoffbound < SCIPgetCutoffbound(scip) )
7006 	         {
7007 	            SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
7008 	
7009 	            SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
7010 	         }
7011 	         else
7012 	         {
7013 	            /* in case the cutoff bound is worse then currently known one we avoid additionaly enforcement and
7014 	             * propagation
7015 	             */
7016 	            SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
7017 	            SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
7018 	         }
7019 	      }
7020 	      else if( SCIPisNegative(scip, scale) && conshdlrdata->detectlowerbound )
7021 	      {
7022 	         SCIP_Real lowerbound;
7023 	
7024 	         /* avoid that the knapsack constraint enters the LP since it is parallel to the objective function */
7025 	         SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
7026 	         SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
7027 	
7028 	         lowerbound = (consdata->capacity - offset) / scale;
7029 	
7030 	         SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provids a lower bound <%g>\n",
7031 	            SCIPconsGetName(cons), lowerbound);
7032 	
7033 	         SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
7034 	      }
7035 	   }
7036 	
7037 	   return SCIP_OKAY;
7038 	}
7039 	
7040 	/** sort the variables and weights w.r.t. the clique partition; thereby ensure the current order of the variables when a
7041 	 *  weight of one variable is greater or equal another weight and both variables are in the same cliques */
7042 	static
7043 	SCIP_RETCODE stableSort(
7044 	   SCIP*                 scip,               /**< SCIP data structure */
7045 	   SCIP_CONSDATA*        consdata,           /**< knapsack constraint data */
7046 	   SCIP_VAR**            vars,               /**< array for sorted variables */
7047 	   SCIP_Longint*         weights,            /**< array for sorted weights */
7048 	   int*                  cliquestartposs,    /**< starting position array for each clique */
7049 	   SCIP_Bool             usenegatedclique    /**< should negated or normal clique partition be used */
7050 	   )
7051 	{
7052 	   SCIP_VAR** origvars;
7053 	   int norigvars;
7054 	   SCIP_Longint* origweights;
7055 	   int* cliquepartition;
7056 	   int ncliques;
7057 	
7058 	   SCIP_VAR*** varpointers;
7059 	   SCIP_Longint** weightpointers;
7060 	   int* cliquecount;
7061 	
7062 	   int nextpos;
7063 	   int c;
7064 	   int v;
7065 	
7066 	   assert(scip != NULL);
7067 	   assert(consdata != NULL);
7068 	   assert(vars != NULL);
7069 	   assert(weights != NULL);
7070 	   assert(cliquestartposs != NULL);
7071 	
7072 	   origweights = consdata->weights;
7073 	   origvars = consdata->vars;
7074 	   norigvars = consdata->nvars;
7075 	
7076 	   assert(origvars != NULL || norigvars == 0);
7077 	   assert(origweights != NULL || norigvars == 0);
7078 	
7079 	   if( norigvars == 0 )
7080 	      return SCIP_OKAY;
7081 	
7082 	   if( usenegatedclique )
7083 	   {
7084 	      assert(consdata->negcliquepartitioned);
7085 	
7086 	      cliquepartition = consdata->negcliquepartition;
7087 	      ncliques = consdata->nnegcliques;
7088 	   }
7089 	   else
7090 	   {
7091 	      assert(consdata->cliquepartitioned);
7092 	
7093 	      cliquepartition = consdata->cliquepartition;
7094 	      ncliques = consdata->ncliques;
7095 	   }
7096 	
7097 	   assert(cliquepartition != NULL);
7098 	   assert(ncliques > 0);
7099 	
7100 	   /* we first count all clique items and alloc temporary memory for a bucket sort */
7101 	   SCIP_CALL( SCIPallocBufferArray(scip, &cliquecount, ncliques) );
7102 	   BMSclearMemoryArray(cliquecount, ncliques);
7103 	
7104 	   /* first we count for each clique the number of elements */
7105 	   for( v = norigvars - 1; v >= 0; --v )
7106 	   {
7107 	      assert(0 <= cliquepartition[v] && cliquepartition[v] < ncliques);
7108 	      ++(cliquecount[cliquepartition[v]]);
7109 	   }
7110 	
7111 	   /*@todo: maybe it is better to put largest cliques up front */
7112 	
7113 	#ifndef NDEBUG
7114 	   BMSclearMemoryArray(vars, norigvars);
7115 	   BMSclearMemoryArray(weights, norigvars);
7116 	#endif
7117 	   SCIP_CALL( SCIPallocBufferArray(scip, &varpointers, ncliques) );
7118 	   SCIP_CALL( SCIPallocBufferArray(scip, &weightpointers, ncliques) );
7119 	
7120 	   nextpos = 0;
7121 	   /* now we initialize all start pointers for each clique, so they will be ordered */
7122 	   for( c = 0; c < ncliques; ++c )
7123 	   {
7124 	      /* to reach the goal that all variables of each clique will be standing next to each other we will initialize the
7125 	       * starting pointers for each clique by adding the number of each clique to the last clique starting pointer
7126 	       * e.g. clique1 has 4 elements and clique2 has 3 elements the the starting pointer for clique1 will be the pointer
7127 	       *      to vars[0], the starting pointer to clique2 will be the pointer to vars[4] and to clique3 it will be
7128 	       *      vars[7]
7129 	       *
7130 	       */
7131 	      varpointers[c] = (SCIP_VAR**) (vars + nextpos);
7132 	      cliquestartposs[c] = nextpos;
7133 	      weightpointers[c] = (SCIP_Longint*) (weights + nextpos);
7134 	      assert(cliquecount[c] > 0);
7135 	      nextpos += cliquecount[c];
7136 	      assert(nextpos > 0);
7137 	   }
7138 	   assert(nextpos == norigvars);
7139 	   cliquestartposs[c] = nextpos;
7140 	
7141 	   /* now we copy all variable and weights to the right order */
7142 	   for( v = 0; v < norigvars; ++v )
7143 	   {
7144 	      *(varpointers[cliquepartition[v]]) = origvars[v];  /*lint !e613*/
7145 	      ++(varpointers[cliquepartition[v]]);
7146 	      *(weightpointers[cliquepartition[v]]) = origweights[v];  /*lint !e613*/
7147 	      ++(weightpointers[cliquepartition[v]]);
7148 	   }
7149 	#ifndef NDEBUG
7150 	   for( v = 0; v < norigvars; ++v )
7151 	   {
7152 	      assert(vars[v] != NULL);
7153 	      assert(weights[v] > 0);
7154 	   }
7155 	#endif
7156 	
7157 	   /* free temporary memory */
7158 	   SCIPfreeBufferArray(scip, &weightpointers);
7159 	   SCIPfreeBufferArray(scip, &varpointers);
7160 	   SCIPfreeBufferArray(scip, &cliquecount);
7161 	
7162 	   return SCIP_OKAY;
7163 	}
7164 	
7165 	/** deletes all fixed variables from knapsack constraint, and replaces variables with binary representatives */
7166 	static
7167 	SCIP_RETCODE applyFixings(
7168 	   SCIP*                 scip,               /**< SCIP data structure */
7169 	   SCIP_CONS*            cons,               /**< knapsack constraint */
7170 	   SCIP_Bool*            cutoff              /**< pointer to store whether the node can be cut off, or NULL if this
7171 	                                              *   information is not needed; in this case, we apply all fixings
7172 	                                              *   instead of stopping after the first infeasible one */
7173 	   )
7174 	{
7175 	   SCIP_CONSDATA* consdata;
7176 	   int v;
7177 	
7178 	   assert(scip != NULL);
7179 	   assert(cons != NULL);
7180 	
7181 	   consdata = SCIPconsGetData(cons);
7182 	   assert(consdata != NULL);
7183 	   assert(consdata->nvars == 0 || consdata->vars != NULL);
7184 	
7185 	   if( cutoff != NULL )
7186 	      *cutoff = FALSE;
7187 	
7188 	   SCIPdebugMsg(scip, "apply fixings:\n");
7189 	   SCIPdebugPrintCons(scip, cons, NULL);
7190 	
7191 	   /* check infeasibility */
7192 	   if ( consdata->onesweightsum > consdata->capacity )
7193 	   {
7194 	      SCIPdebugMsg(scip, "apply fixings detected cutoff.\n");
7195 	
7196 	      if( cutoff != NULL )
7197 	         *cutoff = TRUE;
7198 	
7199 	      return SCIP_OKAY;
7200 	   }
7201 	
7202 	   /* all multi-aggregations should be resolved */
7203 	   consdata->existmultaggr = FALSE;
7204 	
7205 	   v = 0;
7206 	   while( v < consdata->nvars )
7207 	   {
7208 	      SCIP_VAR* var;
7209 	
7210 	      var = consdata->vars[v];
7211 	      assert(SCIPvarIsBinary(var));
7212 	
7213 	      if( SCIPvarGetLbGlobal(var) > 0.5 )
7214 	      {
7215 	         assert(SCIPisFeasEQ(scip, SCIPvarGetUbGlobal(var), 1.0));
7216 	         consdata->capacity -= consdata->weights[v];
7217 	         SCIP_CALL( delCoefPos(scip, cons, v) );
7218 	         consdata->cliquesadded = FALSE; /* reduced capacity might lead to larger cliques */
7219 	      }
7220 	      else if( SCIPvarGetUbGlobal(var) < 0.5 )
7221 	      {
7222 	         assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), 0.0));
7223 	         SCIP_CALL( delCoefPos(scip, cons, v) );
7224 	      }
7225 	      else
7226 	      {
7227 	         SCIP_VAR* repvar;
7228 	         SCIP_VAR* negvar;
7229 	         SCIP_VAR* workvar;
7230 	         SCIP_Longint weight;
7231 	         SCIP_Bool negated;
7232 	
7233 	         weight = consdata->weights[v];
7234 	
7235 	         /* get binary representative of variable */
7236 	         SCIP_CALL( SCIPgetBinvarRepresentative(scip, var, &repvar, &negated) );
7237 	         assert(repvar != NULL);
7238 	
7239 	         /* check for multi-aggregation */
7240 	         if( SCIPvarIsNegated(repvar) )
7241 	         {
7242 	            workvar = SCIPvarGetNegatedVar(repvar);
7243 	            assert(workvar != NULL);
7244 	            negated = TRUE;
7245 	         }
7246 	         else
7247 	         {
7248 	            workvar = repvar;
7249 	            negated = FALSE;
7250 	         }
7251 	
7252 	         /* @todo maybe resolve the problem that the eliminating of the multi-aggregation leads to a non-knapsack
7253 	          * constraint (converting into a linear constraint), for example the multi-aggregation consist of a non-binary
7254 	          * variable or due to resolving now their are non-integral coefficients or a non-integral capacity
7255 	          *
7256 	          * If repvar is not negated so workvar = repvar, otherwise workvar = 1 - repvar. This means,
7257 	          * weight * workvar = weight * (a_1*y_1 + ... + a_n*y_n + c)
7258 	          *
7259 	          * The explanation for  the following block:
7260 	          * 1a) If repvar is a multi-aggregated variable weight * repvar should be replaced by
7261 	          *     weight * (a_1*y_1 + ... + a_n*y_n + c).
7262 	          * 1b) If repvar is a negated variable of a multi-aggregated variable weight * repvar should be replaced by
7263 	          *     weight - weight * (a_1*y_1 + ... + a_n*y_n + c), for better further use here we switch the sign of weight
7264 	          *     so now we have the replacement -weight + weight * (a_1*y_1 + ... + a_n*y_n + c).
7265 	          * 2)  For all replacement variable we check:
7266 	          * 2a) weight * a_i < 0 than we add -weight * a_i * y_i_neg to the constraint and adjust the capacity through
7267 	          *     capacity -= weight * a_i caused by the negation of y_i.
7268 	          * 2b) weight * a_i >= 0 than we add weight * a_i * y_i to the constraint.
7269 	          * 3a) If repvar was not negated we need to subtract weight * c from capacity.
7270 	          * 3b) If repvar was negated we need to subtract weight * (c - 1) from capacity(note we switched the sign of
7271 	          *     weight in this case.
7272 	          */
7273 	         if( SCIPvarGetStatus(workvar) == SCIP_VARSTATUS_MULTAGGR )
7274 	         {
7275 	            SCIP_VAR** aggrvars;
7276 	            SCIP_Real* aggrscalars;
7277 	            SCIP_Real aggrconst;
7278 	            int naggrvars;
7279 	            int i;
7280 	
7281 	            SCIP_CALL( SCIPflattenVarAggregationGraph(scip, workvar) );
7282 	            naggrvars = SCIPvarGetMultaggrNVars(workvar);
7283 	            aggrvars = SCIPvarGetMultaggrVars(workvar);
7284 	            aggrscalars = SCIPvarGetMultaggrScalars(workvar);
7285 	            aggrconst = SCIPvarGetMultaggrConstant(workvar);
7286 	            assert((aggrvars != NULL && aggrscalars != NULL) || naggrvars == 0);
7287 	
7288 	            if( !SCIPisIntegral(scip, weight * aggrconst) )
7289 	            {
7290 	               SCIPerrorMessage("try to resolve a multi-aggregation with a non-integral value for weight*aggrconst = %g\n", weight*aggrconst);
7291 	               return SCIP_ERROR;
7292 	            }
7293 	
7294 	            /* if workvar was negated, we have to flip the weight */
7295 	            if( negated )
7296 	               weight *= -1;
7297 	
7298 	            for( i = naggrvars - 1; i >= 0; --i )
7299 	            {
7300 	               assert(aggrvars != NULL);
7301 	               assert(aggrscalars != NULL);
7302 	
7303 	               if( !SCIPvarIsBinary(aggrvars[i]) )
7304 	               {
7305 	                  SCIPerrorMessage("try to resolve a multi-aggregation with a non-binary %svariable <%s> with bounds [%g,%g]\n",
7306 	                     SCIPvarIsIntegral(aggrvars[i]) ? "integral " : "", SCIPvarGetName(aggrvars[i]),  SCIPvarGetLbGlobal(aggrvars[i]), SCIPvarGetUbGlobal(aggrvars[i]));
7307 	                  return SCIP_ERROR;
7308 	               }
7309 	               if( !SCIPisIntegral(scip, weight * aggrscalars[i]) )
7310 	               {
7311 	                  SCIPerrorMessage("try to resolve a multi-aggregation with a non-integral value for weight*aggrscalars = %g\n", weight*aggrscalars[i]);
7312 	                  return SCIP_ERROR;
7313 	               }
7314 	               /* if the new coefficient is smaller than zero, we need to add the negated variable instead and adjust the capacity */
7315 	               if( SCIPisNegative(scip, weight * aggrscalars[i]) )
7316 	               {
7317 	                  SCIP_CALL( SCIPgetNegatedVar(scip, aggrvars[i], &negvar));
7318 	                  assert(negvar != NULL);
7319 	                  SCIP_CALL( addCoef(scip, cons, negvar, (SCIP_Longint)(SCIPfloor(scip, -weight * aggrscalars[i] + 0.5))) );
7320 	                  consdata->capacity -= (SCIP_Longint)(SCIPfloor(scip, weight * aggrscalars[i] + 0.5));
7321 	               }
7322 	               else
7323 	               {
7324 	                  SCIP_CALL( addCoef(scip, cons, aggrvars[i], (SCIP_Longint)(SCIPfloor(scip, weight * aggrscalars[i] + 0.5))) );
7325 	               }
7326 	            }
7327 	            /* delete old coefficient */
7328 	            SCIP_CALL( delCoefPos(scip, cons, v) );
7329 	
7330 	            /* adjust the capacity with the aggregation constant and if necessary the extra weight through the negation */
7331 	            if( negated )
7332 	               consdata->capacity -= (SCIP_Longint)SCIPfloor(scip, weight * (aggrconst - 1) + 0.5);
7333 	            else
7334 	               consdata->capacity -= (SCIP_Longint)SCIPfloor(scip, weight * aggrconst + 0.5);
7335 	
7336 	            if( consdata->capacity < 0 )
7337 	            {
7338 	               if( cutoff != NULL )
7339 	               {
7340 	                  *cutoff = TRUE;
7341 	                  break;
7342 	               }
7343 	            }
7344 	         }
7345 	         /* check, if the variable should be replaced with the representative */
7346 	         else if( repvar != var )
7347 	         {
7348 	            /* delete old (aggregated) variable */
7349 	            SCIP_CALL( delCoefPos(scip, cons, v) );
7350 	
7351 	            /* add representative instead */
7352 	            SCIP_CALL( addCoef(scip, cons, repvar, weight) );
7353 	         }
7354 	         else
7355 	            ++v;
7356 	      }
7357 	   }
7358 	   assert(consdata->onesweightsum == 0);
7359 	
7360 	   SCIPdebugMsg(scip, "after applyFixings, before merging:\n");
7361 	   SCIPdebugPrintCons(scip, cons, NULL);
7362 	
7363 	   /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have to
7364 	    * clean up the constraint
7365 	    */
7366 	   if( cutoff != NULL && !(*cutoff) )
7367 	   {
7368 	      SCIP_CALL( mergeMultiples(scip, cons, cutoff) );
7369 	      SCIPdebugMsg(scip, "after applyFixings and merging:\n");
7370 	      SCIPdebugPrintCons(scip, cons, NULL);
7371 	   }
7372 	
7373 	   return SCIP_OKAY;
7374 	}
7375 	
7376 	
7377 	/** propagation method for knapsack constraints */
7378 	static
7379 	SCIP_RETCODE propagateCons(
7380 	   SCIP*                 scip,               /**< SCIP data structure */
7381 	   SCIP_CONS*            cons,               /**< knapsack constraint */
7382 	   SCIP_Bool*            cutoff,             /**< pointer to store whether the node can be cut off */
7383 	   SCIP_Bool*            redundant,          /**< pointer to store whether constraint is redundant */
7384 	   int*                  nfixedvars,         /**< pointer to count number of fixings */
7385 	   SCIP_Bool             usenegatedclique    /**< should negated clique information be used */
7386 	   )
7387 	{
7388 	   SCIP_CONSDATA* consdata;
7389 	   SCIP_Bool infeasible;
7390 	   SCIP_Bool tightened;
7391 	   SCIP_Longint* secondmaxweights;
7392 	   SCIP_Longint minweightsum;
7393 	   SCIP_Longint residualcapacity;
7394 	
7395 	   int nvars;
7396 	   int i;
7397 	   int nnegcliques;
7398 	
7399 	   SCIP_VAR** myvars;
7400 	   SCIP_Longint* myweights;
7401 	   int* cliquestartposs;
7402 	   int* cliqueendposs;
7403 	   SCIP_Longint localminweightsum;
7404 	   SCIP_Bool foundmax;
7405 	   int c;
7406 	
7407 	   assert(scip != NULL);
7408 	   assert(cons != NULL);
7409 	   assert(cutoff != NULL);
7410 	   assert(redundant != NULL);
7411 	   assert(nfixedvars != NULL);
7412 	
7413 	   consdata = SCIPconsGetData(cons);
7414 	   assert(consdata != NULL);
7415 	
7416 	   *cutoff = FALSE;
7417 	   *redundant = FALSE;
7418 	
7419 	   SCIPdebugMsg(scip, "propagating knapsack constraint <%s>\n", SCIPconsGetName(cons));
7420 	
7421 	   /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7422 	   if( !SCIPinRepropagation(scip) )
7423 	   {
7424 	      SCIP_CALL( SCIPincConsAge(scip, cons) );
7425 	   }
7426 	
7427 	#ifndef NDEBUG
7428 	   /* assert that only active or negated variables are present */
7429 	   for( i = 0; i < consdata->nvars && consdata->merged; ++i )
7430 	   {
7431 	      assert(SCIPvarIsActive(consdata->vars[i]) || SCIPvarIsNegated(consdata->vars[i]) || SCIPvarGetStatus(consdata->vars[i]) == SCIP_VARSTATUS_FIXED);
7432 	   }
7433 	#endif
7434 	
7435 	   usenegatedclique = usenegatedclique && consdata->merged;
7436 	
7437 	   /* init for debugging */
7438 	   myvars = NULL;
7439 	   myweights = NULL;
7440 	   cliquestartposs = NULL;
7441 	   secondmaxweights = NULL;
7442 	   minweightsum = 0;
7443 	   nvars = consdata->nvars;
7444 	   /* make sure, the items are sorted by non-increasing weight */
7445 	   sortItems(consdata);
7446 	
7447 	   do
7448 	   {
7449 	      localminweightsum = 0;
7450 	
7451 	      /* (1) compute the minimum weight of the knapsack constraint using negated clique information;
7452 	       *     a negated clique means, that at most one of the clique variables can be zero
7453 	       *     - minweightsum = sum_{negated cliques C} ( sum(wi : i \in C) - W_max(C) ), where W_max(C) is the maximal weight of C
7454 	       *
7455 	       *     if for i \in C (a negated clique) oneweightsum + minweightsum - wi + W_max(C) > capacity => xi = 1
7456 	       *     since replacing i with the element of maximal weight leads to infeasibility
7457 	       */
7458 	      if( usenegatedclique && nvars > 0 )
7459 	      {
7460 	         SCIP_CONSHDLRDATA* conshdlrdata;
7461 	         conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
7462 	         assert(conshdlrdata != NULL);
7463 	
7464 	         /* compute clique partitions */
7465 	         SCIP_CALL( calcCliquepartition(scip, conshdlrdata, consdata, FALSE, TRUE) );
7466 	         nnegcliques = consdata->nnegcliques;
7467 	
7468 	         /* if we have no real negated cliques we can stop here */
7469 	         if( nnegcliques == nvars )
7470 	         {
7471 	            /* run the standard algorithm that does not involve cliques */
7472 	            usenegatedclique = FALSE;
7473 	            break;
7474 	         }
7475 	
7476 	         /* allocate temporary memory and initialize it */
7477 	         SCIP_CALL( SCIPduplicateBufferArray(scip, &myvars, consdata->vars, nvars) );
7478 	         SCIP_CALL( SCIPduplicateBufferArray(scip, &myweights, consdata->weights, nvars) ) ;
7479 	         SCIP_CALL( SCIPallocBufferArray(scip, &cliquestartposs, nnegcliques + 1) );
7480 	         SCIP_CALL( SCIPallocBufferArray(scip, &cliqueendposs, nnegcliques) );
7481 	         SCIP_CALL( SCIPallocBufferArray(scip, &secondmaxweights, nnegcliques) );
7482 	         BMSclearMemoryArray(secondmaxweights, nnegcliques);
7483 	
7484 	         /* resort variables to avoid quadratic algorithm later on */
7485 	         SCIP_CALL( stableSort(scip, consdata, myvars, myweights, cliquestartposs, TRUE) );
7486 	
7487 	         /* save the end positions of the cliques because start positions are moved in the following loop */
7488 	         for( c = 0; c < nnegcliques; ++c )
7489 	         {
7490 	            cliqueendposs[c] = cliquestartposs[c+1] - 1;
7491 	            assert(cliqueendposs[c] - cliquestartposs[c] >= 0);
7492 	         }
7493 	
7494 	         c = 0;
7495 	         foundmax = FALSE;
7496 	         i = 0;
7497 	
7498 	         while( i < nvars )
7499 	         {
7500 	            /* ignore variables of the negated clique which are fixed to one since these are counted in
7501 	             * consdata->onesweightsum
7502 	             */
7503 	
7504 	            /* if there are only one variable negated cliques left we can stop */
7505 	            if( nnegcliques - c == nvars - i )
7506 	            {
7507 	               minweightsum += localminweightsum;
7508 	               localminweightsum = 0;
7509 	               break;
7510 	            }
7511 	
7512 	            /* for summing up the minimum active weights due to cliques we have to omit the biggest weights of each
7513 	             * clique, we can only skip this clique if this variables is not fixed to zero, otherwise we have to fix all
7514 	             * other clique variables to one
7515 	             */
7516 	            if( cliquestartposs[c] == i )
7517 	            {
7518 	               assert(myweights[i] > 0);
7519 	               ++c;
7520 	               minweightsum += localminweightsum;
7521 	               localminweightsum = 0;
7522 	               foundmax = TRUE;
7523 	
7524 	               if( SCIPvarGetLbLocal(myvars[i]) > 0.5 )
7525 	                  foundmax = FALSE;
7526 	
7527 	               if( SCIPvarGetUbLocal(myvars[i]) > 0.5 )
7528 	               {
7529 	                  ++i;
7530 	                  continue;
7531 	               }
7532 	            }
7533 	
7534 	            if( SCIPvarGetLbLocal(myvars[i]) < 0.5 )
7535 	            {
7536 	               assert(myweights[i] > 0);
7537 	
7538 	               if( SCIPvarGetUbLocal(myvars[i]) > 0.5 )
7539 	               {
7540 	                  assert(myweights[i] <= myweights[cliquestartposs[c - 1]]);
7541 	
7542 	                  if( !foundmax )
7543 	                  {
7544 	                     foundmax = TRUE;
7545 	
7546 	                     /* overwrite cliquestartpos to the position of the first unfixed variable in this clique */
7547 	                     cliquestartposs[c - 1] = i;
7548 	                     ++i;
7549 	
7550 	                     continue;
7551 	                  }
7552 	                  /* memorize second max weight for each clique */
7553 	                  if( secondmaxweights[c - 1] == 0 )
7554 	                     secondmaxweights[c - 1] = myweights[i];
7555 	
7556 	                  localminweightsum += myweights[i];
7557 	               }
7558 	               /* we found a fixed variable to zero so all other variables in this negated clique have to be fixed to one */
7559 	               else
7560 	               {
7561 	                  int v;
7562 	                  /* fix all other variables of the negated clique to 1 */
7563 	                  for( v = cliquestartposs[c - 1]; v < cliquestartposs[c]; ++v )
7564 	                  {
7565 	                     if( v != i && SCIPvarGetLbLocal(myvars[v]) < 0.5 )
7566 	                     {
7567 	                        SCIPdebugMsg(scip, " -> fixing variable <%s> to 1, due to negated clique information\n", SCIPvarGetName(myvars[v]));
7568 	                        SCIP_CALL( SCIPinferBinvarCons(scip, myvars[v], TRUE, cons, SCIPvarGetIndex(myvars[i]), &infeasible, &tightened) );
7569 	
7570 	                        if( infeasible )
7571 	                        {
7572 	                           assert( SCIPvarGetUbLocal(myvars[v]) < 0.5 );
7573 	
7574 	                           /* analyze the infeasibility if conflict analysis is applicable */
7575 	                           if( SCIPisConflictAnalysisApplicable(scip) )
7576 	                           {
7577 	                              /* conflict analysis can only be applied in solving stage */
7578 	                              assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING || SCIPinProbing(scip));
7579 	
7580 	                              /* initialize the conflict analysis */
7581 	                              SCIP_CALL( SCIPinitConflictAnalysis(scip, SCIP_CONFTYPE_PROPAGATION, FALSE) );
7582 	
7583 	                              /* add the two variables which are fixed to zero within a negated clique */
7584 	                              SCIP_CALL( SCIPaddConflictBinvar(scip, myvars[i]) );
7585 	                              SCIP_CALL( SCIPaddConflictBinvar(scip, myvars[v]) );
7586 	
7587 	                              /* start the conflict analysis */
7588 	                              SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
7589 	                           }
7590 	                           *cutoff = TRUE;
7591 	                           break;
7592 	                        }
7593 	                        assert(tightened);
7594 	                        ++(*nfixedvars);
7595 	                        SCIP_CALL( SCIPresetConsAge(scip, cons) );
7596 	                     }
7597 	                  }
7598 	
7599 	                  /* reset local minweightsum for clique because all fixed to one variables are now counted in consdata->onesweightsum */
7600 	                  localminweightsum = 0;
7601 	                  /* we can jump to the end of this clique */
7602 	                  i = cliqueendposs[c - 1];
7603 	
7604 	                  if( *cutoff )
7605 	                     break;
7606 	               }
7607 	            }
7608 	            ++i;
7609 	         }
7610 	         /* add last clique minweightsum */
7611 	         minweightsum += localminweightsum;
7612 	
7613 	         SCIPdebugMsg(scip, "knapsack constraint <%s> has minimum weight sum of <%" SCIP_LONGINT_FORMAT ">\n",
7614 	            SCIPconsGetName(cons), minweightsum + consdata->onesweightsum );
7615 	
7616 	         /* check, if weights of fixed variables don't exceeds knapsack capacity */
7617 	         if( !(*cutoff) && consdata->capacity >= minweightsum + consdata->onesweightsum )
7618 	         {
7619 	            SCIP_Longint maxcliqueweight = -1LL;
7620 	
7621 	            /* loop over cliques */
7622 	            for( c = 0; c < nnegcliques; ++c )
7623 	            {
7624 	               SCIP_VAR* maxvar;
7625 	               SCIP_Bool maxvarfixed;
7626 	               int endvarposclique;
7627 	               int startvarposclique;
7628 	
7629 	               assert(myvars != NULL);
7630 	               assert(nnegcliques == consdata->nnegcliques);
7631 	               assert(myweights != NULL);
7632 	               assert(secondmaxweights != NULL);
7633 	               assert(cliquestartposs != NULL);
7634 	
7635 	               endvarposclique = cliqueendposs[c];
7636 	               startvarposclique = cliquestartposs[c];
7637 	
7638 	               maxvar = myvars[startvarposclique];
7639 	
7640 	               /* no need to process this negated clique because all variables are already fixed (which we detect from a fixed maxvar) */
7641 	               if( SCIPvarGetUbLocal(maxvar) - SCIPvarGetLbLocal(maxvar) < 0.5 )
7642 	                  continue;
7643 	
7644 	               maxcliqueweight = myweights[startvarposclique];
7645 	               maxvarfixed = FALSE;
7646 	               /* if the sum of all weights of fixed variables to one plus the minimalweightsum (minimal weight which is already
7647 	                * used in this knapsack due to negated cliques) plus any weight minus the second largest weight in this clique
7648 	                * exceeds the capacity the maximum weight variable can be fixed to zero.
7649 	                */
7650 	               if( consdata->onesweightsum + minweightsum  + (maxcliqueweight - secondmaxweights[c]) > consdata->capacity )
7651 	               {
7652 	#ifndef NDEBUG
7653 	                  SCIP_Longint oldonesweightsum = consdata->onesweightsum;
7654 	#endif
7655 	                  assert(maxcliqueweight >= secondmaxweights[c]);
7656 	                  assert(SCIPvarGetLbLocal(maxvar) < 0.5 && SCIPvarGetUbLocal(maxvar) > 0.5);
7657 	
7658 	                  SCIPdebugMsg(scip, " -> fixing variable <%s> to 0\n", SCIPvarGetName(maxvar));
7659 	                  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7660 	                  SCIP_CALL( SCIPinferBinvarCons(scip, maxvar, FALSE, cons, cliquestartposs[c], &infeasible, &tightened) );
7661 	                  assert(consdata->onesweightsum == oldonesweightsum);
7662 	                  assert(!infeasible);
7663 	                  assert(tightened);
7664 	                  (*nfixedvars)++;
7665 	                  maxvarfixed = TRUE;
7666 	               }
7667 	               /* the remaining cliques are singletons such that all subsequent variables have a weight that
7668 	                * fits into the knapsack
7669 	                */
7670 	               else if( nnegcliques - c == nvars - startvarposclique )
7671 	                  break;
7672 	               /* early termination of the remaining loop because no further variable fixings are possible:
7673 	                *
7674 	                * the gain in any of the following negated cliques (the additional term if the maximum weight variable was set to 1, and the second
7675 	                * largest was set to 0) does not suffice to infer additional variable fixings because
7676 	                *
7677 	                * - the cliques are sorted by decreasing maximum weight -> for all c' >= c: maxweights[c'] <= maxcliqueweight
7678 	                * - their second largest elements are at least as large as the smallest weight of the knapsack
7679 	                */
7680 	               else if( consdata->onesweightsum + minweightsum + (maxcliqueweight - consdata->weights[nvars - 1]) <= consdata->capacity )
7681 	                  break;
7682 	
7683 	               /* loop over items with non-maximal weight (omitting the first position) */
7684 	               for( i = endvarposclique; i > startvarposclique; --i )
7685 	               {
7686 	                  /* there should be no variable fixed to 0 between startvarposclique + 1 and endvarposclique unless we
7687 	                   * messed up the clique preprocessing in the previous loop to filter those variables out */
7688 	                  assert(SCIPvarGetUbLocal(myvars[i]) > 0.5);
7689 	
7690 	                  /* only check variables of negated cliques for which no variable is locally fixed */
7691 	                  if( SCIPvarGetLbLocal(myvars[i]) < 0.5 )
7692 	                  {
7693 	                     assert(maxcliqueweight >= myweights[i]);
7694 	                     assert(i == endvarposclique || myweights[i] >= myweights[i+1]);
7695 	
7696 	                     /* we fix the members of this clique with non-maximal weight in two cases to 1:
7697 	                      *
7698 	                      * the maxvar was already fixed to 0 because it has a huge gain.
7699 	                      *
7700 	                      * if for i \in C (a negated clique) onesweightsum - wi + W_max(c) > capacity  => xi = 1
7701 	                      * since replacing i with the element of maximal weight leads to infeasibility */
7702 	                     if( maxvarfixed || consdata->onesweightsum + minweightsum - myweights[i] + maxcliqueweight > consdata->capacity  )
7703 	                     {
7704 	#ifndef NDEBUG
7705 	                        SCIP_Longint oldonesweightsum = consdata->onesweightsum;
7706 	#endif
7707 	                        SCIPdebugMsg(scip, " -> fixing variable <%s> to 1, due to negated clique information\n", SCIPvarGetName(myvars[i]));
7708 	                        SCIP_CALL( SCIPinferBinvarCons(scip, myvars[i], TRUE, cons, -i, &infeasible, &tightened) );
7709 	                        assert(consdata->onesweightsum == oldonesweightsum + myweights[i]);
7710 	                        assert(!infeasible);
7711 	                        assert(tightened);
7712 	                        ++(*nfixedvars);
7713 	                        SCIP_CALL( SCIPresetConsAge(scip, cons) );
7714 	
7715 	                        /* update minweightsum because now the variable is fixed to one and its weight is counted by
7716 	                         * consdata->onesweightsum
7717 	                         */
7718 	                        minweightsum -= myweights[i];
7719 	                        assert(minweightsum >= 0);
7720 	                     }
7721 	                     else
7722 	                        break;
7723 	                  }
7724 	               }
7725 	#ifndef NDEBUG
7726 	               /* in debug mode, we assert that we did not miss possible fixings by the break above */
7727 	               for( ; i > startvarposclique; --i )
7728 	               {
7729 	                  SCIP_Bool varisfixed = SCIPvarGetUbLocal(myvars[i]) - SCIPvarGetLbLocal(myvars[i]) < 0.5;
7730 	                  SCIP_Bool exceedscapacity = consdata->onesweightsum + minweightsum - myweights[i] + maxcliqueweight > consdata->capacity;
7731 	
7732 	                  assert(i == endvarposclique || myweights[i] >= myweights[i+1]);
7733 	                  assert(varisfixed || !exceedscapacity);
7734 	               }
7735 	#endif
7736 	            }
7737 	         }
7738 	         SCIPfreeBufferArray(scip, &secondmaxweights);
7739 	         SCIPfreeBufferArray(scip, &cliqueendposs);
7740 	         SCIPfreeBufferArray(scip, &cliquestartposs);
7741 	         SCIPfreeBufferArray(scip, &myweights);
7742 	         SCIPfreeBufferArray(scip, &myvars);
7743 	      }
7744 	
7745 	      assert(consdata->negcliquepartitioned || minweightsum == 0);
7746 	   }
7747 	   while( FALSE );
7748 	
7749 	   assert(usenegatedclique || minweightsum == 0);
7750 	   /* check, if weights of fixed variables already exceed knapsack capacity */
7751 	   if( consdata->capacity < minweightsum + consdata->onesweightsum )
7752 	   {
7753 	      SCIPdebugMsg(scip, " -> cutoff - fixed weight: %" SCIP_LONGINT_FORMAT ", capacity: %" SCIP_LONGINT_FORMAT " \n",
7754 	         consdata->onesweightsum, consdata->capacity);
7755 	
7756 	      SCIP_CALL( SCIPresetConsAge(scip, cons) );
7757 	      *cutoff = TRUE;
7758 	
7759 	      /* analyze the cutoff in SOLVING stage and if conflict analysis is turned on */
7760 	      if( (SCIPgetStage(scip) == SCIP_STAGE_SOLVING || SCIPinProbing(scip)) && SCIPisConflictAnalysisApplicable(scip) )
7761 	      {
7762 	         /* start conflict analysis with the fixed-to-one variables, add only as many as needed to exceed the capacity */
7763 	         SCIP_Longint weight;
7764 	
7765 	         weight = 0;
7766 	
7767 	         SCIP_CALL( SCIPinitConflictAnalysis(scip, SCIP_CONFTYPE_PROPAGATION, FALSE) );
7768 	
7769 	         for( i = 0; i < nvars && weight <= consdata->capacity; i++ )
7770 	         {
7771 	            if( SCIPvarGetLbLocal(consdata->vars[i]) > 0.5)
7772 	            {
7773 	               SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[i]) );
7774 	               weight += consdata->weights[i];
7775 	            }
7776 	         }
7777 	
7778 	         SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
7779 	      }
7780 	
7781 	      return SCIP_OKAY;
7782 	   }
7783 	
7784 	   /* the algorithm below is a special case of propagation involving negated cliques */
7785 	   if( !usenegatedclique )
7786 	   {
7787 	      assert(consdata->sorted);
7788 	      residualcapacity = consdata->capacity - consdata->onesweightsum;
7789 	
7790 	      /* fix all variables to zero, that don't fit into the knapsack anymore */
7791 	      for( i = 0; i < nvars && consdata->weights[i] > residualcapacity; ++i )
7792 	      {
7793 	         /* if all weights of fixed variables to one plus any weight exceeds the capacity the variables have to be fixed
7794 	          * to zero
7795 	          */
7796 	         if( SCIPvarGetLbLocal(consdata->vars[i]) < 0.5 )
7797 	         {
7798 	            if( SCIPvarGetUbLocal(consdata->vars[i]) > 0.5 )
7799 	            {
7800 	               assert(consdata->onesweightsum + consdata->weights[i] > consdata->capacity);
7801 	               SCIPdebugMsg(scip, " -> fixing variable <%s> to 0\n", SCIPvarGetName(consdata->vars[i]));
7802 	               SCIP_CALL( SCIPresetConsAge(scip, cons) );
7803 	               SCIP_CALL( SCIPinferBinvarCons(scip, consdata->vars[i], FALSE, cons, i, &infeasible, &tightened) );
7804 	               assert(!infeasible);
7805 	               assert(tightened);
7806 	               (*nfixedvars)++;
7807 	            }
7808 	         }
7809 	      }
7810 	   }
7811 	
7812 	   /* check if the knapsack is now redundant */
7813 	   if( !SCIPconsIsModifiable(cons) )
7814 	   {
7815 	      SCIP_Longint unfixedweightsum = consdata->onesweightsum;
7816 	
7817 	      /* sum up the weights of all unfixed variables, plus the weight sum of all variables fixed to one already */
7818 	      for( i = 0; i < nvars; ++i )
7819 	      {
7820 	         if( SCIPvarGetLbLocal(consdata->vars[i]) + 0.5 < SCIPvarGetUbLocal(consdata->vars[i]) )
7821 	         {
7822 	            unfixedweightsum += consdata->weights[i];
7823 	
7824 	            /* the weight sum is larger than the capacity, so the constraint is not redundant */
7825 	            if( unfixedweightsum > consdata->capacity )
7826 	               return SCIP_OKAY;
7827 	         }
7828 	      }
7829 	      /* we summed up all (unfixed and fixed to one) weights and did not exceed the capacity, so the constraint is redundant */
7830 	      SCIPdebugMsg(scip, " -> knapsack constraint <%s> is redundant: weightsum=%" SCIP_LONGINT_FORMAT ", unfixedweightsum=%" SCIP_LONGINT_FORMAT ", capacity=%" SCIP_LONGINT_FORMAT "\n",
7831 	         SCIPconsGetName(cons), consdata->weightsum, unfixedweightsum, consdata->capacity);
7832 	      SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7833 	      *redundant = TRUE;
7834 	   }
7835 	
7836 	   return SCIP_OKAY;
7837 	}
7838 	
7839 	/** all but one variable fit into the knapsack constraint, so we can upgrade this constraint to an logicor constraint
7840 	 *  containing all negated variables of this knapsack constraint
7841 	 */
7842 	static
7843 	SCIP_RETCODE upgradeCons(
7844 	   SCIP*                 scip,               /**< SCIP data structure */
7845 	   SCIP_CONS*            cons,               /**< knapsack constraint */
7846 	   int*                  ndelconss,          /**< pointer to store the amount of deleted constraints */
7847 	   int*                  naddconss           /**< pointer to count number of added constraints */
7848 	   )
7849 	{
7850 	   SCIP_CONS* newcons;
7851 	   SCIP_CONSDATA* consdata;
7852 	
7853 	   assert(scip != NULL);
7854 	   assert(cons != NULL);
7855 	   assert(ndelconss != NULL);
7856 	   assert(naddconss != NULL);
7857 	
7858 	   consdata = SCIPconsGetData(cons);
7859 	   assert(consdata != NULL);
7860 	   assert(consdata->nvars > 1);
7861 	
7862 	   /* if the knapsack constraint consists only of two variables, we can upgrade it to a set-packing constraint */
7863 	   if( consdata->nvars == 2 )
7864 	   {
7865 	      SCIPdebugMsg(scip, "upgrading knapsack constraint <%s> to a set-packing constraint", SCIPconsGetName(cons));
7866 	
7867 	      SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), consdata->nvars, consdata->vars,
7868 	            SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
7869 	            SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
7870 	            SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons),
7871 	            SCIPconsIsStickingAtNode(cons)) );
7872 	   }
7873 	   /* if the knapsack constraint consists of at least three variables, we can upgrade it to a logicor constraint
7874 	    * containing all negated variables of the knapsack
7875 	    */
7876 	   else
7877 	   {
7878 	      SCIP_VAR** consvars;
7879 	
7880 	      SCIPdebugMsg(scip, "upgrading knapsack constraint <%s> to a logicor constraint", SCIPconsGetName(cons));
7881 	
7882 	      SCIP_CALL( SCIPallocBufferArray(scip, &consvars, consdata->nvars) );
7883 	      SCIP_CALL( SCIPgetNegatedVars(scip, consdata->nvars, consdata->vars, consvars) );
7884 	
7885 	      SCIP_CALL( SCIPcreateConsLogicor(scip, &newcons, SCIPconsGetName(cons), consdata->nvars, consvars,
7886 	            SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
7887 	            SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
7888 	            SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons),
7889 	            SCIPconsIsStickingAtNode(cons)) );
7890 	
7891 	      SCIPfreeBufferArray(scip, &consvars);
7892 	   }
7893 	
7894 	   SCIP_CALL( SCIPaddCons(scip, newcons) );
7895 	   SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
7896 	   ++(*naddconss);
7897 	
7898 	   SCIP_CALL( SCIPdelCons(scip, cons) );
7899 	   ++(*ndelconss);
7900 	
7901 	   return SCIP_OKAY;
7902 	}
7903 	
7904 	/** delete redundant variables
7905 	 *
7906 	 * i.e. 5x1 + 5x2 + 5x3 + 2x4 + 1x5 <= 13   =>   x4, x5 always fits into the knapsack, so we can delete them
7907 	 *
7908 	 * i.e. 5x1 + 5x2 + 5x3 + 2x4 + 1x5 <= 8 and we have the cliqueinformation (x1,x2,x3) is a clique
7909 	 *      =>   x4, x5 always fits into the knapsack, so we can delete them
7910 	 *
7911 	 * i.e. 5x1 + 5x2 + 5x3 + 1x4 + 1x5 <= 6 and we have the cliqueinformation (x1,x2,x3) is a clique and (x4,x5) too
7912 	 *      =>   we create the set partitioning constraint x4 + x5 <= 1 and delete them in this knapsack
7913 	 */
7914 	static
7915 	SCIP_RETCODE deleteRedundantVars(
7916 	   SCIP*                 scip,               /**< SCIP data structure */
7917 	   SCIP_CONS*            cons,               /**< knapsack constraint */
7918 	   SCIP_Longint          frontsum,           /**< sum of front items which fit if we try to take from the first till the last */
7919 	   int                   splitpos,           /**< split position till when all front items are fitting, splitpos is the
7920 	                                              *   first which did not fit */
7921 	   int*                  nchgcoefs,          /**< pointer to store the amount of changed coefficients */
7922 	   int*                  nchgsides,          /**< pointer to store the amount of changed sides */
7923 	   int*                  naddconss           /**< pointer to count number of added constraints */
7924 	   )
7925 	{
7926 	   SCIP_CONSHDLRDATA* conshdlrdata;
7927 	   SCIP_CONSDATA* consdata;
7928 	   SCIP_VAR** vars;
7929 	   SCIP_Longint* weights;
7930 	   SCIP_Longint capacity;
7931 	   SCIP_Longint gcd;
7932 	   int nvars;
7933 	   int w;
7934 	
7935 	   assert(scip != NULL);
7936 	   assert(cons != NULL);
7937 	   assert(nchgcoefs != NULL);
7938 	   assert(nchgsides != NULL);
7939 	   assert(naddconss != NULL);
7940 	
7941 	   consdata = SCIPconsGetData(cons);
7942 	   assert(consdata != NULL);
7943 	   assert(0 < frontsum && frontsum < consdata->weightsum);
7944 	   assert(0 < splitpos && splitpos < consdata->nvars);
7945 	
7946 	   conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
7947 	   assert(conshdlrdata != NULL);
7948 	
7949 	   vars = consdata->vars;
7950 	   weights = consdata->weights;
7951 	   nvars = consdata->nvars;
7952 	   capacity = consdata->capacity;
7953 	
7954 	   /* weight should still be sorted, because the reduction preserves this, but corresponding variables with equal
7955 	    * weight must not be sorted by their index
7956 	    */
7957 	#ifndef NDEBUG
7958 	   for( w = nvars - 1; w > 0; --w )
7959 	      assert(weights[w] <= weights[w-1]);
7960 	#endif
7961 	
7962 	   /* if there are no variables rear to splitpos, the constraint has no redundant variables */
7963 	   if( consdata->nvars - 1 == splitpos )
7964 	      return SCIP_OKAY;
7965 	
7966 	   assert(frontsum + weights[splitpos] > capacity);
7967 	
7968 	   /* detect redundant variables */
7969 	   if( consdata->weightsum - weights[splitpos] <= capacity )
7970 	   {
7971 	      /* all rear items are redundant, because leaving one item in front and incl. of splitpos out the rear itmes always
7972 	       * fit
7973 	       */
7974 	      SCIPdebugMsg(scip, "Found redundant variables in constraint <%s>.\n", SCIPconsGetName(cons));
7975 	
7976 	      /* delete items and update capacity */
7977 	      for( w = nvars - 1; w > splitpos; --w )
7978 	      {
7979 	         consdata->capacity -= weights[w];
7980 	         SCIP_CALL( delCoefPos(scip, cons, w) );
7981 	      }
7982 	      assert(w == splitpos);
7983 	
7984 	      ++(*nchgsides);
7985 	      *nchgcoefs += (nvars - splitpos);
7986 	
7987 	      /* division by greatest common divisor */
7988 	      gcd = weights[w];
7989 	      for( ; w >= 0 && gcd > 1; --w )
7990 	      {
7991 	         gcd = SCIPcalcGreComDiv(gcd, weights[w]);
7992 	      }
7993 	
7994 	      /* normalize if possible */
7995 	      if( gcd > 1 )
7996 	      {
7997 	         for( w = splitpos; w >= 0; --w )
7998 	         {
7999 	            consdataChgWeight(consdata, w, weights[w]/gcd);
8000 	         }
8001 	         (*nchgcoefs) += nvars;
8002 	
8003 	         consdata->capacity /= gcd;
8004 	         ++(*nchgsides);
8005 	      }
8006 	
8007 	      /* weight should still be sorted, because the reduction preserves this, but corresponding variables with equal
8008 	       * weight must not be sorted by their index
8009 	       */
8010 	#ifndef NDEBUG
8011 	      for( w = consdata->nvars - 1; w > 0; --w )
8012 	         assert(weights[w] <= weights[w - 1]);
8013 	#endif
8014 	   }
8015 	   /* rear items can only be redundant, when the sum is smaller to the weight at splitpos and all rear items would
8016 	    * always fit into the knapsack, therefor the item directly after splitpos needs to be smaller than the one at
8017 	    * splitpos and needs to fit into the knapsack
8018 	    */
8019 	   else if( conshdlrdata->disaggregation && frontsum + weights[splitpos + 1] <= capacity )
8020 	   {
8021 	      int* clqpart;
8022 	      int nclq;
8023 	      int len;
8024 	
8025 	      len = nvars - (splitpos + 1);
8026 	      /* allocate temporary memory */
8027 	      SCIP_CALL( SCIPallocBufferArray(scip, &clqpart, len) );
8028 	
8029 	      /* calculate clique partition */
8030 	      SCIP_CALL( SCIPcalcCliquePartition(scip, &(consdata->vars[splitpos+1]), len, clqpart, &nclq) );
8031 	
8032 	      /* check if we found at least one clique */
8033 	      if( nclq < len )
8034 	      {
8035 	         SCIP_Longint maxactduetoclq;
8036 	         int cliquenum;
8037 	
8038 	         maxactduetoclq = 0;
8039 	         cliquenum = 0;
8040 	
8041 	         /* calculate maximum activity due to cliques */
8042 	         for( w = 0; w < len; ++w )
8043 	         {
8044 	            assert(clqpart[w] >= 0 && clqpart[w] <= w);
8045 	            if( clqpart[w] == cliquenum )
8046 	            {
8047 	               maxactduetoclq += weights[w + splitpos + 1];
8048 	               ++cliquenum;
8049 	            }
8050 	         }
8051 	
8052 	         /* all rear items are redundant due to clique information, if maxactduetoclq is smaller than the weight before,
8053 	          * so delete them and create for all clique the corresponding clique constraints and update the capacity
8054 	          */
8055 	         if( frontsum + maxactduetoclq <= capacity )
8056 	         {
8057 	            SCIP_VAR** clqvars;
8058 	            int nclqvars;
8059 	            int c;
8060 	
8061 	            assert(maxactduetoclq < weights[splitpos]);
8062 	
8063 	            SCIPdebugMsg(scip, "Found redundant variables in constraint <%s> due to clique information.\n", SCIPconsGetName(cons));
8064 	
8065 	            /* allocate temporary memory */
8066 	            SCIP_CALL( SCIPallocBufferArray(scip, &clqvars, len - nclq + 1) );
8067 	
8068 	            for( c = 0; c < nclq; ++c )
8069 	            {
8070 	               nclqvars = 0;
8071 	               for( w = 0; w < len; ++w )
8072 	               {
8073 	                  if( clqpart[w] == c )
8074 	                  {
8075 	                     clqvars[nclqvars] = vars[w + splitpos + 1];
8076 	                     ++nclqvars;
8077 	                  }
8078 	               }
8079 	
8080 	               /* we found a real clique so extract this constraint, because we do not know who this information generated so */
8081 	               if( nclqvars > 1 )
8082 	               {
8083 	                  SCIP_CONS* cliquecons;
8084 	                  char name[SCIP_MAXSTRLEN];
8085 	
8086 	                  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%" SCIP_LONGINT_FORMAT "_%d", SCIPconsGetName(cons), capacity, c);
8087 	                  SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, nclqvars, clqvars,
8088 	                        SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
8089 	                        SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
8090 	                        SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons),
8091 	                        SCIPconsIsStickingAtNode(cons)) );
8092 	                  SCIPdebugMsg(scip, " -> adding clique constraint: ");
8093 	                  SCIPdebugPrintCons(scip, cliquecons, NULL);
8094 	                  SCIP_CALL( SCIPaddCons(scip, cliquecons) );
8095 	                  SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
8096 	                  ++(*naddconss);
8097 	               }
8098 	            }
8099 	
8100 	            /* delete items and update capacity */
8101 	            for( w = nvars - 1; w > splitpos; --w )
8102 	            {
8103 	               SCIP_CALL( delCoefPos(scip, cons, w) );
8104 	               ++(*nchgcoefs);
8105 	            }
8106 	            consdata->capacity -= maxactduetoclq;
8107 	            assert(frontsum <= consdata->capacity);
8108 	            ++(*nchgsides);
8109 	
8110 	            assert(w == splitpos);
8111 	
8112 	            /* renew weights pointer */
8113 	            weights = consdata->weights;
8114 	
8115 	            /* division by greatest common divisor */
8116 	            gcd = weights[w];
8117 	            for( ; w >= 0 && gcd > 1; --w )
8118 	            {
8119 	               gcd = SCIPcalcGreComDiv(gcd, weights[w]);
8120 	            }
8121 	
8122 	            /* normalize if possible */
8123 	            if( gcd > 1 )
8124 	            {
8125 	               for( w = splitpos; w >= 0; --w )
8126 	               {
8127 	                  consdataChgWeight(consdata, w, weights[w]/gcd);
8128 	               }
8129 	               (*nchgcoefs) += nvars;
8130 	
8131 	               consdata->capacity /= gcd;
8132 	               ++(*nchgsides);
8133 	            }
8134 	
8135 	            /* free temporary memory */
8136 	            SCIPfreeBufferArray(scip, &clqvars);
8137 	
8138 	            /* weight should still be sorted, because the reduction preserves this, but corresponding variables with equal
8139 	             * weight must not be sorted by their index
8140 	             */
8141 	#ifndef NDEBUG
8142 	            for( w = consdata->nvars - 1; w > 0; --w )
8143 	               assert(weights[w] <= weights[w - 1]);
8144 	#endif
8145 	         }
8146 	      }
8147 	
8148 	      /* free temporary memory */
8149 	      SCIPfreeBufferArray(scip, &clqpart);
8150 	   }
8151 	
8152 	   return SCIP_OKAY;
8153 	}
8154 	
8155 	/* detect redundant variables which always fits into the knapsack
8156 	 *
8157 	 * i.e. 5x1 + 5x2 + 5x3 + 2x4 + 1x5 <= 13   =>   x4, x5 always fits into the knapsack, so we can delete them
8158 	 *
8159 	 * i.e. 5x1 + 5x2 + 5x3 + 2x4 + 1x5 <= 8 and we have the cliqueinformation (x1,x2,x3) is a clique
8160 	 *      =>   x4, x5 always fits into the knapsack, so we can delete them
8161 	 *
8162 	 * i.e. 5x1 + 5x2 + 5x3 + 1x4 + 1x5 <= 6 and we have the cliqueinformation (x1,x2,x3) is a clique and (x4,x5) too
8163 	 *      =>   we create the set partitioning constraint x4 + x5 <= 1 and delete them in this knapsack
8164 	 */
8165 	static
8166 	SCIP_RETCODE detectRedundantVars(
8167 	   SCIP*                 scip,               /**< SCIP data structure */
8168 	   SCIP_CONS*            cons,               /**< knapsack constraint */
8169 	   int*                  ndelconss,          /**< pointer to store the amount of deleted constraints */
8170 	   int*                  nchgcoefs,          /**< pointer to store the amount of changed coefficients */
8171 	   int*                  nchgsides,          /**< pointer to store the amount of changed sides */
8172 	   int*                  naddconss           /**< pointer to count number of added constraints */
8173 	   )
8174 	{
8175 	   SCIP_CONSHDLRDATA* conshdlrdata;
8176 	   SCIP_CONSDATA* consdata;
8177 	   SCIP_VAR** vars;
8178 	   SCIP_Longint* weights;
8179 	   SCIP_Longint capacity;
8180 	   SCIP_Longint sum;
8181 	   int noldchgcoefs;
8182 	   int nvars;
8183 	   int v;
8184 	   int w;
8185 	
8186 	   assert(scip != NULL);
8187 	   assert(cons != NULL);
8188 	   assert(ndelconss != NULL);
8189 	   assert(nchgcoefs != NULL);
8190 	   assert(nchgsides != NULL);
8191 	   assert(naddconss != NULL);
8192 	
8193 	   consdata = SCIPconsGetData(cons);
8194 	   assert(consdata != NULL);
8195 	   assert(consdata->nvars >= 2);
8196 	   assert(consdata->weightsum > consdata->capacity);
8197 	
8198 	   noldchgcoefs = *nchgcoefs;
8199 	   vars = consdata->vars;
8200 	   weights = consdata->weights;
8201 	   nvars = consdata->nvars;
8202 	   capacity = consdata->capacity;
8203 	   sum = 0;
8204 	
8205 	   /* search for maximal fitting items */
8206 	   for( v = 0; v < nvars && sum + weights[v] <= capacity; ++v )
8207 	      sum += weights[v];
8208 	
8209 	   assert(v < nvars);
8210 	
8211 	   /* all but one variable fit into the knapsack, so we can upgrade this constraint to a logicor */
8212 	   if( v == nvars - 1 )
8213 	   {
8214 	      SCIP_CALL( upgradeCons(scip, cons, ndelconss, naddconss) );
8215 	      assert(SCIPconsIsDeleted(cons));
8216 	
8217 	      return SCIP_OKAY;
8218 	   }
8219 	
8220 	   if( v < nvars - 1 )
8221 	   {
8222 	      /* try to delete variables */
8223 	      SCIP_CALL( deleteRedundantVars(scip, cons, sum, v, nchgcoefs, nchgsides, naddconss) );
8224 	      assert(consdata->nvars > 1);
8225 	
8226 	      /* all but one variable fit into the knapsack, so we can upgrade this constraint to a logicor */
8227 	      if( v == consdata->nvars - 1 )
8228 	      {
8229 	         SCIP_CALL( upgradeCons(scip, cons, ndelconss, naddconss) );
8230 	         assert(SCIPconsIsDeleted(cons));
8231 	      }
8232 	
8233 	      return SCIP_OKAY;
8234 	   }
8235 	
8236 	   /* if we already found some redundant variables, stop here */
8237 	   if( *nchgcoefs > noldchgcoefs )
8238 	      return SCIP_OKAY;
8239 	
8240 	   assert(vars == consdata->vars);
8241 	   assert(weights == consdata->weights);
8242 	   assert(nvars == consdata->nvars);
8243 	   assert(capacity == consdata->capacity);
8244 	
8245 	   conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
8246 	   assert(conshdlrdata != NULL);
8247 	   /* calculate clique partition */
8248 	   SCIP_CALL( calcCliquepartition(scip, conshdlrdata, consdata, TRUE, FALSE) );
8249 	
8250 	   /* check for real existing cliques */
8251 	   if( consdata->cliquepartition[v] < v )
8252 	   {
8253 	      SCIP_Longint sumfront;
8254 	      SCIP_Longint maxactduetoclqfront;
8255 	      int* clqpart;
8256 	      int cliquenum;
8257 	
8258 	      sumfront = 0;
8259 	      maxactduetoclqfront = 0;
8260 	
8261 	      clqpart = consdata->cliquepartition;
8262 	      cliquenum = 0;
8263 	
8264 	      /* calculate maximal activity due to cliques */
8265 	      for( w = 0; w < nvars; ++w )
8266 	      {
8267 	         assert(clqpart[w] >= 0 && clqpart[w] <= w);
8268 	         if( clqpart[w] == cliquenum )
8269 	         {
8270 	            if( maxactduetoclqfront + weights[w] <= capacity )
8271 	            {
8272 	               maxactduetoclqfront += weights[w];
8273 	               ++cliquenum;
8274 	            }
8275 	            else
8276 	               break;
8277 	         }
8278 	         sumfront += weights[w];
8279 	      }
8280 	      assert(w >= v);
8281 	
8282 	      /* if all items fit, then delete the whole constraint but create clique constraints which led to this
8283 	       * information
8284 	       */
8285 	      if( conshdlrdata->disaggregation && w == nvars )
8286 	      {
8287 	         SCIP_VAR** clqvars;
8288 	         int nclqvars;
8289 	         int c;
8290 	         int ncliques;
8291 	
8292 	         assert(maxactduetoclqfront <= capacity);
8293 	
8294 	         SCIPdebugMsg(scip, "Found redundant constraint <%s> due to clique information.\n", SCIPconsGetName(cons));
8295 	
8296 	         ncliques = consdata->ncliques;
8297 	
8298 	         /* allocate temporary memory */
8299 	         SCIP_CALL( SCIPallocBufferArray(scip, &clqvars, nvars - ncliques + 1) );
8300 	
8301 	         for( c = 0; c < ncliques; ++c )
8302 	         {
8303 	            nclqvars = 0;
8304 	            for( w = 0; w < nvars; ++w )
8305 	            {
8306 	               if( clqpart[w] == c )
8307 	               {
8308 	                  clqvars[nclqvars] = vars[w];
8309 	                  ++nclqvars;
8310 	               }
8311 	            }
8312 	
8313 	            /* we found a real clique so extract this constraint, because we do not know who this information generated so */
8314 	            if( nclqvars > 1 )
8315 	            {
8316 	               SCIP_CONS* cliquecons;
8317 	               char name[SCIP_MAXSTRLEN];
8318 	
8319 	               (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%" SCIP_LONGINT_FORMAT "_%d", SCIPconsGetName(cons), capacity, c);
8320 	               SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, nclqvars, clqvars,
8321 	                     SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
8322 	                     SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
8323 	                     SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons),
8324 	                     SCIPconsIsStickingAtNode(cons)) );
8325 	               SCIPdebugMsg(scip, " -> adding clique constraint: ");
8326 	               SCIPdebugPrintCons(scip, cliquecons, NULL);
8327 	               SCIP_CALL( SCIPaddCons(scip, cliquecons) );
8328 	               SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
8329 	               ++(*naddconss);
8330 	            }
8331 	         }
8332 	
8333 	         /* delete old constraint */
8334 	         SCIP_CALL( SCIPdelConsLocal(scip, cons) );
8335 	         ++(*ndelconss);
8336 	
8337 	         SCIPfreeBufferArray(scip, &clqvars);
8338 	
8339 	         return SCIP_OKAY;
8340 	      }
8341 	
8342 	      if( w > v && w < nvars - 1 )
8343 	      {
8344 	         /* try to delete variables */
8345 	         SCIP_CALL( deleteRedundantVars(scip, cons, sumfront, w, nchgcoefs, nchgsides, naddconss) );
8346 	      }
8347 	   }
8348 	
8349 	   return SCIP_OKAY;
8350 	}
8351 	
8352 	/** divides weights by their greatest common divisor and divides capacity by the same value, rounding down the result */
8353 	static
8354 	void normalizeWeights(
8355 	   SCIP_CONS*            cons,               /**< knapsack constraint */
8356 	   int*                  nchgcoefs,          /**< pointer to count total number of changed coefficients */
8357 	   int*                  nchgsides           /**< pointer to count number of side changes */
8358 	   )
8359 	{
8360 	   SCIP_CONSDATA* consdata;
8361 	   SCIP_Longint gcd;
8362 	   int i;
8363 	
8364 	   assert(nchgcoefs != NULL);
8365 	   assert(nchgsides != NULL);
8366 	   assert(!SCIPconsIsModifiable(cons));
8367 	
8368 	   consdata = SCIPconsGetData(cons);
8369 	   assert(consdata != NULL);
8370 	   assert(consdata->row == NULL); /* we are in presolve, so no LP row exists */
8371 	   assert(consdata->onesweightsum == 0); /* all fixed variables should have been removed */
8372 	   assert(consdata->weightsum > consdata->capacity); /* otherwise, the constraint is redundant */
8373 	   assert(consdata->nvars >= 1);
8374 	
8375 	   /* sort items, because we can stop earlier if the smaller weights are evaluated first */
8376 	   sortItems(consdata);
8377 	
8378 	   gcd = consdata->weights[consdata->nvars-1];
8379 	   for( i = consdata->nvars-2; i >= 0 && gcd >= 2; --i )
8380 	   {
8381 	      assert(SCIPvarGetLbLocal(consdata->vars[i]) < 0.5);
8382 	      assert(SCIPvarGetUbLocal(consdata->vars[i]) > 0.5); /* all fixed variables should have been removed */
8383 	
8384 	      gcd = SCIPcalcGreComDiv(gcd, consdata->weights[i]);
8385 	   }
8386 	
8387 	   if( gcd >= 2 )
8388 	   {
8389 	      SCIPdebugMessage("knapsack constraint <%s>: dividing weights by %" SCIP_LONGINT_FORMAT "\n", SCIPconsGetName(cons), gcd);
8390 	
8391 	      for( i = 0; i < consdata->nvars; ++i )
8392 	      {
8393 	         consdataChgWeight(consdata, i, consdata->weights[i]/gcd);
8394 	      }
8395 	      consdata->capacity /= gcd;
8396 	      (*nchgcoefs) += consdata->nvars;
8397 	      (*nchgsides)++;
8398 	
8399 	      /* weight should still be sorted, because the reduction preserves this */
8400 	#ifndef NDEBUG
8401 	      for( i = consdata->nvars - 1; i > 0; --i )
8402 	         assert(consdata->weights[i] <= consdata->weights[i - 1]);
8403 	#endif
8404 	      consdata->sorted = TRUE;
8405 	   }
8406 	}
8407 	
8408 	/** dual weights tightening for knapsack constraints
8409 	 *
8410 	 *  1. a) check if all two pairs exceed the capacity, then we can upgrade this constraint to a set-packing constraint
8411 	 *     b) check if all but the smallest weight fit into the knapsack,  then we can upgrade this constraint to a logicor
8412 	 *        constraint
8413 	 *
8414 	 *  2. check if besides big coefficients, that fit only by itself, for a certain amount of variables all combination of
8415 	 *     these are a minimal cover, then might reduce the weights and the capacity, e.g.
8416 	 *
8417 	 *     +219y1 + 180y2 + 74x1 + 70x2 + 63x3 + 62x4 + 53x5 <= 219  <=>  3y1 + 3y2 + x1 + x2 + x3 + x4 + x5 <= 3
8418 	 *
8419 	 *  3. use the duality between a^Tx <= capacity   <=>   a^T~x >= weightsum - capacity to tighten weights, e.g.
8420 	 *
8421 	 *     11x1 + 10x2 + 7x3 + 7x4 + 5x5 <= 27    <=>   11~x1 + 10~x2 + 7~x3 + 7~x4 + 5~x5 >= 13
8422 	 *
8423 	 *     the above constraint can be changed to       8~x1 + 8~x2 + 6.5~x3 + 6.5~x4 + 5~x5 >= 13
8424 	 *
8425 	 *     16~x1 + 16~x2 + 13~x3 + 13~x4 + 10~x5 >= 26   <=>   16x1 + 16x2 + 13x3 + 13x4 + 10x5 <= 42
8426 	 */
8427 	static
8428 	SCIP_RETCODE dualWeightsTightening(
8429 	   SCIP*                 scip,               /**< SCIP data structure */
8430 	   SCIP_CONS*            cons,               /**< knapsack constraint */
8431 	   int*                  ndelconss,          /**< pointer to store the amount of deleted constraints */
8432 	   int*                  nchgcoefs,          /**< pointer to store the amount of changed coefficients */
8433 	   int*                  nchgsides,          /**< pointer to store the amount of changed sides */
8434 	   int*                  naddconss           /**< pointer to count number of added constraints */
8435 	   )
8436 	{
8437 	   SCIP_CONSDATA* consdata;
8438 	   SCIP_Longint* weights;
8439 	   SCIP_Longint dualcapacity;
8440 	   SCIP_Longint reductionsum;
8441 	   SCIP_Longint capacity;
8442 	   SCIP_Longint exceedsum;
8443 	   int oldnchgcoefs;
8444 	   int nvars;
8445 	   int vbig;
8446 	   int v;
8447 	   int w;
8448 	#ifndef NDEBUG
8449 	   int oldnchgsides;
8450 	#endif
8451 	
8452 	   assert(scip != NULL);
8453 	   assert(cons != NULL);
8454 	   assert(ndelconss != NULL);
8455 	   assert(nchgcoefs != NULL);
8456 	   assert(nchgsides != NULL);
8457 	   assert(naddconss != NULL);
8458 	
8459 	#ifndef NDEBUG
8460 	   oldnchgsides = *nchgsides;
8461 	#endif
8462 	
8463 	   consdata = SCIPconsGetData(cons);
8464 	   assert(consdata != NULL);
8465 	   assert(consdata->weightsum > consdata->capacity);
8466 	   assert(consdata->nvars >= 2);
8467 	   assert(consdata->sorted);
8468 	
8469 	   /* constraint should be merged */
8470 	   assert(consdata->merged);
8471 	
8472 	   nvars = consdata->nvars;
8473 	   weights = consdata->weights;
8474 	   capacity = consdata->capacity;
8475 	
8476 	   oldnchgcoefs = *nchgcoefs;
8477 	
8478 	   /* case 1. */
8479 	   if( weights[nvars - 1] + weights[nvars - 2] > capacity )
8480 	   {
8481 	      SCIP_CONS* newcons;
8482 	
8483 	      /* two variable are enough to exceed the constraint, so we can update it to a set-packing
8484 	       *
8485 	       * e.g. 5x1 + 4x2 + 3x3 <= 5   <=>    x1 + x2 + x3 <= 1
8486 	       */
8487 	      SCIPdebugMsg(scip, "upgrading knapsack constraint <%s> to a set-packing constraint", SCIPconsGetName(cons));
8488 	
8489 	      SCIP_CALL( SCIPcreateConsSetpack(scip, &newcons, SCIPconsGetName(cons), consdata->nvars, consdata->vars,
8490 	            SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
8491 	            SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
8492 	            SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons),
8493 	            SCIPconsIsStickingAtNode(cons)) );
8494 	
8495 	      SCIP_CALL( SCIPaddCons(scip, newcons) );
8496 	      SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
8497 	      ++(*naddconss);
8498 	
8499 	      SCIP_CALL( SCIPdelCons(scip, cons) );
8500 	      ++(*ndelconss);
8501 	
8502 	      return SCIP_OKAY;
8503 	   }
8504 	
8505 	   /* all but one variable fit into the knapsack, so we can upgrade this constraint to a logicor */
8506 	   if( consdata->weightsum - weights[nvars - 1] <= consdata->capacity )
8507 	   {
8508 	      SCIP_CALL( upgradeCons(scip, cons, ndelconss, naddconss) );
8509 	      assert(SCIPconsIsDeleted(cons));
8510 	
8511 	      return SCIP_OKAY;
8512 	   }
8513 	
8514 	   /* early termination, if the pair with biggest coeffcients together does not exceed the dualcapacity */
8515 	   /* @todo might be changed/removed when improving the coeffcients tightening */
8516 	   if( consdata->weightsum - capacity > weights[0] + weights[1] )
8517 	      return SCIP_OKAY;
8518 	
8519 	   /* case 2. */
8520 	
8521 	   v = 0;
8522 	
8523 	   /* @todo generalize the following algorithm for several parts of the knapsack
8524 	    *
8525 	    * the following is done without looking at the dualcapacity; it is enough to check whether for a certain amount of
8526 	    * variables each combination is a minimal cover, some examples
8527 	    *
8528 	    * +74x1 + 70x2 + 63x3 + 62x4 + 53x5 <= 219     <=>    74~x1 + 70~x2 + 63~x3 + 62~x4 + 53~x5 >= 103
8529 	    *                                              <=>      ~x1 +   ~x2 +   ~x3 +   ~x4 +   ~x5 >= 2
8530 	    *                                              <=>       x1 +    x2 +    x3 +    x4 +    x5 <= 3
8531 	    *
8532 	    * +219y1 + 180y_2 +74x1 + 70x2 + 63x3 + 62x4 + 53x5 <= 219  <=>  3y1 + 3y2 + x1 + x2 + x3 + x4 + x5 <= 3
8533 	    *
8534 	    */
8535 	
8536 	   /* determine big weights that fit only by itself */
8537 	   while( v < nvars && weights[v] + weights[nvars - 1] > capacity )
8538 	      ++v;
8539 	
8540 	   vbig = v;
8541 	   assert(vbig < nvars - 1);
8542 	   exceedsum = 0;
8543 	
8544 	   /* determine the amount needed to exceed the capacity */
8545 	   while( v < nvars && exceedsum <= capacity )
8546 	   {
8547 	      exceedsum += weights[v];
8548 	      ++v;
8549 	   }
8550 	
8551 	   /* if we exceeded the capacity we might reduce the weights */
8552 	   if( exceedsum > capacity )
8553 	   {
8554 	      assert(vbig > 0 || v < nvars);
8555 	
8556 	      /* all small weights were needed to exceed the capacity */
8557 	      if( v == nvars )
8558 	      {
8559 	         SCIP_Longint newweight = (SCIP_Longint)nvars - vbig - 1;
8560 	         assert(newweight > 0);
8561 	
8562 	         /* reduce big weights */
8563 	         for( v = 0; v < vbig; ++v )
8564 	         {
8565 	            if( weights[v] > newweight )
8566 	            {
8567 	               consdataChgWeight(consdata, v, newweight);
8568 	               ++(*nchgcoefs);
8569 	            }
8570 	         }
8571 	
8572 	         /* reduce small weights */
8573 	         for( ; v < nvars; ++v )
8574 	         {
8575 	            if( weights[v] > 1 )
8576 	            {
8577 	               consdataChgWeight(consdata, v, 1LL);
8578 	               ++(*nchgcoefs);
8579 	            }
8580 	         }
8581 	
8582 	         consdata->capacity = newweight;
8583 	
8584 	         /* weight should still be sorted, because the reduction preserves this, but corresponding variables with equal
8585 	          * weight must not be sorted by their index
8586 	          */
8587 	#ifndef NDEBUG
8588 	         for( v = nvars - 1; v > 0; --v )
8589 	            assert(weights[v] <= weights[v-1]);
8590 	#endif
8591 	
8592 	         return SCIP_OKAY;
8593 	      }
8594 	      /* a certain amount of small variables exceed the capacity, so check if this holds for all combinations of the
8595 	       * small weights
8596 	       */
8597 	      else
8598 	      {
8599 	         SCIP_Longint exceedsumback = 0;
8600 	         int nexceed = v - vbig;
8601 	
8602 	         assert(nexceed > 1);
8603 	
8604 	         /* determine weightsum of the same amount as before but of the smallest weight */
8605 	         for( w = nvars - 1; w >= nvars - nexceed; --w )
8606 	            exceedsumback += weights[w];
8607 	
8608 	         assert(w >= 0);
8609 	
8610 	         /* if the same amount but with the smallest possible weights also exceed the capacity, it holds for all
8611 	          * combinations of all small weights
8612 	          */
8613 	         if( exceedsumback > capacity )
8614 	         {
8615 	            SCIP_Longint newweight = nexceed - 1;
8616 	
8617 	            /* taking out the smallest element needs to fit */
8618 	            assert(exceedsumback - weights[nvars - 1] <= capacity);
8619 	
8620 	            /* reduce big weights */
8621 	            for( v = 0; v < vbig; ++v )
8622 	            {
8623 	               if( weights[v] > newweight )
8624 	               {
8625 	                  consdataChgWeight(consdata, v, newweight);
8626 	                  ++(*nchgcoefs);
8627 	               }
8628 	            }
8629 	
8630 	            /* reduce small weights */
8631 	            for( ; v < nvars; ++v )
8632 	            {
8633 	               if( weights[v] > 1 )
8634 	               {
8635 	                  consdataChgWeight(consdata, v, 1LL);
8636 	                  ++(*nchgcoefs);
8637 	               }
8638 	            }
8639 	
8640 	            consdata->capacity = newweight;
8641 	
8642 	            /* weight should still be sorted, because the reduction preserves this, but corresponding variables with equal
8643 	             * weight must not be sorted by their index
8644 	             */
8645 	#ifndef NDEBUG
8646 	            for( v = nvars - 1; v > 0; --v )
8647 	               assert(weights[v] <= weights[v-1]);
8648 	#endif
8649 	            return SCIP_OKAY;
8650 	         }
8651 	      }
8652 	   }
8653 	   else
8654 	   {
8655 	      /* if the following assert fails we have either a redundant constraint or a set-packing constraint, this should
8656 	       * not happen here
8657 	       */
8658 	      assert(vbig > 0 && vbig < nvars);
8659 	
8660 	      /* either choose a big coefficients or all other variables
8661 	       *
8662 	       * 973x1 + 189x2 + 189x3 + 145x4 + 110x5 + 104x6 + 93x7 + 71x8 + 68x9 + 10x10 <= 979
8663 	       *
8664 	       * either choose x1, or all other variables (weightsum of x2 to x10 is 979 above), so we can tighten this
8665 	       * constraint to
8666 	       *
8667 	       * 9x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 <= 9
8668 	       */
8669 	
8670 	      if( weights[vbig - 1] > (SCIP_Longint)nvars - vbig || weights[vbig] > 1 )
8671 	      {
8672 	         SCIP_Longint newweight = (SCIP_Longint)nvars - vbig;
8673 	#ifndef NDEBUG
8674 	         SCIP_Longint resweightsum = consdata->weightsum;
8675 	
8676 	         for( v = 0; v < vbig; ++v )
8677 	            resweightsum -= weights[v];
8678 	
8679 	         assert(exceedsum == resweightsum);
8680 	#endif
8681 	         assert(newweight > 0);
8682 	
8683 	         /* reduce big weights */
8684 	         for( v = 0; v < vbig; ++v )
8685 	         {
8686 	            if( weights[v] > newweight )
8687 	            {
8688 	               consdataChgWeight(consdata, v, newweight);
8689 	               ++(*nchgcoefs);
8690 	            }
8691 	         }
8692 	
8693 	         /* reduce small weights */
8694 	         for( ; v < nvars; ++v )
8695 	         {
8696 	            if( weights[v] > 1 )
8697 	            {
8698 	               consdataChgWeight(consdata, v, 1LL);
8699 	               ++(*nchgcoefs);
8700 	            }
8701 	         }
8702 	
8703 	         consdata->capacity = newweight;
8704 	
8705 	         /* weight should still be sorted, because the reduction preserves this, but corresponding variables with equal
8706 	          * weight must not be sorted by their index
8707 	          */
8708 	#ifndef NDEBUG
8709 	         for( v = nvars - 1; v > 0; --v )
8710 	            assert(weights[v] <= weights[v-1]);
8711 	#endif
8712 	         return SCIP_OKAY;
8713 	      }
8714 	   }
8715 	
8716 	   /* case 3. */
8717 	
8718 	   dualcapacity = consdata->weightsum - capacity;
8719 	   reductionsum = 0;
8720 	   v = 0;
8721 	
8722 	   /* reduce big weights
8723 	    *
8724 	    * e.g. 11x0 + 11x1 + 10x2 + 10x3 <= 32   <=>    11~x0 + 11~x1 + 10~x2 + 10~x3 >= 10
8725 	    *                                        <=>    10~x0 + 10~x1 + 10~x2 + 10~x3 >= 10
8726 	    *                                        <=>       x0 +    x1 +    x2 +    x3 <= 3
8727 	    */
8728 	   while( weights[v] > dualcapacity )
8729 	   {
8730 	      reductionsum += (weights[v] - dualcapacity);
8731 	      consdataChgWeight(consdata, v, dualcapacity);
8732 	      ++v;
8733 	      assert(v < nvars);
8734 	   }
8735 	   (*nchgcoefs) += v;
8736 	
8737 	   /* skip weights equal to the dualcapacity, because we cannot change them  */
8738 	   while( v < nvars && weights[v] == dualcapacity )
8739 	      ++v;
8740 	
8741 	   /* any negated variable out of the first n - 1 items is enough to fulfill the constraint, so we can update it to a logicor
8742 	    * after a possible removal of the last, redundant item
8743 	    *
8744 	    * e.g. 10x1 + 10x2 + 10x3 <= 20   <=>    10~x1 + 10~x2 + 10~x3 >= 10  <=>   ~x1 + ~x2 + ~x3 >= 1
8745 	    */
8746 	   if( v >= nvars - 1 )
8747 	   {
8748 	      /* the last weight is not enough to satisfy the dual capacity -> remove this redundant item */
8749 	      if( v == nvars - 1 )
8750 	      {
8751 	         SCIP_CALL( delCoefPos(scip, cons, nvars - 1) );
8752 	      }
8753 	      SCIP_CALL( upgradeCons(scip, cons, ndelconss, naddconss) );
8754 	      assert(SCIPconsIsDeleted(cons));
8755 	
8756 	      return SCIP_OKAY;
8757 	   }
8758 	   else /* v < nvars - 1 <=> at least two items with weight smaller than the dual capacity */
8759 	   {
8760 	      /* @todo generalize the following algorithm for more than two variables */
8761 	
8762 	      if( weights[nvars - 1] + weights[nvars - 2] >= dualcapacity )
8763 	      {
8764 	         /* we have a dual-knapsack constraint where we either need to choose one variable out of a subset (big
8765 	          * coefficients) of all or two variables of the rest
8766 	          *
8767 	          * e.g. 9x1 + 9x2 + 6x3 + 4x4 <= 19   <=>    9~x1 + 9~x2 + 6~x3 + 4~x4 >= 9
8768 	          *                                    <=>    2~x1 + 2~x2 +  ~x3 +  ~x4 >= 2
8769 	          *                                    <=>    2x1  +  2x2 +   x3 +   x4 <= 4
8770 	          *
8771 	          *      3x1 + 3x2 + 2x3 + 2x4 + 2x5 + 2x6 + x7 <= 12   <=>   3~x1 + 3~x2 + 2~x3 + 2~x4 + 2~x5 + 2~x6 + ~x7 >= 3
8772 	          *                                                     <=>   2~x1 + 2~x2 +  ~x3 +  ~x4 +  ~x5 +  ~x6 + ~x7 >= 2
8773 	          *                                                     <=>   2 x1 + 2 x2 +   x3 +   x4 +   x5 +   x6 +  x7 <= 7
8774 	          *
8775 	          */
8776 	         if( v > 0 && weights[nvars - 2] > 1 )
8777 	         {
8778 	            int ncoefchg = 0;
8779 	
8780 	            /* reduce all bigger weights */
8781 	            for( w = 0; w < v; ++w )
8782 	            {
8783 	               if( weights[w] > 2 )
8784 	               {
8785 	                  consdataChgWeight(consdata, w, 2LL);
8786 	                  ++ncoefchg;
8787 	               }
8788 	               else
8789 	               {
8790 	                  assert(weights[0] == 2);
8791 	                  assert(weights[v - 1] == 2);
8792 	                  break;
8793 	               }
8794 	            }
8795 	
8796 	            /* reduce all smaller weights */
8797 	            for( w = v; w < nvars; ++w )
8798 	            {
8799 	               if( weights[w] > 1 )
8800 	               {
8801 	                  consdataChgWeight(consdata, w, 1LL);
8802 	                  ++ncoefchg;
8803 	               }
8804 	            }
8805 	            assert(ncoefchg > 0);
8806 	
8807 	            (*nchgcoefs) += ncoefchg;
8808 	
8809 	            /* correct the capacity */
8810 	            consdata->capacity = (-2 + v * 2 + nvars - v); /*lint !e647*/
8811 	            assert(consdata->capacity > 0);
8812 	            assert(weights[0] <= consdata->capacity);
8813 	            assert(consdata->weightsum > consdata->capacity);
8814 	            /* reset the reductionsum */
8815 	            reductionsum = 0;
8816 	         }
8817 	         else if( v == 0 )
8818 	         {
8819 	            assert(weights[nvars - 2] == 1);
8820 	         }
8821 	      }
8822 	      else
8823 	      {
8824 	         SCIP_Longint minweight = weights[nvars - 1];
8825 	         SCIP_Longint newweight = dualcapacity - minweight;
8826 	         SCIP_Longint restsumweights = 0;
8827 	         SCIP_Longint sumcoef;
8828 	         SCIP_Bool sumcoefcase = FALSE;
8829 	         int startv = v;
8830 	         int end;
8831 	         int k;
8832 	
8833 	         assert(weights[nvars - 1] + weights[nvars - 2] <= capacity);
8834 	
8835 	         /* reduce big weights of pairs that exceed the dualcapacity
8836 	          *
8837 	          * e.g. 9x1 + 9x2 + 6x3 + 4x4 + 4x5 + 4x6 <= 27   <=>    9~x1 + 9~x2 + 6~x3 + 4~x4 + 4~x5 + 4~x6 >= 9
8838 	          *                                                <=>    9~x1 + 9~x2 + 5~x3 + 4~x4 + 4~x5 + 4~x6 >= 9
8839 	          *                                                <=>    9x1  + 9x2  + 5x3  + 4x4  + 4x5  + 4x6  <= 27
8840 	          */
8841 	         while( weights[v] > newweight )
8842 	         {
8843 	            reductionsum += (weights[v] - newweight);
8844 	            consdataChgWeight(consdata, v, newweight);
8845 	            ++v;
8846 	            assert(v < nvars);
8847 	         }
8848 	         (*nchgcoefs) += (v - startv);
8849 	
8850 	         /* skip equal weights */
8851 	         while( weights[v] == newweight )
8852 	            ++v;
8853 	
8854 	         if( v > 0 )
8855 	         {
8856 	            for( w = v; w < nvars; ++w )
8857 	               restsumweights += weights[w];
8858 	         }
8859 	         else
8860 	            restsumweights = consdata->weightsum;
8861 	
8862 	         if( restsumweights < dualcapacity )
8863 	         {
8864 	            /* we found redundant variables, which does not influence the feasibility of any integral solution, e.g.
8865 	             *
8866 	             * +61x1  + 61x2  + 61x3  + 61x4  + 61x5  + 61x6  + 35x7  + 10x8 <= 350  <=>
8867 	             * +61~x1 + 61~x2 + 61~x3 + 61~x4 + 61~x5 + 61~x6 + 35~x7 + 10~x8 >= 61
8868 	             */
8869 	            if( startv == v )
8870 	            {
8871 	               /* remove redundant variables */
8872 	               for( w = nvars - 1; w >= v; --w )
8873 	               {
8874 	                  SCIP_CALL( delCoefPos(scip, cons, v) );
8875 	                  ++(*nchgcoefs);
8876 	               }
8877 	
8878 	#ifndef NDEBUG
8879 	               /* each coefficients should exceed the dualcapacity by itself */
8880 	               for( ; w >= 0; --w )
8881 	                  assert(weights[w] == dualcapacity);
8882 	#endif
8883 	               /* for performance reasons we do not update the capacity(, i.e. reduce it by reductionsum) and directly
8884 	                * upgrade this constraint
8885 	                */
8886 	               SCIP_CALL( upgradeCons(scip, cons, ndelconss, naddconss) );
8887 	               assert(SCIPconsIsDeleted(cons));
8888 	
8889 	               return SCIP_OKAY;
8890 	            }
8891 	
8892 	            /* special case where we have three different coefficient types
8893 	             *
8894 	             * e.g. 9x1 + 9x2 + 6x3 + 6x4 + 4x5 + 4x6 <= 29   <=>    9~x1 + 9~x2 + 6~x3 + 6~x4 + 4~x5 + 4~x6 >= 9
8895 	             *                                                <=>    9~x1 + 9~x2 + 5~x3 + 5~x4 + 4~x5 + 4~x6 >= 9
8896 	             *                                                <=>    3~x1 + 3~x2 + 2~x3 + 2~x4 +  ~x5 +  ~x6 >= 3
8897 	             *                                                <=>    3x1  + 3x2  + 2x3  + 2x4  +   x5 +   x6 <= 9
8898 	             */
8899 	            if( weights[v] > 1 || (weights[startv] > (SCIP_Longint)nvars - v) || (startv > 0 && weights[0] == (SCIP_Longint)nvars - v + 1) )
8900 	            {
8901 	               SCIP_Longint newcap;
8902 	
8903 	               /* adjust smallest coefficients, which all together do not exceed the dualcapacity */
8904 	               for( w = nvars - 1; w >= v; --w )
8905 	               {
8906 	                  if( weights[w] > 1 )
8907 	                  {
8908 	                     consdataChgWeight(consdata, w, 1LL);
8909 	                     ++(*nchgcoefs);
8910 	                  }
8911 	               }
8912 	
8913 	               /* adjust middle sized coefficients, which when choosing also one small coefficients exceed the
8914 	                * dualcapacity
8915 	                */
8916 	               newweight = (SCIP_Longint)nvars - v;
8917 	               assert(newweight > 1);
8918 	               for( ; w >= startv; --w )
8919 	               {
8920 	                  if( weights[w] > newweight )
8921 	                  {
8922 	                     consdataChgWeight(consdata, w, newweight);
8923 	                     ++(*nchgcoefs);
8924 	                  }
8925 	                  else
8926 	                     assert(weights[w] == newweight);
8927 	               }
8928 	
8929 	               /* adjust big sized coefficients, where each of them exceeds the dualcapacity by itself */
8930 	               ++newweight;
8931 	               assert(newweight > 2);
8932 	               for( ; w >= 0; --w )
8933 	               {
8934 	                  if( weights[w] > newweight )
8935 	                  {
8936 	                     consdataChgWeight(consdata, w, newweight);
8937 	                     ++(*nchgcoefs);
8938 	                  }
8939 	                  else
8940 	                     assert(weights[w] == newweight);
8941 	               }
8942 	
8943 	               /* update the capacity */
8944 	               newcap = ((SCIP_Longint)startv - 1) * newweight + ((SCIP_Longint)v - startv) * (newweight - 1)  + ((SCIP_Longint)nvars - v);
8945 	               if( consdata->capacity > newcap )
8946 	               {
8947 	                  consdata->capacity = newcap;
8948 	                  ++(*nchgsides);
8949 	               }
8950 	               else
8951 	                  assert(consdata->capacity == newcap);
8952 	            }
8953 	            assert(weights[v] == 1 && (weights[startv] == (SCIP_Longint)nvars - v) && (startv == 0 || weights[0] == (SCIP_Longint)nvars - v + 1));
8954 	
8955 	            /* the new dualcapacity should still be equal to the (nvars - v + 1) */
8956 	            assert(consdata->weightsum - consdata->capacity == (SCIP_Longint)nvars - v + 1);
8957 	
8958 	            /* weight should still be sorted, because the reduction preserves this, but corresponding variables with equal
8959 	             * weight must not be sorted by their index
8960 	             */
8961 	#ifndef NDEBUG
8962 	            for( w = nvars - 1; w > 0; --w )
8963 	               assert(weights[w] <= weights[w - 1]);
8964 	#endif
8965 	            return SCIP_OKAY;
8966 	         }
8967 	
8968 	         /* check if all rear items have the same weight as the last one, so we cannot tighten the constraint further */
8969 	         end = nvars - 2;
8970 	         while( end >= 0 && weights[end] == weights[end + 1] )
8971 	         {
8972 	            assert(end >= v);
8973 	            --end;
8974 	         }
8975 	
8976 	         if( v >= end )
8977 	            goto TERMINATE;
8978 	
8979 	         end = nvars - 2;
8980 	
8981 	         /* can we stop early, another special reduction case might exist */
8982 	         if( 2 * weights[end] > dualcapacity )
8983 	         {
8984 	            restsumweights = 0;
8985 	
8986 	            /* determine capacity of the small items */
8987 	            for( w = end + 1; w < nvars; ++w )
8988 	               restsumweights += weights[w];
8989 	
8990 	            if( restsumweights * 2 <= dualcapacity )
8991 	            {
8992 	               /* check for further posssible reductions in the middle */
8993 	               while( v < end && restsumweights + weights[v] >= dualcapacity )
8994 	                  ++v;
8995 	
8996 	               if( v >= end )
8997 	                  goto TERMINATE;
8998 	
8999 	               /* dualcapacity is even, we can set the middle weights to dualcapacity/2 */
9000 	               if( (dualcapacity & 1) == 0 )
9001 	               {
9002 	                  newweight = dualcapacity / 2;
9003 	
9004 	                  /* set all middle coefficients */
9005 	                  for( ; v <= end; ++v )
9006 	                  {
9007 	                     if( weights[v] > newweight )
9008 	                     {
9009 	                        reductionsum += (weights[v] - newweight);
9010 	                        consdataChgWeight(consdata, v, newweight);
9011 	                        ++(*nchgcoefs);
9012 	                     }
9013 	                  }
9014 	               }
9015 	               /* dualcapacity is odd, we can set the middle weights to dualcapacity but therefor need to multiply all
9016 	                * other coefficients by 2
9017 	                */
9018 	               else
9019 	               {
9020 	                  /* correct the reductionsum */
9021 	                  reductionsum *= 2;
9022 	
9023 	                  /* multiply big coefficients by 2 */
9024 	                  for( w = 0; w < v; ++w )
9025 	                  {
9026 	                     consdataChgWeight(consdata, w, weights[w] * 2);
9027 	                  }
9028 	
9029 	                  newweight = dualcapacity;
9030 	                  /* set all middle coefficients */
9031 	                  for( ; v <= end; ++v )
9032 	                  {
9033 	                     reductionsum += (2 * weights[v] - newweight);
9034 	                     consdataChgWeight(consdata, v, newweight);
9035 	                  }
9036 	
9037 	                  /* multiply small coefficients by 2 */
9038 	                  for( w = end + 1; w < nvars; ++w )
9039 	                  {
9040 	                     consdataChgWeight(consdata, w, weights[w] * 2);
9041 	                  }
9042 	                  (*nchgcoefs) += nvars;
9043 	
9044 	                  dualcapacity *= 2;
9045 	                  consdata->capacity *= 2;
9046 	                  ++(*nchgsides);
9047 	               }
9048 	            }
9049 	
9050 	            goto TERMINATE;
9051 	         }
9052 	
9053 	         /* further reductions using the next possible coefficient sum
9054 	          *
9055 	          * e.g. 9x1 + 8x2 + 7x3 + 3x4 + x5 <= 19   <=>    9~x1 + 8~x2 + 7~x3 + 3~x4 + ~x5 >= 9
9056 	          *                                         <=>    9~x1 + 8~x2 + 6~x3 + 3~x4 + ~x5 >= 9
9057 	          *                                         <=>    9x1  + 8x2  + 6x3  + 3x4  + x5  <= 18
9058 	          */
9059 	         /* @todo loop for "k" can be extended, same coefficient when determine next sumcoef can be left out */
9060 	         for( k = 0; k < 4; ++k )
9061 	         {
9062 	            /* determine next minimal coefficient sum */
9063 	            switch( k )
9064 	            {
9065 	            case 0:
9066 	               sumcoef = weights[nvars - 1] + weights[nvars - 2];
9067 	               break;
9068 	            case 1:
9069 	               assert(nvars >= 3);
9070 	               sumcoef = weights[nvars - 1] + weights[nvars - 3];
9071 	               break;
9072 	            case 2:
9073 	               assert(nvars >= 4);
9074 	               if( weights[nvars - 1] + weights[nvars - 4] < weights[nvars - 2] + weights[nvars - 3] )
9075 	               {
9076 	                  sumcoefcase = TRUE;
9077 	                  sumcoef = weights[nvars - 1] + weights[nvars - 4];
9078 	               }
9079 	               else
9080 	               {
9081 	                  sumcoefcase = FALSE;
9082 	                  sumcoef = weights[nvars - 2] + weights[nvars - 3];
9083 	               }
9084 	               break;
9085 	            case 3:
9086 	               assert(nvars >= 5);
9087 	               if( sumcoefcase )
9088 	               {
9089 	                  sumcoef = MIN(weights[nvars - 1] + weights[nvars - 5], weights[nvars - 2] + weights[nvars - 3]);
9090 	               }
9091 	               else
9092 	               {
9093 	                  sumcoef = MIN(weights[nvars - 1] + weights[nvars - 4], weights[nvars - 1] + weights[nvars - 2] + weights[nvars - 3]);
9094 	               }
9095 	               break;
9096 	            default:
9097 	               return SCIP_ERROR;
9098 	            }
9099 	
9100 	            /* tighten next coefficients that, pair with the current small coefficient, exceed the dualcapacity */
9101 	            minweight = weights[end];
9102 	            while( minweight <= sumcoef )
9103 	            {
9104 	               newweight = dualcapacity - minweight;
9105 	               startv = v;
9106 	               assert(v < nvars);
9107 	
9108 	               /* @todo check for further reductions, when two times the minweight exceeds the dualcapacity */
9109 	               /* shrink big coefficients */
9110 	               while( weights[v] + minweight > dualcapacity && 2 * minweight <= dualcapacity )
9111 	               {
9112 	                  reductionsum += (weights[v] - newweight);
9113 	                  consdataChgWeight(consdata, v, newweight);
9114 	                  ++v;
9115 	                  assert(v < nvars);
9116 	               }
9117 	               (*nchgcoefs) += (v - startv);
9118 	
9119 	               /* skip unchangable weights */
9120 	               while( weights[v] + minweight == dualcapacity )
9121 	               {
9122 	                  assert(v < nvars);
9123 	                  ++v;
9124 	               }
9125 	
9126 	               --end;
9127 	               /* skip same end weights */
9128 	               while( end >= 0 && weights[end] == weights[end + 1] )
9129 	                  --end;
9130 	
9131 	               if( v >= end )
9132 	                  goto TERMINATE;
9133 	
9134 	               minweight = weights[end];
9135 	            }
9136 	
9137 	            if( v >= end )
9138 	               goto TERMINATE;
9139 	
9140 	            /* now check if a combination of small coefficients allows us to tighten big coefficients further */
9141 	            if( sumcoef < minweight )
9142 	            {
9143 	               minweight = sumcoef;
9144 	               newweight = dualcapacity - minweight;
9145 	               startv = v;
9146 	               assert(v < nvars);
9147 	
9148 	               /* shrink big coefficients */
9149 	               while( weights[v] + minweight > dualcapacity && 2 * minweight <= dualcapacity )
9150 	               {
9151 	                  reductionsum += (weights[v] - newweight);
9152 	                  consdataChgWeight(consdata, v, newweight);
9153 	                  ++v;
9154 	                  assert(v < nvars);
9155 	               }
9156 	               (*nchgcoefs) += (v - startv);
9157 	
9158 	               /* skip unchangable weights */
9159 	               while( weights[v] + minweight == dualcapacity )
9160 	               {
9161 	                  assert(v < nvars);
9162 	                  ++v;
9163 	               }
9164 	            }
9165 	
9166 	            if( v >= end )
9167 	               goto TERMINATE;
9168 	
9169 	            /* can we stop early, another special reduction case might exist */
9170 	            if( 2 * weights[end] > dualcapacity )
9171 	            {
9172 	               restsumweights = 0;
9173 	
9174 	               /* determine capacity of the small items */
9175 	               for( w = end + 1; w < nvars; ++w )
9176 	                  restsumweights += weights[w];
9177 	
9178 	               if( restsumweights * 2 <= dualcapacity )
9179 	               {
9180 	                  /* check for further posssible reductions in the middle */
9181 	                  while( v < end && restsumweights + weights[v] >= dualcapacity )
9182 	                     ++v;
9183 	
9184 	                  if( v >= end )
9185 	                     goto TERMINATE;
9186 	
9187 	                  /* dualcapacity is even, we can set the middle weights to dualcapacity/2 */
9188 	                  if( (dualcapacity & 1) == 0 )
9189 	                  {
9190 	                     newweight = dualcapacity / 2;
9191 	
9192 	                     /* set all middle coefficients */
9193 	                     for( ; v <= end; ++v )
9194 	                     {
9195 	                        if( weights[v] > newweight )
9196 	                        {
9197 	                           reductionsum += (weights[v] - newweight);
9198 	                           consdataChgWeight(consdata, v, newweight);
9199 	                           ++(*nchgcoefs);
9200 	                        }
9201 	                     }
9202 	                  }
9203 	                  /* dualcapacity is odd, we can set the middle weights to dualcapacity but therefor need to multiply all
9204 	                   * other coefficients by 2
9205 	                   */
9206 	                  else
9207 	                  {
9208 	                     /* correct the reductionsum */
9209 	                     reductionsum *= 2;
9210 	
9211 	                     /* multiply big coefficients by 2 */
9212 	                     for( w = 0; w < v; ++w )
9213 	                     {
9214 	                        consdataChgWeight(consdata, w, weights[w] * 2);
9215 	                     }
9216 	
9217 	                     newweight = dualcapacity;
9218 	                     /* set all middle coefficients */
9219 	                     for( ; v <= end; ++v )
9220 	                     {
9221 	                        reductionsum += (2 * weights[v] - newweight);
9222 	                        consdataChgWeight(consdata, v, newweight);
9223 	                     }
9224 	
9225 	                     /* multiply small coefficients by 2 */
9226 	                     for( w = end + 1; w < nvars; ++w )
9227 	                     {
9228 	                        consdataChgWeight(consdata, w, weights[w] * 2);
9229 	                     }
9230 	                     (*nchgcoefs) += nvars;
9231 	
9232 	                     dualcapacity *= 2;
9233 	                     consdata->capacity *= 2;
9234 	                     ++(*nchgsides);
9235 	                  }
9236 	               }
9237 	
9238 	               goto TERMINATE;
9239 	            }
9240 	
9241 	            /* cannot tighten any further */
9242 	            if( 2 * sumcoef > dualcapacity )
9243 	               goto TERMINATE;
9244 	         }
9245 	      }
9246 	   }
9247 	
9248 	 TERMINATE:
9249 	   /* correct capacity */
9250 	   if( reductionsum > 0 )
9251 	   {
9252 	      assert(v > 0);
9253 	
9254 	      consdata->capacity -= reductionsum;
9255 	      ++(*nchgsides);
9256 	
9257 	      assert(consdata->weightsum - dualcapacity == consdata->capacity);
9258 	   }
9259 	   assert(weights[0] <= consdata->capacity);
9260 	
9261 	   /* weight should still be sorted, because the reduction preserves this, but corresponding variables with equal
9262 	    * weight must not be sorted by their index
9263 	    */
9264 	#ifndef NDEBUG
9265 	   for( w = nvars - 1; w > 0; --w )
9266 	      assert(weights[w] <= weights[w - 1]);
9267 	#endif
9268 	
9269 	   if( oldnchgcoefs < *nchgcoefs )
9270 	   {
9271 	      assert(!SCIPconsIsDeleted(cons));
9272 	
9273 	      /* it might be that we can divide the weights by their greatest common divisor */
9274 	      normalizeWeights(cons, nchgcoefs, nchgsides);
9275 	   }
9276 	   else
9277 	   {
9278 	      assert(oldnchgcoefs == *nchgcoefs);
9279 	      assert(oldnchgsides == *nchgsides);
9280 	   }
9281 	
9282 	   return SCIP_OKAY;
9283 	}
9284 	
9285 	
9286 	/** fixes variables with weights bigger than the capacity and delete redundant constraints, also sort weights */
9287 	static
9288 	SCIP_RETCODE prepareCons(
9289 	   SCIP*                 scip,               /**< SCIP data structure */
9290 	   SCIP_CONS*            cons,               /**< knapsack constraint */
9291 	   int*                  nfixedvars,         /**< pointer to store the amount of fixed variables */
9292 	   int*                  ndelconss,          /**< pointer to store the amount of deleted constraints */
9293 	   int*                  nchgcoefs           /**< pointer to store the amount of changed coefficients */
9294 	   )
9295 	{
9296 	   SCIP_VAR** vars;
9297 	   SCIP_CONSDATA* consdata;
9298 	   SCIP_Longint* weights;
9299 	   SCIP_Longint capacity;
9300 	   SCIP_Bool infeasible;
9301 	   SCIP_Bool fixed;
9302 	   int nvars;
9303 	   int v;
9304 	
9305 	   assert(scip != NULL);
9306 	   assert(cons != NULL);
9307 	   assert(nfixedvars != NULL);
9308 	   assert(ndelconss != NULL);
9309 	   assert(nchgcoefs != NULL);
9310 	
9311 	   consdata = SCIPconsGetData(cons);
9312 	   assert(consdata != NULL);
9313 	
9314 	   nvars = consdata->nvars;
9315 	
9316 	   /* no variables left, then delete constraint */
9317 	   if( nvars == 0 )
9318 	   {
9319 	      assert(consdata->capacity >= 0);
9320 	
9321 	      SCIP_CALL( SCIPdelCons(scip, cons) );
9322 	      ++(*ndelconss);
9323 	
9324 	      return SCIP_OKAY;
9325 	   }
9326 	
9327 	   /* sort items */
9328 	   sortItems(consdata);
9329 	
9330 	   vars = consdata->vars;
9331 	   weights = consdata->weights;
9332 	   capacity = consdata->capacity;
9333 	   v = 0;
9334 	
9335 	   /* check for weights bigger than the capacity */
9336 	   while( v < nvars && weights[v] > capacity )
9337 	   {
9338 	      SCIP_CALL( SCIPfixVar(scip, vars[v], 0.0, &infeasible, &fixed) );
9339 	      assert(!infeasible);
9340 	
9341 	      if( fixed )
9342 	         ++(*nfixedvars);
9343 	
9344 	      ++v;
9345 	   }
9346 	
9347 	   /* if we fixed at least one variable we need to delete them from the constraint */
9348 	   if( v > 0 )
9349 	   {
9350 	      if( v == nvars )
9351 	      {
9352 	         SCIP_CALL( SCIPdelCons(scip, cons) );
9353 	         ++(*ndelconss);
9354 	
9355 	         return SCIP_OKAY;
9356 	      }
9357 	
9358 	      /* delete all position from back to front */
9359 	      for( --v; v >= 0; --v )
9360 	      {
9361 	         SCIP_CALL( delCoefPos(scip, cons, v) );
9362 	         ++(*nchgcoefs);
9363 	      }
9364 	
9365 	      /* sort items again because of deletion */
9366 	      sortItems(consdata);
9367 	      assert(vars == consdata->vars);
9368 	      assert(weights == consdata->weights);
9369 	   }
9370 	   assert(consdata->sorted);
9371 	   assert(weights[0] <= capacity);
9372 	
9373 	   if( !SCIPisHugeValue(scip, (SCIP_Real) capacity) && consdata->weightsum <= capacity )
9374 	   {
9375 	      SCIP_CALL( SCIPdelCons(scip, cons) );
9376 	      ++(*ndelconss);
9377 	   }
9378 	
9379 	   return SCIP_OKAY;
9380 	}
9381 	
9382 	
9383 	/** tries to simplify weights and delete redundant variables in knapsack a^Tx <= capacity
9384 	 *
9385 	 *  1. use the duality between a^Tx <= capacity   <=>   -a^T~x <= capacity - weightsum to tighten weights, e.g.
9386 	 *
9387 	 *     11x1 + 10x2 + 7x3 + 5x4 + 5x5 <= 25    <=>   -10~x1 - 10~x2 - 7~x3 - 5~x4 - 5~x5 <= -13
9388 	 *
9389 	 *     the above constraint can be changed to
9390 	 *
9391 	 *     -8~x1 - 8~x2 - 7~x3 - 5~x4 - 5~x5 <= -12   <=>   8x1 + 8x2 + 7x3 + 5x4 + 5x5 <= 20
9392 	 *
9393 	 *  2. if variables in a constraint do not affect the (in-)feasibility of the constraint, we can delete them, e.g.
9394 	 *
9395 	 *     7x1 + 6x2 + 5x3 + 5x4 + x5 + x6 <= 20 => x5 and x6 are redundant and can be removed
9396 	 *
9397 	 *  3. Tries to use gcd information an all but one weight to change this not-included weight and normalize the
9398 	 *     constraint further, e.g.
9399 	 *
9400 	 *     9x1 + 6x2 + 6x3 + 5x4 <= 13   =>   9x1 + 6x2 + 6x3 + 6x4 <= 12   =>   3x1 + 2x2 + 2x3 + 2x4 <= 4   =>   4x1 + 2x2 + 2x3 + 2x4 <= 4
9401 	 *                                                                                                        =>   2x1 + x2 + x3 + x4 <= 2
9402 	 *     9x1 + 6x2 + 6x3 + 7x4 <= 13   =>   9x1 + 6x2 + 6x3 + 6x4 <= 12   =>   see above
9403 	 */
9404 	static
9405 	SCIP_RETCODE simplifyInequalities(
9406 	   SCIP*                 scip,               /**< SCIP data structure */
9407 	   SCIP_CONS*            cons,               /**< knapsack constraint */
9408 	   int*                  nfixedvars,         /**< pointer to store the amount of fixed variables */
9409 	   int*                  ndelconss,          /**< pointer to store the amount of deleted constraints */
9410 	   int*                  nchgcoefs,          /**< pointer to store the amount of changed coefficients */
9411 	   int*                  nchgsides,          /**< pointer to store the amount of changed sides */
9412 	   int*                  naddconss,          /**< pointer to count number of added constraints */
9413 	   SCIP_Bool*            cutoff              /**< pointer to store whether the node can be cut off */
9414 	   )
9415 	{
9416 	   SCIP_VAR** vars;
9417 	   SCIP_CONSDATA* consdata;
9418 	   SCIP_Longint* weights;
9419 	   SCIP_Longint restweight;
9420 	   SCIP_Longint newweight;
9421 	   SCIP_Longint weight;
9422 	   SCIP_Longint oldgcd;
9423 	   SCIP_Longint rest;
9424 	   SCIP_Longint gcd;
9425 	   int oldnchgcoefs;
9426 	   int oldnchgsides;
9427 	   int candpos;
9428 	   int candpos2;
9429 	   int offsetv;
9430 	   int nvars;
9431 	   int v;
9432 	
9433 	   assert(scip != NULL);
9434 	   assert(cons != NULL);
9435 	   assert(nfixedvars != NULL);
9436 	   assert(ndelconss != NULL);
9437 	   assert(nchgcoefs != NULL);
9438 	   assert(nchgsides != NULL);
9439 	   assert(naddconss != NULL);
9440 	   assert(cutoff != NULL);
9441 	   assert(!SCIPconsIsModifiable(cons));
9442 	
9443 	   consdata = SCIPconsGetData(cons);
9444 	   assert( consdata != NULL );
9445 	
9446 	   *cutoff = FALSE;
9447 	
9448 	   /* remove double enties and also combinations of active and negated variables */
9449 	   SCIP_CALL( mergeMultiples(scip, cons, cutoff) );
9450 	   assert(consdata->merged);
9451 	   if( *cutoff )
9452 	      return SCIP_OKAY;
9453 	
9454 	   assert(consdata->capacity >= 0);
9455 	
9456 	   /* fix variables with big coefficients and remove redundant constraints, sort weights */
9457 	   SCIP_CALL( prepareCons(scip, cons, nfixedvars, ndelconss, nchgcoefs) );
9458 	
9459 	   if( SCIPconsIsDeleted(cons) )
9460 	      return SCIP_OKAY;
9461 	
9462 	   if( !SCIPisHugeValue(scip, (SCIP_Real) consdata->capacity) )
9463 	   {
9464 	      /* 1. dual weights tightening */
9465 	      SCIP_CALL( dualWeightsTightening(scip, cons, ndelconss, nchgcoefs, nchgsides, naddconss) );
9466 	
9467 	      if( SCIPconsIsDeleted(cons) )
9468 	         return SCIP_OKAY;
9469 	      /* 2. delete redundant variables */
9470 	      SCIP_CALL( detectRedundantVars(scip, cons, ndelconss, nchgcoefs, nchgsides, naddconss) );
9471 	
9472 	      if( SCIPconsIsDeleted(cons) )
9473 	         return SCIP_OKAY;
9474 	   }
9475 	
9476 	   weights = consdata->weights;
9477 	   nvars = consdata->nvars;
9478 	
9479 	#ifndef NDEBUG
9480 	   /* constraint might not be sorted, but the weights are already sorted */
9481 	   for( v = nvars - 1; v > 0; --v )
9482 	      assert(weights[v] <= weights[v-1]);
9483 	#endif
9484 	
9485 	   /* determine greatest common divisor */
9486 	   gcd = weights[nvars - 1];
9487 	   for( v = nvars - 2; v >= 0 && gcd > 1; --v )
9488 	   {
9489 	      gcd = SCIPcalcGreComDiv(gcd, weights[v]);
9490 	   }
9491 	
9492 	   /* divide the constraint by their greatest common divisor */
9493 	   if( gcd >= 2 )
9494 	   {
9495 	      for( v = nvars - 1; v >= 0; --v )
9496 	      {
9497 	         consdataChgWeight(consdata, v, weights[v]/gcd);
9498 	      }
9499 	      (*nchgcoefs) += nvars;
9500 	
9501 	      consdata->capacity /= gcd;
9502 	      (*nchgsides)++;
9503 	   }
9504 	   assert(consdata->nvars == nvars);
9505 	
9506 	   /* weight should still be sorted, because the reduction preserves this, but corresponding variables with equal weight
9507 	    * must not be sorted by their index
9508 	    */
9509 	#ifndef NDEBUG
9510 	   for( v = nvars - 1; v > 0; --v )
9511 	      assert(weights[v] <= weights[v-1]);
9512 	#endif
9513 	
9514 	   /* 3. start gcd procedure for all variables */
9515 	   do
9516 	   {
9517 	      SCIPdebug( oldnchgcoefs = *nchgcoefs; )
9518 	      SCIPdebug( oldnchgsides = *nchgsides; )
9519 	
9520 	      vars = consdata->vars;
9521 	      weights = consdata->weights;
9522 	      nvars = consdata->nvars;
9523 	
9524 	      /* stop if we have two coefficients which are one in absolute value */
9525 	      if( weights[nvars - 1] == 1 && weights[nvars - 2] == 1 )
9526 	         return SCIP_OKAY;
9527 	
9528 	      v = 0;
9529 	      /* determine coefficients as big as the capacity, these we do not need to take into account when calculating the
9530 	       * gcd
9531 	       */
9532 	      while( weights[v] == consdata->capacity )
9533 	      {
9534 	         ++v;
9535 	         assert(v < nvars);
9536 	      }
9537 	
9538 	      /* all but one variable are as big as the capacity, this is handled elsewhere */
9539 	      if( v == nvars - 1 )
9540 	         return SCIP_OKAY;
9541 	
9542 	      offsetv = v;
9543 	
9544 	      gcd = -1;
9545 	      candpos = -1;
9546 	      candpos2 = -1;
9547 	
9548 	      /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
9549 	       * change the coefficient
9550 	       */
9551 	      for( v = nvars - 1; v >= offsetv; --v )
9552 	      {
9553 	         weight = weights[v];
9554 	         assert(weight >= 1);
9555 	
9556 	         oldgcd = gcd;
9557 	
9558 	         if( gcd == -1 )
9559 	         {
9560 	            gcd = weights[v];
9561 	            assert(gcd >= 1);
9562 	         }
9563 	         else
9564 	         {
9565 	            /* calculate greatest common divisor for all variables */
9566 	            gcd = SCIPcalcGreComDiv(gcd, weight);
9567 	         }
9568 	
9569 	         /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
9570 	          * can terminate
9571 	          */
9572 	         if( gcd == 1 )
9573 	         {
9574 	            /* found candidate */
9575 	            if( candpos == -1 )
9576 	            {
9577 	               gcd = oldgcd;
9578 	               candpos = v;
9579 	
9580 	               /* if both first coefficients have a gcd of 1, both are candidates for the coefficient change */
9581 	               if( v == nvars - 2 )
9582 	                  candpos2 = v + 1;
9583 	            }
9584 	            /* two different variables lead to a gcd of one, so we cannot change a coefficient */
9585 	            else
9586 	            {
9587 	               if( candpos == v + 1 && candpos2 == v + 2 )
9588 	               {
9589 	                  assert(candpos2 == nvars - 1);
9590 	
9591 	                  /* take new candidates */
9592 	                  candpos = candpos2;
9593 	
9594 	                  /* recalculate gcd from scratch */
9595 	                  gcd = weights[v+1];
9596 	                  assert(gcd >= 1);
9597 	
9598 	                  /* calculate greatest common divisor for variables */
9599 	                  gcd = SCIPcalcGreComDiv(gcd, weights[v]);
9600 	                  if( gcd == 1 )
9601 	                     return SCIP_OKAY;
9602 	               }
9603 	               else
9604 	                  /* cannot determine a possible coefficient for reduction */
9605 	                  return SCIP_OKAY;
9606 	            }
9607 	         }
9608 	      }
9609 	      assert(gcd >= 2);
9610 	
9611 	      /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
9612 	       * further
9613 	       */
9614 	      assert(((candpos >= offsetv) || (candpos == -1 && offsetv > 0)) && candpos < nvars);
9615 	
9616 	      /* determine the remainder of the capacity and the gcd */
9617 	      rest = consdata->capacity % gcd;
9618 	      assert(rest >= 0);
9619 	      assert(rest < gcd);
9620 	
9621 	      if( candpos == -1 )
9622 	      {
9623 	         /* we assume that the constraint was normalized */
9624 	         assert(rest > 0);
9625 	
9626 	         /* replace old with new capacity */
9627 	         consdata->capacity -= rest;
9628 	         ++(*nchgsides);
9629 	
9630 	         /* replace old big coefficients with new capacity */
9631 	         for( v = 0; v < offsetv; ++v )
9632 	         {
9633 	            consdataChgWeight(consdata, v, consdata->capacity);
9634 	         }
9635 	
9636 	         *nchgcoefs += offsetv;
9637 	         goto CONTINUE;
9638 	      }
9639 	
9640 	      /* determine the remainder of the coefficient candidate and the gcd */
9641 	      restweight = weights[candpos] % gcd;
9642 	      assert(restweight >= 1);
9643 	      assert(restweight < gcd);
9644 	
9645 	      /* calculate new coefficient */
9646 	      if( restweight > rest )
9647 	         newweight = weights[candpos] - restweight + gcd;
9648 	      else
9649 	         newweight = weights[candpos] - restweight;
9650 	
9651 	      assert(newweight == 0 || SCIPcalcGreComDiv(gcd, newweight) == gcd);
9652 	
9653 	      SCIPdebugMsg(scip, "gcd = %" SCIP_LONGINT_FORMAT ", rest = %" SCIP_LONGINT_FORMAT ", restweight = %" SCIP_LONGINT_FORMAT "; possible new weight of variable <%s> %" SCIP_LONGINT_FORMAT ", possible new capacity %" SCIP_LONGINT_FORMAT ", offset of coefficients as big as capacity %d\n", gcd, rest, restweight, SCIPvarGetName(vars[candpos]), newweight, consdata->capacity - rest, offsetv);
9654 	
9655 	      /* must not change weights and capacity if one variable would be removed and we have a big coefficient,
9656 	       * e.g., 11x1 + 6x2 + 6x3 + 5x4 <= 11 => gcd = 6, offsetv = 1 => newweight = 0, but we would lose x1 = 1 => x4 = 0
9657 	       */
9658 	      if( newweight == 0 && offsetv > 0 )
9659 	         return SCIP_OKAY;
9660 	
9661 	      if( rest > 0 )
9662 	      {
9663 	         /* replace old with new capacity */
9664 	         consdata->capacity -= rest;
9665 	         ++(*nchgsides);
9666 	
9667 	         /* replace old big coefficients with new capacity */
9668 	         for( v = 0; v < offsetv; ++v )
9669 	         {
9670 	            consdataChgWeight(consdata, v, consdata->capacity);
9671 	         }
9672 	
9673 	         *nchgcoefs += offsetv;
9674 	      }
9675 	
9676 	      if( newweight == 0 )
9677 	      {
9678 	         /* delete redundant coefficient */
9679 	         SCIP_CALL( delCoefPos(scip, cons, candpos) );
9680 	         assert(consdata->nvars == nvars - 1);
9681 	         --nvars;
9682 	      }
9683 	      else
9684 	      {
9685 	         /* replace old with new coefficient */
9686 	         consdataChgWeight(consdata, candpos, newweight);
9687 	      }
9688 	      ++(*nchgcoefs);
9689 	
9690 	      assert(consdata->vars == vars);
9691 	      assert(consdata->nvars == nvars);
9692 	      assert(consdata->weights == weights);
9693 	
9694 	   CONTINUE:
9695 	      /* now constraint can be normalized, dividing it by the gcd */
9696 	      for( v = nvars - 1; v >= 0; --v )
9697 	      {
9698 	         consdataChgWeight(consdata, v, weights[v]/gcd);
9699 	      }
9700 	      (*nchgcoefs) += nvars;
9701 	
9702 	      consdata->capacity /= gcd;
9703 	      ++(*nchgsides);
9704 	
9705 	      SCIPdebugPrintCons(scip, cons, NULL);
9706 	
9707 	      SCIPdebugMsg(scip, "we did %d coefficient changes and %d side changes on constraint %s when applying one round of the gcd algorithm\n", *nchgcoefs - oldnchgcoefs, *nchgsides - oldnchgsides, SCIPconsGetName(cons));
9708 	   }
9709 	   while( nvars >= 2 );
9710 	
9711 	   return SCIP_OKAY;
9712 	}
9713 	
9714 	
9715 	/** inserts an element into the list of binary zero implications */
9716 	static
9717 	SCIP_RETCODE insertZerolist(
9718 	   SCIP*                 scip,               /**< SCIP data structure */
9719 	   int**                 liftcands,          /**< array of the lifting candidates */
9720 	   int*                  nliftcands,         /**< number of lifting candidates */
9721 	   int**                 firstidxs,          /**< array of first zeroitems indices */
9722 	   SCIP_Longint**        zeroweightsums,     /**< array of sums of weights of the implied-to-zero items */
9723 	   int**                 zeroitems,          /**< pointer to zero items array */
9724 	   int**                 nextidxs,           /**< pointer to array of next zeroitems indeces */
9725 	   int*                  zeroitemssize,      /**< pointer to size of zero items array */
9726 	   int*                  nzeroitems,         /**< pointer to length of zero items array */
9727 	   int                   probindex,          /**< problem index of variable y in implication y == v -> x == 0 */
9728 	   SCIP_Bool             value,              /**< value v of variable y in implication */
9729 	   int                   knapsackidx,        /**< index of variable x in knapsack */
9730 	   SCIP_Longint          knapsackweight,     /**< weight of variable x in knapsack */
9731 	   SCIP_Bool*            memlimitreached     /**< pointer to store whether the memory limit was reached */
9732 	   )
9733 	{
9734 	   int nzeros;
9735 	
9736 	   assert(liftcands != NULL);
9737 	   assert(liftcands[value] != NULL);
9738 	   assert(nliftcands != NULL);
9739 	   assert(firstidxs != NULL);
9740 	   assert(firstidxs[value] != NULL);
9741 	   assert(zeroweightsums != NULL);
9742 	   assert(zeroweightsums[value] != NULL);
9743 	   assert(zeroitems != NULL);
9744 	   assert(nextidxs != NULL);
9745 	   assert(zeroitemssize != NULL);
9746 	   assert(nzeroitems != NULL);
9747 	   assert(*nzeroitems <= *zeroitemssize);
9748 	   assert(0 <= probindex && probindex < SCIPgetNVars(scip) - SCIPgetNContVars(scip));
9749 	   assert(memlimitreached != NULL);
9750 	
9751 	   nzeros = *nzeroitems;
9752 	
9753 	   /* allocate enough memory */
9754 	   if( nzeros == *zeroitemssize )
9755 	   {
9756 	      /* we explicitly construct the complete implication graph where the knapsack variables are involved;
9757 	       * this can be too huge - abort on memory limit
9758 	       */
9759 	      if( *zeroitemssize >= MAX_ZEROITEMS_SIZE )
9760 	      {
9761 	         SCIPdebugMsg(scip, "memory limit of %d bytes reached in knapsack preprocessing - abort collecting zero items\n",
9762 	            *zeroitemssize);
9763 	         *memlimitreached = TRUE;
9764 	         return SCIP_OKAY;
9765 	      }
9766 	      *zeroitemssize *= 2;
9767 	      *zeroitemssize = MIN(*zeroitemssize, MAX_ZEROITEMS_SIZE);
9768 	      SCIP_CALL( SCIPreallocBufferArray(scip, zeroitems, *zeroitemssize) );
9769 	      SCIP_CALL( SCIPreallocBufferArray(scip, nextidxs, *zeroitemssize) );
9770 	   }
9771 	   assert(nzeros < *zeroitemssize);
9772 	
9773 	   if( *memlimitreached )
9774 	      *memlimitreached = FALSE;
9775 	
9776 	   /* insert element */
9777 	   (*zeroitems)[nzeros] = knapsackidx;
9778 	   (*nextidxs)[nzeros] = firstidxs[value][probindex];
9779 	   if( firstidxs[value][probindex] == 0 )
9780 	   {
9781 	      liftcands[value][nliftcands[value]] = probindex;
9782 	      ++nliftcands[value];
9783 	   }
9784 	   firstidxs[value][probindex] = nzeros;
9785 	   ++(*nzeroitems);
9786 	   zeroweightsums[value][probindex] += knapsackweight;
9787 	
9788 	   return SCIP_OKAY;
9789 	}
9790 	
9791 	#define MAX_CLIQUELENGTH 50
9792 	/** applies rule (3) of the weight tightening procedure, which can lift other variables into the knapsack:
9793 	 *  (3) for a clique C let C(xi == v) := C \ {j: xi == v -> xj == 0}),
9794 	 *      let cliqueweightsum(xi == v) := sum(W(C(xi == v)))
9795 	 *      if cliqueweightsum(xi == v) < capacity:
9796 	 *      - fixing variable xi to v would make the knapsack constraint redundant
9797 	 *      - the weight of the variable or its negation (depending on v) can be increased as long as it has the same
9798 	 *        redundancy effect:
9799 	 *          wi'       := capacity - cliqueweightsum(xi == v)
9800 	 *      this rule can also be applied to binary variables not in the knapsack!
9801 	 */
9802 	static
9803 	SCIP_RETCODE tightenWeightsLift(
9804 	   SCIP*                 scip,               /**< SCIP data structure */
9805 	   SCIP_CONS*            cons,               /**< knapsack constraint */
9806 	   int*                  nchgcoefs,          /**< pointer to count total number of changed coefficients */
9807 	   SCIP_Bool*            cutoff              /**< pointer to store whether the node can be cut off */
9808 	   )
9809 	{
9810 	   SCIP_CONSDATA* consdata;
9811 	   SCIP_VAR** binvars;
9812 	   int nbinvars;
9813 	   int* liftcands[2];          /* binary variables that have at least one entry in zeroitems */
9814 	   int* firstidxs[2];          /* first index in zeroitems for each binary variable/value pair, or zero for empty list */
9815 	   SCIP_Longint* zeroweightsums[2]; /* sums of weights of the implied-to-zero items */
9816 	   int* zeroitems;             /* item number in knapsack that is implied to zero */
9817 	   int* nextidxs;              /* next index in zeroitems for the same binary variable, or zero for end of list */
9818 	   int zeroitemssize;
9819 	   int nzeroitems;
9820 	   SCIP_Bool* zeroiteminserted[2];
9821 	   SCIP_Bool memlimitreached;
9822 	   int nliftcands[2];
9823 	   SCIP_Bool* cliqueused;
9824 	   SCIP_Bool* itemremoved;
9825 	   SCIP_Longint maxcliqueweightsum;
9826 	   SCIP_VAR** addvars;
9827 	   SCIP_Longint* addweights;
9828 	   SCIP_Longint addweightsum;
9829 	   int nvars;
9830 	   int cliquenum;
9831 	   int naddvars;
9832 	   int val;
9833 	   int i;
9834 	
9835 	   int* tmpindices;
9836 	   SCIP_Bool* tmpboolindices;
9837 	   int* tmpindices2;
9838 	   SCIP_Bool* tmpboolindices2;
9839 	   int* tmpindices3;
9840 	   SCIP_Bool* tmpboolindices3;
9841 	   int tmp;
9842 	   int tmp2;
9843 	   int tmp3;
9844 	   SCIP_CONSHDLR* conshdlr;
9845 	   SCIP_CONSHDLRDATA* conshdlrdata;
9846 	
9847 	   assert(nchgcoefs != NULL);
9848 	   assert(!SCIPconsIsModifiable(cons));
9849 	
9850 	   consdata = SCIPconsGetData(cons);
9851 	   assert(consdata != NULL);
9852 	   assert(consdata->row == NULL); /* we are in presolve, so no LP row exists */
9853 	   assert(consdata->weightsum > consdata->capacity); /* otherwise, the constraint is redundant */
9854 	   assert(consdata->nvars > 0);
9855 	   assert(consdata->merged);
9856 	
9857 	   nvars = consdata->nvars;
9858 	
9859 	   /* check if the knapsack has too many items/cliques for applying this costly method */
9860 	   if( (!consdata->cliquepartitioned && nvars > MAX_USECLIQUES_SIZE) || consdata->ncliques > MAX_USECLIQUES_SIZE )
9861 	      return SCIP_OKAY;
9862 	
9863 	   /* sort items, s.t. the heaviest one is in the first position */
9864 	   sortItems(consdata);
9865 	
9866 	   if( !consdata->cliquepartitioned && nvars > MAX_USECLIQUES_SIZE )
9867 	      return SCIP_OKAY;
9868 	
9869 	   /* we have to consider all integral variables since even integer and implicit integer variables can have binary bounds */
9870 	   nbinvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
9871 	   assert(nbinvars > 0);
9872 	   binvars = SCIPgetVars(scip);
9873 	
9874 	   /* get conshdlrdata to use cleared memory */
9875 	   conshdlr = SCIPconsGetHdlr(cons);
9876 	   assert(conshdlr != NULL);
9877 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
9878 	   assert(conshdlrdata != NULL);
9879 	
9880 	   /* allocate temporary memory for the list of implied to zero variables */
9881 	   zeroitemssize = MIN(nbinvars, MAX_ZEROITEMS_SIZE); /* initial size of zeroitems buffer */
9882 	   SCIP_CALL( SCIPallocBufferArray(scip, &liftcands[0], nbinvars) );
9883 	   SCIP_CALL( SCIPallocBufferArray(scip, &liftcands[1], nbinvars) );
9884 	
9885 	   assert(conshdlrdata->ints1size > 0);
9886 	   assert(conshdlrdata->ints2size > 0);
9887 	   assert(conshdlrdata->longints1size > 0);
9888 	   assert(conshdlrdata->longints2size > 0);
9889 	
9890 	   /* next if conditions should normally not be true, because it means that presolving has created more binary variables
9891 	    * than binary + integer variables existed at the presolving initialization method, but for example if you would
9892 	    * transform all integers into their binary representation then it maybe happens
9893 	    */
9894 	   if( conshdlrdata->ints1size < nbinvars )
9895 	   {
9896 	      int oldsize = conshdlrdata->ints1size;
9897 	
9898 	      conshdlrdata->ints1size = nbinvars;
9899 	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->ints1, oldsize, conshdlrdata->ints1size) );
9900 	      BMSclearMemoryArray(&(conshdlrdata->ints1[oldsize]), conshdlrdata->ints1size - oldsize); /*lint !e866*/
9901 	   }
9902 	   if( conshdlrdata->ints2size < nbinvars )
9903 	   {
9904 	      int oldsize = conshdlrdata->ints2size;
9905 	
9906 	      conshdlrdata->ints2size = nbinvars;
9907 	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->ints2, oldsize, conshdlrdata->ints2size) );
9908 	      BMSclearMemoryArray(&(conshdlrdata->ints2[oldsize]), conshdlrdata->ints2size - oldsize); /*lint !e866*/
9909 	   }
9910 	   if( conshdlrdata->longints1size < nbinvars )
9911 	   {
9912 	      int oldsize = conshdlrdata->longints1size;
9913 	
9914 	      conshdlrdata->longints1size = nbinvars;
9915 	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->longints1, oldsize, conshdlrdata->longints1size) );
9916 	      BMSclearMemoryArray(&(conshdlrdata->longints1[oldsize]), conshdlrdata->longints1size - oldsize); /*lint !e866*/
9917 	   }
9918 	   if( conshdlrdata->longints2size < nbinvars )
9919 	   {
9920 	      int oldsize = conshdlrdata->longints2size;
9921 	
9922 	      conshdlrdata->longints2size = nbinvars;
9923 	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->longints2, oldsize, conshdlrdata->longints2size) );
9924 	      BMSclearMemoryArray(&(conshdlrdata->longints2[oldsize]), conshdlrdata->longints2size - oldsize); /*lint !e866*/
9925 	   }
9926 	
9927 	   firstidxs[0] = conshdlrdata->ints1;
9928 	   firstidxs[1] = conshdlrdata->ints2;
9929 	   zeroweightsums[0] = conshdlrdata->longints1;
9930 	   zeroweightsums[1] = conshdlrdata->longints2;
9931 	
9932 	   /* check for cleared arrays, all entries are zero */
9933 	#ifndef NDEBUG
9934 	   for( tmp = nbinvars - 1; tmp >= 0; --tmp )
9935 	   {
9936 	      assert(firstidxs[0][tmp] == 0);
9937 	      assert(firstidxs[1][tmp] == 0);
9938 	      assert(zeroweightsums[0][tmp] == 0);
9939 	      assert(zeroweightsums[1][tmp] == 0);
9940 	   }
9941 	#endif
9942 	
9943 	   SCIP_CALL( SCIPallocBufferArray(scip, &zeroitems, zeroitemssize) );
9944 	   SCIP_CALL( SCIPallocBufferArray(scip, &nextidxs, zeroitemssize) );
9945 	
9946 	   zeroitems[0] = -1; /* dummy element */
9947 	   nextidxs[0] = -1;
9948 	   nzeroitems = 1;
9949 	   nliftcands[0] = 0;
9950 	   nliftcands[1] = 0;
9951 	
9952 	   assert(conshdlrdata->bools1size > 0);
9953 	   assert(conshdlrdata->bools2size > 0);
9954 	
9955 	   /* next if conditions should normally not be true, because it means that presolving has created more binary variables
9956 	    * than binary + integer variables existed at the presolving initialization method, but for example if you would
9957 	    * transform all integers into their binary representation then it maybe happens
9958 	    */
9959 	   if( conshdlrdata->bools1size < nbinvars )
9960 	   {
9961 	      int oldsize = conshdlrdata->bools1size;
9962 	
9963 	      conshdlrdata->bools1size = nbinvars;
9964 	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->bools1, oldsize, conshdlrdata->bools1size) );
9965 	      BMSclearMemoryArray(&(conshdlrdata->bools1[oldsize]), conshdlrdata->bools1size - oldsize); /*lint !e866*/
9966 	   }
9967 	   if( conshdlrdata->bools2size < nbinvars )
9968 	   {
9969 	      int oldsize = conshdlrdata->bools2size;
9970 	
9971 	      conshdlrdata->bools2size = nbinvars;
9972 	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->bools2, oldsize, conshdlrdata->bools2size) );
9973 	      BMSclearMemoryArray(&(conshdlrdata->bools2[oldsize]), conshdlrdata->bools2size - oldsize); /*lint !e866*/
9974 	   }
9975 	
9976 	   zeroiteminserted[0] = conshdlrdata->bools1;
9977 	   zeroiteminserted[1] = conshdlrdata->bools2;
9978 	
9979 	   /* check for cleared arrays, all entries are zero */
9980 	#ifndef NDEBUG
9981 	   for( tmp = nbinvars - 1; tmp >= 0; --tmp )
9982 	   {
9983 	      assert(zeroiteminserted[0][tmp] == 0);
9984 	      assert(zeroiteminserted[1][tmp] == 0);
9985 	   }
9986 	#endif
9987 	
9988 	   SCIP_CALL( SCIPallocBufferArray(scip, &tmpboolindices3, consdata->nvars) );
9989 	   SCIP_CALL( SCIPallocBufferArray(scip, &tmpboolindices2, 2 * nbinvars) );
9990 	   SCIP_CALL( SCIPallocBufferArray(scip, &tmpindices3, consdata->nvars) );
9991 	   SCIP_CALL( SCIPallocBufferArray(scip, &tmpindices2, 2 * nbinvars) );
9992 	   SCIP_CALL( SCIPallocBufferArray(scip, &tmpindices, 2 * nbinvars) );
9993 	   SCIP_CALL( SCIPallocBufferArray(scip, &tmpboolindices, 2 * nbinvars) );
9994 	
9995 	   tmp2 = 0;
9996 	   tmp3 = 0;
9997 	
9998 	   memlimitreached = FALSE;
9999 	   for( i = 0; i < consdata->nvars && !memlimitreached; ++i )
10000	   {
10001	      SCIP_CLIQUE** cliques;
10002	      SCIP_VAR* var;
10003	      SCIP_Longint weight;
10004	      SCIP_Bool value;
10005	      int varprobindex;
10006	      int ncliques;
10007	      int j;
10008	
10009	      tmp = 0;
10010	
10011	      /* get corresponding active problem variable */
10012	      var = consdata->vars[i];
10013	      weight = consdata->weights[i];
10014	      value = TRUE;
10015	      SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10016	      varprobindex = SCIPvarGetProbindex(var);
10017	      assert(0 <= varprobindex && varprobindex < nbinvars);
10018	
10019	      /* update the zeroweightsum */
10020	      zeroweightsums[!value][varprobindex] += weight; /*lint !e514*/
10021	      tmpboolindices3[tmp3] = !value;
10022	      tmpindices3[tmp3] = varprobindex;
10023	      ++tmp3;
10024	
10025	      /* initialize the arrays of inserted zero items */
10026	      /* first add the implications (~x == 1 -> x == 0) */
10027	      {
10028	         SCIP_Bool implvalue;
10029	         int probindex;
10030	
10031	         probindex = SCIPvarGetProbindex(var);
10032	         assert(0 <= probindex && probindex < nbinvars);
10033	
10034	         implvalue = !value;
10035	
10036	         /* insert the item into the list of the implied variable/value */
10037	         assert( !zeroiteminserted[implvalue][probindex] );
10038	
10039	         if( firstidxs[implvalue][probindex] == 0 )
10040	         {
10041	            tmpboolindices2[tmp2] = implvalue;
10042	            tmpindices2[tmp2] = probindex;
10043	            ++tmp2;
10044	         }
10045	         SCIP_CALL( insertZerolist(scip, liftcands, nliftcands, firstidxs, zeroweightsums,
10046	               &zeroitems, &nextidxs, &zeroitemssize, &nzeroitems, probindex, implvalue, i, weight,
10047	               &memlimitreached) );
10048	         zeroiteminserted[implvalue][probindex] = TRUE;
10049	         tmpboolindices[tmp] = implvalue;
10050	         tmpindices[tmp] = probindex;
10051	         ++tmp;
10052	      }
10053	
10054	      /* get the cliques where the knapsack item is member of with value 1 */
10055	      ncliques = SCIPvarGetNCliques(var, value);
10056	      cliques = SCIPvarGetCliques(var, value);
10057	      for( j = 0; j < ncliques && !memlimitreached; ++j )
10058	      {
10059	         SCIP_VAR** cliquevars;
10060	         SCIP_Bool* cliquevalues;
10061	         int ncliquevars;
10062	         int k;
10063	
10064	         ncliquevars = SCIPcliqueGetNVars(cliques[j]);
10065	
10066	         /* discard big cliques */
10067	         if( ncliquevars > MAX_CLIQUELENGTH )
10068	            continue;
10069	
10070	         cliquevars = SCIPcliqueGetVars(cliques[j]);
10071	         cliquevalues = SCIPcliqueGetValues(cliques[j]);
10072	
10073	         for( k = ncliquevars - 1; k >= 0; --k )
10074	         {
10075	            SCIP_Bool implvalue;
10076	            int probindex;
10077	
10078	            if( var == cliquevars[k] )
10079	               continue;
10080	
10081	            probindex = SCIPvarGetProbindex(cliquevars[k]);
10082	            if( probindex == -1 )
10083	               continue;
10084	
10085	            assert(0 <= probindex && probindex < nbinvars);
10086	            implvalue = cliquevalues[k];
10087	
10088	            /* insert the item into the list of the clique variable/value */
10089	            if( !zeroiteminserted[implvalue][probindex] )
10090	            {
10091	               if( firstidxs[implvalue][probindex] == 0 )
10092	               {
10093	                  tmpboolindices2[tmp2] = implvalue;
10094	                  tmpindices2[tmp2] = probindex;
10095	                  ++tmp2;
10096	               }
10097	
10098	               SCIP_CALL( insertZerolist(scip, liftcands, nliftcands, firstidxs, zeroweightsums,
10099	                     &zeroitems, &nextidxs, &zeroitemssize, &nzeroitems, probindex, implvalue, i, weight,
10100	                     &memlimitreached) );
10101	               zeroiteminserted[implvalue][probindex] = TRUE;
10102	               tmpboolindices[tmp] = implvalue;
10103	               tmpindices[tmp] = probindex;
10104	               ++tmp;
10105	
10106	               if( memlimitreached )
10107	                  break;
10108	            }
10109	         }
10110	      }
10111	      /* clear zeroiteminserted */
10112	      for( --tmp; tmp >= 0; --tmp)
10113	         zeroiteminserted[tmpboolindices[tmp]][tmpindices[tmp]] = FALSE;
10114	   }
10115	   SCIPfreeBufferArray(scip, &tmpboolindices);
10116	
10117	   /* calculate the clique partition and the maximal sum of weights using the clique information */
10118	   assert(consdata->sorted);
10119	   SCIP_CALL( calcCliquepartition(scip, conshdlrdata, consdata, TRUE, FALSE) );
10120	
10121	   assert(conshdlrdata->bools3size > 0);
10122	
10123	   /* next if condition should normally not be true, because it means that presolving has created more binary variables
10124	    * in one constraint than binary + integer variables existed in the whole problem at the presolving initialization
10125	    * method, but for example if you would transform all integers into their binary representation then it maybe happens
10126	    */
10127	   if( conshdlrdata->bools3size < consdata->nvars )
10128	   {
10129	      int oldsize = conshdlrdata->bools3size;
10130	
10131	      conshdlrdata->bools3size = consdata->nvars;;
10132	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->bools3, oldsize, conshdlrdata->bools3size) );
10133	      BMSclearMemoryArray(&(conshdlrdata->bools3[oldsize]), conshdlrdata->bools3size - oldsize); /*lint !e866*/
10134	   }
10135	
10136	   cliqueused = conshdlrdata->bools3;
10137	
10138	   /* check for cleared array, all entries are zero */
10139	#ifndef NDEBUG
10140	   for( tmp = consdata->nvars - 1; tmp >= 0; --tmp )
10141	      assert(cliqueused[tmp] == 0);
10142	#endif
10143	
10144	   maxcliqueweightsum = 0;
10145	   tmp = 0;
10146	
10147	   /* calculates maximal weight of cliques */
10148	   for( i = 0; i < consdata->nvars; ++i )
10149	   {
10150	      cliquenum = consdata->cliquepartition[i];
10151	      assert(0 <= cliquenum && cliquenum < consdata->nvars);
10152	
10153	      if( !cliqueused[cliquenum] )
10154	      {
10155	         maxcliqueweightsum += consdata->weights[i];
10156	         cliqueused[cliquenum] = TRUE;
10157	         tmpindices[tmp] = cliquenum;
10158	         ++tmp;
10159	      }
10160	   }
10161	   /* clear cliqueused */
10162	   for( --tmp; tmp >= 0; --tmp)
10163	      cliqueused[tmp] = FALSE;
10164	
10165	   assert(conshdlrdata->bools4size > 0);
10166	
10167	   /* next if condition should normally not be true, because it means that presolving has created more binary variables
10168	    * in one constraint than binary + integer variables existed in the whole problem at the presolving initialization
10169	    * method, but for example if you would transform all integers into their binary representation then it maybe happens
10170	    */
10171	   if( conshdlrdata->bools4size < consdata->nvars )
10172	   {
10173	      int oldsize = conshdlrdata->bools4size;
10174	
10175	      conshdlrdata->bools4size = consdata->nvars;
10176	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->bools4, oldsize, conshdlrdata->bools4size) );
10177	      BMSclearMemoryArray(&conshdlrdata->bools4[oldsize], conshdlrdata->bools4size - oldsize); /*lint !e866*/
10178	   }
10179	
10180	   itemremoved = conshdlrdata->bools4;
10181	
10182	   /* check for cleared array, all entries are zero */
10183	#ifndef NDEBUG
10184	   for( tmp = consdata->nvars - 1; tmp >= 0; --tmp )
10185	      assert(itemremoved[tmp] == 0);
10186	#endif
10187	
10188	   /* for each binary variable xi and each fixing v, calculate the cliqueweightsum and update the weight of the
10189	    * variable in the knapsack (this is sequence-dependent because the new or modified weights have to be
10190	    * included in subsequent cliqueweightsum calculations)
10191	    */
10192	   SCIP_CALL( SCIPallocBufferArray(scip, &addvars, 2*nbinvars) );
10193	   SCIP_CALL( SCIPallocBufferArray(scip, &addweights, 2*nbinvars) );
10194	   naddvars = 0;
10195	   addweightsum = 0;
10196	   for( val = 0; val < 2 && addweightsum < consdata->capacity; ++val )
10197	   {
10198	      for( i = 0; i < nliftcands[val] && addweightsum < consdata->capacity; ++i )
10199	      {
10200	         SCIP_Longint cliqueweightsum;
10201	         int probindex;
10202	         int idx;
10203	         int j;
10204	
10205	         tmp = 0;
10206	
10207	         probindex = liftcands[val][i];
10208	         assert(0 <= probindex && probindex < nbinvars);
10209	
10210	         /* ignore empty zero lists and variables that cannot be lifted anyways */
10211	         if( firstidxs[val][probindex] == 0
10212	            || maxcliqueweightsum - zeroweightsums[val][probindex] + addweightsum >= consdata->capacity )
10213	            continue;
10214	
10215	         /* mark the items that are implied to zero by setting the current variable to the current value */
10216	         for( idx = firstidxs[val][probindex]; idx != 0; idx = nextidxs[idx] )
10217	         {
10218	            assert(0 < idx && idx < nzeroitems);
10219	            assert(0 <= zeroitems[idx] && zeroitems[idx] < consdata->nvars);
10220	            itemremoved[zeroitems[idx]] = TRUE;
10221	         }
10222	
10223	         /* calculate the residual cliqueweight sum */
10224	         cliqueweightsum = addweightsum; /* the previously added items are single-element cliques */
10225	         for( j = 0; j < consdata->nvars; ++j )
10226	         {
10227	            cliquenum = consdata->cliquepartition[j];
10228	            assert(0 <= cliquenum && cliquenum < consdata->nvars);
10229	            if( !itemremoved[j] )
10230	            {
10231	               if( !cliqueused[cliquenum] )
10232	               {
10233	                  cliqueweightsum += consdata->weights[j];
10234	                  cliqueused[cliquenum] = TRUE;
10235	                  tmpindices[tmp] = cliquenum;
10236	                  ++tmp;
10237	               }
10238	
10239	               if( cliqueweightsum >= consdata->capacity )
10240	                  break;
10241	            }
10242	         }
10243	
10244	         /* check if the weight of the variable/value can be increased */
10245	         if( cliqueweightsum < consdata->capacity )
10246	         {
10247	            SCIP_VAR* var;
10248	            SCIP_Longint weight;
10249	
10250	            /* insert the variable (with value TRUE) in the list of additional items */
10251	            assert(naddvars < 2*nbinvars);
10252	            var = binvars[probindex];
10253	            if( val == FALSE )
10254	            {
10255	               SCIP_CALL( SCIPgetNegatedVar(scip, var, &var) );
10256	            }
10257	            weight = consdata->capacity - cliqueweightsum;
10258	            addvars[naddvars] = var;
10259	            addweights[naddvars] = weight;
10260	            addweightsum += weight;
10261	            naddvars++;
10262	
10263	            SCIPdebugMsg(scip, "knapsack constraint <%s>: adding lifted item %" SCIP_LONGINT_FORMAT "<%s>\n",
10264	               SCIPconsGetName(cons), weight, SCIPvarGetName(var));
10265	         }
10266	
10267	         /* clear itemremoved */
10268	         for( idx = firstidxs[val][probindex]; idx != 0; idx = nextidxs[idx] )
10269	         {
10270	            assert(0 < idx && idx < nzeroitems);
10271	            assert(0 <= zeroitems[idx] && zeroitems[idx] < consdata->nvars);
10272	            itemremoved[zeroitems[idx]] = FALSE;
10273	         }
10274	         /* clear cliqueused */
10275	         for( --tmp; tmp >= 0; --tmp)
10276	            cliqueused[tmpindices[tmp]] = FALSE;
10277	      }
10278	   }
10279	
10280	   /* clear part of zeroweightsums */
10281	   for( --tmp3; tmp3 >= 0; --tmp3)
10282	      zeroweightsums[tmpboolindices3[tmp3]][tmpindices3[tmp3]] = 0;
10283	
10284	   /* clear rest of zeroweightsums and firstidxs */
10285	   for( --tmp2; tmp2 >= 0; --tmp2)
10286	   {
10287	      zeroweightsums[tmpboolindices2[tmp2]][tmpindices2[tmp2]] = 0;
10288	      firstidxs[tmpboolindices2[tmp2]][tmpindices2[tmp2]] = 0;
10289	   }
10290	
10291	   /* add all additional item weights */
10292	   for( i = 0; i < naddvars; ++i )
10293	   {
10294	      SCIP_CALL( addCoef(scip, cons, addvars[i], addweights[i]) );
10295	   }
10296	   *nchgcoefs += naddvars;
10297	
10298	   if( naddvars > 0 )
10299	   {
10300	      /* if new items were added, multiple entries of the same variable are possible and we have to clean up the constraint */
10301	      SCIP_CALL( mergeMultiples(scip, cons, cutoff) );
10302	   }
10303	
10304	   /* free temporary memory */
10305	   SCIPfreeBufferArray(scip, &addweights);
10306	   SCIPfreeBufferArray(scip, &addvars);
10307	   SCIPfreeBufferArray(scip, &tmpindices);
10308	   SCIPfreeBufferArray(scip, &tmpindices2);
10309	   SCIPfreeBufferArray(scip, &tmpindices3);
10310	   SCIPfreeBufferArray(scip, &tmpboolindices2);
10311	   SCIPfreeBufferArray(scip, &tmpboolindices3);
10312	   SCIPfreeBufferArray(scip, &nextidxs);
10313	   SCIPfreeBufferArray(scip, &zeroitems);
10314	   SCIPfreeBufferArray(scip, &liftcands[1]);
10315	   SCIPfreeBufferArray(scip, &liftcands[0]);
10316	
10317	   return SCIP_OKAY;
10318	}
10319	
10320	/** tightens item weights and capacity in presolving:
10321	 *  given a knapsack sum(wi*xi) <= capacity
10322	 *  (1) let weightsum := sum(wi)
10323	 *      if weightsum - wi < capacity:
10324	 *      - not using item i would make the knapsack constraint redundant
10325	 *      - wi and capacity can be changed to have the same redundancy effect and the same results for
10326	 *        fixing xi to zero or one, but with a reduced wi and tightened capacity to tighten the LP relaxation
10327	 *      - change coefficients:
10328	 *          wi'       := weightsum - capacity
10329	 *          capacity' := capacity - (wi - wi')
10330	 *  (2) increase weights from front to back(sortation is necessary) if there is no space left for another weight
10331	 *      - determine the four(can be adjusted) minimal weightsums of the knapsack, i.e. in increasing order
10332	 *        weights[nvars - 1], weights[nvars - 2], MIN(weights[nvars - 3], weights[nvars - 1] + weights[nvars - 2]),
10333	 *        MIN(MAX(weights[nvars - 3], weights[nvars - 1] + weights[nvars - 2]), weights[nvars - 4]), note that there
10334	 *        can be multiple times the same weight, this can be improved
10335	 *      - check if summing up a minimal weightsum with a big weight exceeds the capacity, then we can increase the big
10336	 *        weight, to capacity - lastmininmalweightsum, e.g. :
10337	 *        19x1 + 15x2 + 10x3 + 5x4 + 5x5 <= 19
10338	 *         ->  minimal weightsums: 5, 5, 10, 10
10339	 *         ->  15 + 5 > 19 => increase 15 to 19 - 0 = 19
10340	 *         ->  10 + 10 > 19 => increase 10 to 19 - 5 = 14, resulting in
10341	 *        19x1 + 19x2 + 14x3 + 5x4 + 5x5  <= 19
10342	 *  (3) let W(C) be the maximal weight of clique C,
10343	 *          cliqueweightsum := sum(W(C))
10344	 *      if cliqueweightsum - W(C) < capacity:
10345	 *      - not using any item of C would make the knapsack constraint redundant
10346	 *      - weights wi, i in C, and capacity can be changed to have the same redundancy effect and the same results for
10347	 *        fixing xi, i in C, to zero or one, but with a reduced wi and tightened capacity to tighten the LP relaxation
10348	 *      - change coefficients:
10349	 *          delta     := capacity - (cliqueweightsum - W(C))
10350	 *          wi'       := max(wi - delta, 0)
10351	 *          capacity' := capacity - delta
10352	 *      This rule has to add the used cliques in order to ensure they are enforced - otherwise, the reduction might
10353	 *      introduce infeasible solutions.
10354	 *  (4) for a clique C let C(xi == v) := C \ {j: xi == v -> xj == 0}),
10355	 *      let cliqueweightsum(xi == v) := sum(W(C(xi == v)))
10356	 *      if cliqueweightsum(xi == v) < capacity:
10357	 *      - fixing variable xi to v would make the knapsack constraint redundant
10358	 *      - the weight of the variable or its negation (depending on v) can be increased as long as it has the same
10359	 *        redundancy effect:
10360	 *          wi'       := capacity - cliqueweightsum(xi == v)
10361	 *      This rule can also be applied to binary variables not in the knapsack!
10362	 *  (5) if min{w} + wi > capacity:
10363	 *      - using item i would force to fix other items to zero
10364	 *      - wi can be increased to the capacity
10365	 */
10366	static
10367	SCIP_RETCODE tightenWeights(
10368	   SCIP*                 scip,               /**< SCIP data structure */
10369	   SCIP_CONS*            cons,               /**< knapsack constraint */
10370	   SCIP_PRESOLTIMING     presoltiming,       /**< current presolving timing */
10371	   int*                  nchgcoefs,          /**< pointer to count total number of changed coefficients */
10372	   int*                  nchgsides,          /**< pointer to count number of side changes */
10373	   int*                  naddconss,          /**< pointer to count number of added constraints */
10374	   int*                  ndelconss,          /**< pointer to count number of deleted constraints */
10375	   SCIP_Bool*            cutoff              /**< pointer to store whether the node can be cut off */
10376	   )
10377	{
10378	   SCIP_CONSHDLRDATA* conshdlrdata;
10379	   SCIP_CONSDATA* consdata;
10380	   SCIP_Longint* weights;
10381	   SCIP_Longint sumcoef;
10382	   SCIP_Longint capacity;
10383	   SCIP_Longint newweight;
10384	   SCIP_Longint maxweight;
10385	   SCIP_Longint minweight;
10386	   SCIP_Bool sumcoefcase = FALSE;
10387	   int startpos;
10388	   int backpos;
10389	   int nvars;
10390	   int pos;
10391	   int k;
10392	   int i;
10393	
10394	   assert(nchgcoefs != NULL);
10395	   assert(nchgsides != NULL);
10396	   assert(!SCIPconsIsModifiable(cons));
10397	
10398	   conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
10399	   assert(conshdlrdata != NULL);
10400	
10401	   consdata = SCIPconsGetData(cons);
10402	   assert(consdata != NULL);
10403	   assert(consdata->row == NULL); /* we are in presolve, so no LP row exists */
10404	   assert(consdata->onesweightsum == 0); /* all fixed variables should have been removed */
10405	   assert(consdata->weightsum > consdata->capacity); /* otherwise, the constraint is redundant */
10406	   assert(consdata->nvars > 0);
10407	
10408	   SCIP_CALL( mergeMultiples(scip, cons, cutoff) );
10409	   if( *cutoff )
10410	      return SCIP_OKAY;
10411	
10412	   /* apply rule (1) */
10413	   if( (presoltiming & SCIP_PRESOLTIMING_FAST) != 0 )
10414	   {
10415	      do
10416	      {
10417	         assert(consdata->merged);
10418	
10419	         /* sort items, s.t. the heaviest one is in the first position */
10420	         sortItems(consdata);
10421	
10422	         for( i = 0; i < consdata->nvars; ++i )
10423	         {
10424	            SCIP_Longint weight;
10425	
10426	            weight = consdata->weights[i];
10427	            if( consdata->weightsum - weight < consdata->capacity )
10428	            {
10429	               newweight = consdata->weightsum - consdata->capacity;
10430	               consdataChgWeight(consdata, i, newweight);
10431	               consdata->capacity -= (weight - newweight);
10432	               (*nchgcoefs)++;
10433	               (*nchgsides)++;
10434	               assert(!consdata->sorted);
10435	               SCIPdebugMsg(scip, "knapsack constraint <%s>: changed weight of <%s> from %" SCIP_LONGINT_FORMAT " to %" SCIP_LONGINT_FORMAT ", capacity from %" SCIP_LONGINT_FORMAT " to %" SCIP_LONGINT_FORMAT "\n",
10436	                  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), weight, newweight,
10437	                  consdata->capacity + (weight-newweight), consdata->capacity);
10438	            }
10439	            else
10440	               break;
10441	         }
10442	      }
10443	      while( !consdata->sorted && consdata->weightsum > consdata->capacity );
10444	   }
10445	
10446	   /* check for redundancy */
10447	   if( consdata->weightsum <= consdata->capacity )
10448	      return SCIP_OKAY;
10449	
10450	   pos = 0;
10451	   while( pos < consdata->nvars && consdata->weights[pos] == consdata->capacity )
10452	      ++pos;
10453	
10454	   sumcoef = 0;
10455	   weights = consdata->weights;
10456	   nvars = consdata->nvars;
10457	   capacity = consdata->capacity;
10458	
10459	   if( (presoltiming & (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_MEDIUM)) != 0 &&
10460	      pos < nvars && weights[pos] + weights[pos + 1] > capacity )
10461	   {
10462	      /* further reductions using the next possible coefficient sum
10463	       *
10464	       * e.g. 19x1 + 15x2 + 10x3 + 5x4 + 5x5 <= 19  <=>  19x1 + 19x2 + 14x3 + 5x4 + 5x5  <= 19
10465	       */
10466	      /* @todo loop for "k" can be extended, same coefficient when determine next sumcoef can be left out */
10467	      for( k = 0; k < 4; ++k )
10468	      {
10469	         newweight = capacity - sumcoef;
10470	
10471	         /* determine next minimal coefficient sum */
10472	         switch( k )
10473	         {
10474	         case 0:
10475	            sumcoef = weights[nvars - 1];
10476	            backpos = nvars - 1;
10477	            break;
10478	         case 1:
10479	            sumcoef = weights[nvars - 2];
10480	            backpos = nvars - 2;
10481	            break;
10482	         case 2:
10483	            if( weights[nvars - 3] < weights[nvars - 1] + weights[nvars - 2] )
10484	            {
10485	               sumcoefcase = TRUE;
10486	               sumcoef = weights[nvars - 3];
10487	               backpos = nvars - 3;
10488	            }
10489	            else
10490	            {
10491	               sumcoefcase = FALSE;
10492	               sumcoef = weights[nvars - 1] + weights[nvars - 2];
10493	               backpos = nvars - 2;
10494	            }
10495	            break;
10496	         default:
10497	            assert(k == 3);
10498	            if( sumcoefcase )
10499	            {
10500	               if( weights[nvars - 4] < weights[nvars - 1] + weights[nvars - 2] )
10501	               {
10502	                  sumcoef = weights[nvars - 4];
10503	                  backpos = nvars - 4;
10504	               }
10505	               else
10506	               {
10507	                  sumcoef = weights[nvars - 1] + weights[nvars - 2];
10508	                  backpos = nvars - 2;
10509	               }
10510	            }
10511	            else
10512	            {
10513	               sumcoef = weights[nvars - 3];
10514	               backpos = nvars - 3;
10515	            }
10516	            break;
10517	         }
10518	
10519	         if( backpos <= pos )
10520	            break;
10521	
10522	         /* tighten next coefficients that, paired with the current small coefficient, exceed the capacity */
10523	         maxweight = weights[pos];
10524	         startpos = pos;
10525	         while( 2 * maxweight > capacity && maxweight + sumcoef > capacity )
10526	         {
10527	            assert(newweight > weights[pos]);
10528	
10529	            SCIPdebugMsg(scip, "in constraint <%s> changing weight %" SCIP_LONGINT_FORMAT " to %" SCIP_LONGINT_FORMAT "\n",
10530	               SCIPconsGetName(cons), maxweight, newweight);
10531	
10532	            consdataChgWeight(consdata, pos, newweight);
10533	
10534	            ++pos;
10535	            assert(pos < nvars);
10536	
10537	            maxweight = weights[pos];
10538	
10539	            if( backpos <= pos )
10540	               break;
10541	         }
10542	         (*nchgcoefs) += (pos - startpos);
10543	
10544	         /* skip unchangable weights */
10545	         while( pos < nvars && weights[pos] + sumcoef == capacity )
10546	            ++pos;
10547	
10548	         /* check special case were there is only one weight left to tighten
10549	          *
10550	          * e.g.  95x1 + 59x2 + 37x3 + 36x4 <= 95 (37 > 36)
10551	          *
10552	          *   =>  95x1 + 59x2 + 59x3 + 36x4 <= 95
10553	          *
10554	          *       197x1 + 120x2 + 77x3 + 10x4 <= 207 (here we cannot tighten the coefficient further)
10555	          */
10556	         if( pos + 1 == backpos && weights[pos] > sumcoef &&
10557	            ((k == 0) || (k == 1 && weights[nvars - 1] + sumcoef + weights[pos] > capacity)) )
10558	         {
10559	            newweight = capacity - sumcoef;
10560	            assert(newweight > weights[pos]);
10561	
10562	            SCIPdebugMsg(scip, "in constraint <%s> changing weight %" SCIP_LONGINT_FORMAT " to %" SCIP_LONGINT_FORMAT "\n",
10563	               SCIPconsGetName(cons), maxweight, newweight);
10564	
10565	            consdataChgWeight(consdata, pos, newweight);
10566	
10567	            break;
10568	         }
10569	
10570	         if( backpos <= pos )
10571	            break;
10572	      }
10573	   }
10574	
10575	   /* apply rule (2) (don't apply, if the knapsack has too many items for applying this costly method) */
10576	   if( (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
10577	   {
10578	      if( conshdlrdata->disaggregation && consdata->nvars - pos <= MAX_USECLIQUES_SIZE && consdata->nvars >= 2 &&
10579	         pos > 0 && (SCIP_Longint)consdata->nvars - pos <= consdata->capacity &&
10580	         consdata->weights[pos - 1] == consdata->capacity && (pos == consdata->nvars || consdata->weights[pos] == 1) )
10581	      {
10582	         SCIP_VAR** clqvars;
10583	         SCIP_CONS* cliquecons;
10584	         char name[SCIP_MAXSTRLEN];
10585	         int* clqpart;
10586	         int nclqvars;
10587	         int nclq;
10588	         int len;
10589	         int c;
10590	         int w;
10591	
10592	         assert(!SCIPconsIsDeleted(cons));
10593	
10594	         if( pos == consdata->nvars )
10595	         {
10596	            SCIPdebugMsg(scip, "upgrading knapsack constraint <%s> to a set-packing constraint", SCIPconsGetName(cons));
10597	
10598	            SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, SCIPconsGetName(cons), pos, consdata->vars,
10599	                  SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
10600	                  SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
10601	                  SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons),
10602	                  SCIPconsIsStickingAtNode(cons)) );
10603	
10604	            SCIP_CALL( SCIPaddCons(scip, cliquecons) );
10605	            SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
10606	            ++(*naddconss);
10607	
10608	            /* delete old constraint */
10609	            SCIP_CALL( SCIPdelCons(scip, cons) );
10610	            ++(*ndelconss);
10611	
10612	            return SCIP_OKAY;
10613	         }
10614	
10615	         len = consdata->nvars - pos;
10616	
10617	         /* allocate temporary memory */
10618	         SCIP_CALL( SCIPallocBufferArray(scip, &clqpart, len) );
10619	
10620	         /* calculate clique partition */
10621	         SCIP_CALL( SCIPcalcCliquePartition(scip, &(consdata->vars[pos]), len, clqpart, &nclq) );
10622	         assert(nclq <= len);
10623	
10624	#ifndef NDEBUG
10625	         /* clique numbers must be at least as high as the index */
10626	         for( w = 0; w < nclq; ++w )
10627	            assert(clqpart[w] <= w);
10628	#endif
10629	
10630	         SCIPdebugMsg(scip, "Disaggregating knapsack constraint <%s> due to clique information.\n", SCIPconsGetName(cons));
10631	
10632	         /* allocate temporary memory */
10633	         SCIP_CALL( SCIPallocBufferArray(scip, &clqvars, pos + len - nclq + 1) );
10634	
10635	         /* copy corresponding variables with big coefficients */
10636	         for( w = pos - 1; w >= 0; --w )
10637	            clqvars[w] = consdata->vars[w];
10638	
10639	         /* create for each clique a set-packing constraint */
10640	         for( c = 0; c < nclq; ++c )
10641	         {
10642	            nclqvars = pos;
10643	
10644	            for( w = c; w < len; ++w )
10645	            {
10646	               if( clqpart[w] == c )
10647	               {
10648	                  assert(nclqvars < pos + len - nclq + 1);
10649	                  clqvars[nclqvars] = consdata->vars[w + pos];
10650	                  ++nclqvars;
10651	               }
10652	            }
10653	
10654	            assert(nclqvars > 1);
10655	
10656	            (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%" SCIP_LONGINT_FORMAT "_%d", SCIPconsGetName(cons), consdata->capacity, c);
10657	            SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, nclqvars, clqvars,
10658	                  SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
10659	                  SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
10660	                  SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons),
10661	                  SCIPconsIsStickingAtNode(cons)) );
10662	            SCIPdebugMsg(scip, " -> adding clique constraint: ");
10663	            SCIPdebugPrintCons(scip, cliquecons, NULL);
10664	            SCIP_CALL( SCIPaddCons(scip, cliquecons) );
10665	            SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
10666	            ++(*naddconss);
10667	         }
10668	
10669	         /* delete old constraint */
10670	         SCIP_CALL( SCIPdelCons(scip, cons) );
10671	         ++(*ndelconss);
10672	
10673	         SCIPfreeBufferArray(scip, &clqvars);
10674	         SCIPfreeBufferArray(scip, &clqpart);
10675	
10676	         return SCIP_OKAY;
10677	      }
10678	      else if( consdata->nvars <= MAX_USECLIQUES_SIZE || (consdata->cliquepartitioned && consdata->ncliques <= MAX_USECLIQUES_SIZE) )
10679	      {
10680	         SCIP_Longint* maxcliqueweights;
10681	         SCIP_Longint* newweightvals;
10682	         int* newweightidxs;
10683	         SCIP_Longint cliqueweightsum;
10684	
10685	         SCIP_CALL( SCIPallocBufferArray(scip, &maxcliqueweights, consdata->nvars) );
10686	         SCIP_CALL( SCIPallocBufferArray(scip, &newweightvals, consdata->nvars) );
10687	         SCIP_CALL( SCIPallocBufferArray(scip, &newweightidxs, consdata->nvars) );
10688	
10689	         /* repeat as long as changes have been applied */
10690	         do
10691	         {
10692	            int ncliques;
10693	            int cliquenum;
10694	            SCIP_Bool zeroweights;
10695	
10696	            assert(consdata->merged);
10697	
10698	            /* sort items, s.t. the heaviest one is in the first position */
10699	            sortItems(consdata);
10700	
10701	            /* calculate a clique partition */
10702	            SCIP_CALL( calcCliquepartition(scip, conshdlrdata, consdata, TRUE, FALSE) );
10703	
10704	            /* if there are only single element cliques, rule (2) is equivalent to rule (1) */
10705	            if( consdata->cliquepartition[consdata->nvars - 1] == consdata->nvars - 1 )
10706	               break;
10707	
10708	            /* calculate the maximal weight of the cliques and store the clique type */
10709	            cliqueweightsum = 0;
10710	            ncliques = 0;
10711	
10712	            for( i = 0; i < consdata->nvars; ++i )
10713	            {
10714	               SCIP_Longint weight;
10715	
10716	               cliquenum = consdata->cliquepartition[i];
10717	               assert(0 <= cliquenum && cliquenum <= ncliques);
10718	
10719	               weight = consdata->weights[i];
10720	               assert(weight > 0);
10721	
10722	               if( cliquenum == ncliques )
10723	               {
10724	                  maxcliqueweights[ncliques] = weight;
10725	                  cliqueweightsum += weight;
10726	                  ++ncliques;
10727	               }
10728	
10729	               assert(maxcliqueweights[cliquenum] >= weight);
10730	            }
10731	
10732	            /* apply rule on every clique */
10733	            zeroweights = FALSE;
10734	            for( i = 0; i < ncliques; ++i )
10735	            {
10736	               SCIP_Longint delta;
10737	
10738	               delta = consdata->capacity - (cliqueweightsum - maxcliqueweights[i]);
10739	               if( delta > 0 )
10740	               {
10741	                  SCIP_Longint newcapacity;
10742	#ifndef NDEBUG
10743	                  SCIP_Longint newmincliqueweight;
10744	#endif
10745	                  SCIP_Longint newminweightsuminclique;
10746	                  SCIP_Bool forceclique;
10747	                  int nnewweights;
10748	                  int j;
10749	
10750	                  SCIPdebugMsg(scip, "knapsack constraint <%s>: weights of clique %d (maxweight: %" SCIP_LONGINT_FORMAT ") can be tightened: cliqueweightsum=%" SCIP_LONGINT_FORMAT ", capacity=%" SCIP_LONGINT_FORMAT " -> delta: %" SCIP_LONGINT_FORMAT "\n",
10751	                     SCIPconsGetName(cons), i, maxcliqueweights[i], cliqueweightsum, consdata->capacity, delta);
10752	                  newcapacity = consdata->capacity - delta;
10753	                  forceclique = FALSE;
10754	                  nnewweights = 0;
10755	#ifndef NDEBUG
10756	                  newmincliqueweight = newcapacity + 1;
10757	                  for( j = 0; j < i; ++j )
10758	                     assert(consdata->cliquepartition[j] < i); /* no element j < i can be in clique i */
10759	#endif
10760	                  for( j = i; j < consdata->nvars; ++j )
10761	                  {
10762	                     if( consdata->cliquepartition[j] == i )
10763	                     {
10764	                        newweight = consdata->weights[j] - delta;
10765	                        newweight = MAX(newweight, 0);
10766	
10767	                        /* cache the new weight */
10768	                        assert(nnewweights < consdata->nvars);
10769	                        newweightvals[nnewweights] = newweight;
10770	                        newweightidxs[nnewweights] = j;
10771	                        nnewweights++;
10772	
10773	#ifndef NDEBUG
10774	                        assert(newweight <= newmincliqueweight); /* items are sorted by non-increasing weight! */
10775	                        newmincliqueweight = newweight;
10776	#endif
10777	                     }
10778	                  }
10779	
10780	                  /* check if our clique information results out of this knapsack constraint and if so check if we would loose the clique information */
10781	                  if( nnewweights > 1 )
10782	                  {
10783	#ifndef NDEBUG
10784	                     j = newweightidxs[nnewweights - 2];
10785	                     assert(0 <= j && j < consdata->nvars);
10786	                     assert(consdata->cliquepartition[j] == i);
10787	                     j = newweightidxs[nnewweights - 1];
10788	                     assert(0 <= j && j < consdata->nvars);
10789	                     assert(consdata->cliquepartition[j] == i);
10790	#endif
10791	
10792	                     newminweightsuminclique = newweightvals[nnewweights - 2];
10793	                     newminweightsuminclique += newweightvals[nnewweights - 1];
10794	
10795	                     /* check if these new two minimal weights both fit into the knapsack;
10796	                      * if this is true, we have to add a clique constraint in order to enforce the clique
10797	                      * (otherwise, the knapsack might have been one of the reasons for the clique, and the weight
10798	                      * reduction might be infeasible, i.e., allows additional solutions)
10799	                      */
10800	                     if( newminweightsuminclique <= newcapacity )
10801	                        forceclique = TRUE;
10802	                  }
10803	
10804	                  /* check if we really want to apply the change */
10805	                  if( conshdlrdata->disaggregation || !forceclique )
10806	                  {
10807	                     SCIPdebugMsg(scip, " -> change capacity from %" SCIP_LONGINT_FORMAT " to %" SCIP_LONGINT_FORMAT " (forceclique:%u)\n",
10808	                        consdata->capacity, newcapacity, forceclique);
10809	                     consdata->capacity = newcapacity;
10810	                     (*nchgsides)++;
10811	
10812	                     for( k = 0; k < nnewweights; ++k )
10813	                     {
10814	                        j = newweightidxs[k];
10815	                        assert(0 <= j && j < consdata->nvars);
10816	                        assert(consdata->cliquepartition[j] == i);
10817	
10818	                        /* apply the weight change */
10819	                        SCIPdebugMsg(scip, " -> change weight of <%s> from %" SCIP_LONGINT_FORMAT " to %" SCIP_LONGINT_FORMAT "\n",
10820	                           SCIPvarGetName(consdata->vars[j]), consdata->weights[j], newweightvals[k]);
10821	                        consdataChgWeight(consdata, j, newweightvals[k]);
10822	                        (*nchgcoefs)++;
10823	                        assert(!consdata->sorted);
10824	                        zeroweights = zeroweights || (newweightvals[k] == 0);
10825	                     }
10826	                     /* if before the weight update at least one pair of weights did not fit into the knapsack and now fits,
10827	                      * we have to make sure, the clique is enforced - the clique might have been constructed partially from
10828	                      * this constraint, and by reducing the weights, this clique information is not contained anymore in the
10829	                      * knapsack constraint
10830	                      */
10831	                     if( forceclique )
10832	                     {
10833	                        SCIP_CONS* cliquecons;
10834	                        char name[SCIP_MAXSTRLEN];
10835	                        SCIP_VAR** cliquevars;
10836	
10837	                        SCIP_CALL( SCIPallocBufferArray(scip, &cliquevars, nnewweights) );
10838	                        for( k = 0; k < nnewweights; ++k )
10839	                           cliquevars[k] = consdata->vars[newweightidxs[k]];
10840	
10841	                        (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_clq_%" SCIP_LONGINT_FORMAT "_%d", SCIPconsGetName(cons), consdata->capacity, i);
10842	                        SCIP_CALL( SCIPcreateConsSetpack(scip, &cliquecons, name, nnewweights, cliquevars,
10843	                              SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
10844	                              SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
10845	                              SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons),
10846	                              SCIPconsIsStickingAtNode(cons)) );
10847	                        SCIPdebugMsg(scip, " -> adding clique constraint: ");
10848	                        SCIPdebugPrintCons(scip, cliquecons, NULL);
10849	                        SCIP_CALL( SCIPaddCons(scip, cliquecons) );
10850	                        SCIP_CALL( SCIPreleaseCons(scip, &cliquecons) );
10851	                        SCIPfreeBufferArray(scip, &cliquevars);
10852	                        (*naddconss)++;
10853	                     }
10854	                  }
10855	               }
10856	            }
10857	            if( zeroweights )
10858	            {
10859	               SCIP_CALL( removeZeroWeights(scip, cons) );
10860	            }
10861	         }
10862	         while( !consdata->sorted && consdata->weightsum > consdata->capacity );
10863	
10864	         /* free temporary memory */
10865	         SCIPfreeBufferArray(scip, &newweightidxs);
10866	         SCIPfreeBufferArray(scip, &newweightvals);
10867	         SCIPfreeBufferArray(scip, &maxcliqueweights);
10868	
10869	         /* check for redundancy */
10870	         if( consdata->weightsum <= consdata->capacity )
10871	            return SCIP_OKAY;
10872	      }
10873	   }
10874	
10875	   /* apply rule (3) */
10876	   if( (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
10877	   {
10878	      SCIP_CALL( tightenWeightsLift(scip, cons, nchgcoefs, cutoff) );
10879	   }
10880	
10881	   /* check for redundancy */
10882	   if( consdata->weightsum <= consdata->capacity )
10883	      return SCIP_OKAY;
10884	
10885	   if( (presoltiming & SCIP_PRESOLTIMING_FAST) != 0 )
10886	   {
10887	      /* apply rule (4) (all but smallest weight) */
10888	      assert(consdata->merged);
10889	      sortItems(consdata);
10890	      minweight = consdata->weights[consdata->nvars-1];
10891	      for( i = 0; i < consdata->nvars-1; ++i )
10892	      {
10893	         SCIP_Longint weight;
10894	
10895	         weight = consdata->weights[i];
10896	         assert(weight >= minweight);
10897	         if( minweight + weight > consdata->capacity )
10898	         {
10899	            if( weight < consdata->capacity )
10900	            {
10901	               SCIPdebugMsg(scip, "knapsack constraint <%s>: changed weight of <%s> from %" SCIP_LONGINT_FORMAT " to %" SCIP_LONGINT_FORMAT "\n",
10902	                  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), weight, consdata->capacity);
10903	               assert(consdata->sorted);
10904	               consdataChgWeight(consdata, i, consdata->capacity); /* this does not destroy the weight order! */
10905	               assert(i == 0 || consdata->weights[i-1] >= consdata->weights[i]);
10906	               consdata->sorted = TRUE;
10907	               (*nchgcoefs)++;
10908	            }
10909	         }
10910	         else
10911	            break;
10912	      }
10913	
10914	      /* apply rule (5) (smallest weight) */
10915	      if( consdata->nvars >= 2 )
10916	      {
10917	         SCIP_Longint weight;
10918	
10919	         minweight = consdata->weights[consdata->nvars-2];
10920	         weight = consdata->weights[consdata->nvars-1];
10921	         assert(minweight >= weight);
10922	         if( minweight + weight > consdata->capacity && weight < consdata->capacity )
10923	         {
10924	            SCIPdebugMsg(scip, "knapsack constraint <%s>: changed weight of <%s> from %" SCIP_LONGINT_FORMAT " to %" SCIP_LONGINT_FORMAT "\n",
10925	               SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[consdata->nvars-1]), weight, consdata->capacity);
10926	            assert(consdata->sorted);
10927	            consdataChgWeight(consdata, consdata->nvars-1, consdata->capacity); /* this does not destroy the weight order! */
10928	            assert(minweight >= consdata->weights[consdata->nvars-1]);
10929	            consdata->sorted = TRUE;
10930	            (*nchgcoefs)++;
10931	         }
10932	      }
10933	   }
10934	
10935	   return SCIP_OKAY;
10936	}
10937	
10938	
10939	#ifdef SCIP_DEBUG
10940	static
10941	void printClique(
10942	   SCIP_VAR**            cliquevars,
10943	   int                   ncliquevars
10944	   )
10945	{
10946	   int b;
10947	   SCIPdebugMessage("adding new Clique: ");
10948	   for( b = 0; b < ncliquevars; ++b )
10949	      SCIPdebugPrintf("%s ", SCIPvarGetName(cliquevars[b]));
10950	   SCIPdebugPrintf("\n");
10951	}
10952	#endif
10953	
10954	/** adds negated cliques of the knapsack constraint to the global clique table */
10955	static
10956	SCIP_RETCODE addNegatedCliques(
10957	   SCIP*const            scip,               /**< SCIP data structure */
10958	   SCIP_CONS*const       cons,               /**< knapsack constraint */
10959	   SCIP_Bool*const       cutoff,             /**< pointer to store whether the node can be cut off */
10960	   int*const             nbdchgs             /**< pointer to count the number of performed bound changes */
10961	   )
10962	{
10963	   SCIP_CONSDATA* consdata;
10964	   SCIP_CONSHDLRDATA* conshdlrdata;
10965	   SCIP_VAR** poscliquevars;
10966	   SCIP_VAR** cliquevars;
10967	   SCIP_Longint* maxweights;
10968	   SCIP_Longint* gainweights;
10969	   int* gaincliquepartition;
10970	   SCIP_Bool* cliqueused;
10971	   SCIP_Longint minactduetonegcliques;
10972	   SCIP_Longint freecapacity;
10973	   SCIP_Longint lastweight;
10974	   SCIP_Longint beforelastweight;
10975	   int nposcliquevars;
10976	   int ncliquevars;
10977	   int nvars;
10978	   int nnegcliques;
10979	   int lastcliqueused;
10980	   int thisnbdchgs;
10981	   int v;
10982	   int w;
10983	
10984	   assert(scip != NULL);
10985	   assert(cons != NULL);
10986	   assert(cutoff != NULL);
10987	   assert(nbdchgs != NULL);
10988	
10989	   *cutoff = FALSE;
10990	
10991	   consdata = SCIPconsGetData(cons);
10992	   assert(consdata != NULL);
10993	
10994	   nvars = consdata->nvars;
10995	
10996	   /* check whether the cliques have already been added */
10997	   if( consdata->cliquesadded || nvars == 0 )
10998	      return SCIP_OKAY;
10999	
11000	   /* make sure, the items are merged */
11001	   SCIP_CALL( mergeMultiples(scip, cons, cutoff) );
11002	   if( *cutoff )
11003	      return SCIP_OKAY;
11004	
11005	   /* make sure, items are sorted by non-increasing weight */
11006	   sortItems(consdata);
11007	
11008	   assert(consdata->merged);
11009	
11010	   conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
11011	   assert(conshdlrdata != NULL);
11012	
11013	   /* calculate a clique partition */
11014	   SCIP_CALL( calcCliquepartition(scip, conshdlrdata, consdata, FALSE, TRUE) );
11015	   nnegcliques = consdata->nnegcliques;
11016	
11017	   /* if we have no negated cliques, stop */
11018	   if( nnegcliques == nvars )
11019	      return SCIP_OKAY;
11020	
11021	   /* get temporary memory */
11022	   SCIP_CALL( SCIPallocBufferArray(scip, &poscliquevars, nvars) );
11023	   SCIP_CALL( SCIPallocBufferArray(scip, &cliquevars, nvars) );
11024	   SCIP_CALL( SCIPallocClearBufferArray(scip, &gainweights, nvars) );
11025	   SCIP_CALL( SCIPallocBufferArray(scip, &gaincliquepartition, nvars) );
11026	   SCIP_CALL( SCIPallocBufferArray(scip, &maxweights, nnegcliques) );
11027	   SCIP_CALL( SCIPallocClearBufferArray(scip, &cliqueused, nnegcliques) );
11028	
11029	   nnegcliques = 0;
11030	   minactduetonegcliques = 0;
11031	
11032	   /* determine maximal weights for all negated cliques and calculate minimal weightsum due to negated cliques */
11033	   for( v = 0; v < nvars; ++v )
11034	   {
11035	      assert(0 <= consdata->negcliquepartition[v] && consdata->negcliquepartition[v] <= nnegcliques);
11036	      assert(consdata->weights[v] > 0);
11037	
11038	      if( consdata->negcliquepartition[v] == nnegcliques )
11039	      {
11040	         nnegcliques++;
11041	         maxweights[consdata->negcliquepartition[v]] = consdata->weights[v];
11042	      }
11043	      else
11044	         minactduetonegcliques += consdata->weights[v];
11045	   }
11046	
11047	   nposcliquevars = 0;
11048	
11049	   /* add cliques, using negated cliques information */
11050	   if( minactduetonegcliques > 0 )
11051	   {
11052	      /* free capacity is the rest of not used capacity if the smallest amount of weights due to negated cliques are used */
11053	      freecapacity = consdata->capacity - minactduetonegcliques;
11054	
11055	      SCIPdebugPrintCons(scip, cons, NULL);
11056	      SCIPdebugMsg(scip, "Try to add negated cliques in knapsack constraint handler for constraint %s; capacity = %" SCIP_LONGINT_FORMAT ", minactivity(due to neg. cliques) = %" SCIP_LONGINT_FORMAT ", freecapacity = %" SCIP_LONGINT_FORMAT ".\n",
11057	         SCIPconsGetName(cons), consdata->capacity, minactduetonegcliques, freecapacity);
11058	
11059	      /* calculate possible gain by switching chosen items in negated cliques */
11060	      for( v = 0; v < nvars; ++v )
11061	      {
11062	         if( !cliqueused[consdata->negcliquepartition[v]] )
11063	         {
11064	            cliqueused[consdata->negcliquepartition[v]] = TRUE;
11065	            for( w = v + 1; w < nvars; ++w )
11066	            {
11067	               /* if we would take the biggest weight instead of another what would we gain, take weight[v] instead of
11068	                * weight[w] (which are both in a negated clique) */
11069	               if( consdata->negcliquepartition[v] == consdata->negcliquepartition[w]
11070	                  && consdata->weights[v] > consdata->weights[w] )
11071	               {
11072	                  poscliquevars[nposcliquevars] = consdata->vars[w];
11073	                  gainweights[nposcliquevars] = maxweights[consdata->negcliquepartition[v]] - consdata->weights[w];
11074	                  gaincliquepartition[nposcliquevars] = consdata->negcliquepartition[v];
11075	                  ++nposcliquevars;
11076	               }
11077	            }
11078	         }
11079	      }
11080	
11081	      /* try to create negated cliques */
11082	      if( nposcliquevars > 0 )
11083	      {
11084	         /* sort possible gain per substitution of the clique members */
11085	         SCIPsortDownLongPtrInt(gainweights,(void**) poscliquevars, gaincliquepartition, nposcliquevars);
11086	
11087	         for( v = 0; v < nposcliquevars; ++v )
11088	         {
11089	            SCIP_CALL( SCIPgetNegatedVar(scip, poscliquevars[v], &cliquevars[0]) );
11090	            ncliquevars = 1;
11091	            lastweight = gainweights[v];
11092	            beforelastweight = -1;
11093	            lastcliqueused = gaincliquepartition[v];
11094	            /* clear cliqueused to get an unused array */
11095	            BMSclearMemoryArray(cliqueused, nnegcliques);
11096	            cliqueused[gaincliquepartition[v]] = TRUE;
11097	
11098	            /* taking bigger weights make the knapsack redundant so we will create cliques, only take items which are not
11099	             * in the same negated clique and by taking two of them would exceed the free capacity */
11100	            for( w = v + 1; w < nposcliquevars && !cliqueused[gaincliquepartition[w]] && gainweights[w] + lastweight > freecapacity; ++w )
11101	            {
11102	               beforelastweight = lastweight;
11103	               lastweight = gainweights[w];
11104	               lastcliqueused = gaincliquepartition[w];
11105	               cliqueused[gaincliquepartition[w]] = TRUE;
11106	               SCIP_CALL( SCIPgetNegatedVar(scip, poscliquevars[w], &cliquevars[ncliquevars]) );
11107	               ++ncliquevars;
11108	            }
11109	
11110	            if( ncliquevars > 1 )
11111	            {
11112	               SCIPdebug( printClique(cliquevars, ncliquevars) );
11113	               assert(beforelastweight > 0);
11114	               /* add the clique to the clique table */
11115	               /* this really happens, e.g., on enigma.mps from the short test set */
11116	               SCIP_CALL( SCIPaddClique(scip, cliquevars, NULL, ncliquevars, FALSE, cutoff, &thisnbdchgs) );
11117	               if( *cutoff )
11118	                  goto TERMINATE;
11119	               *nbdchgs += thisnbdchgs;
11120	
11121	               /* reset last used clique to get slightly different cliques */
11122	               cliqueused[lastcliqueused] = FALSE;
11123	
11124	               /* try to replace the last item in the clique by a different item to obtain a slightly different clique */
11125	               for( ++w; w < nposcliquevars && !cliqueused[gaincliquepartition[w]] && beforelastweight + gainweights[w] > freecapacity; ++w )
11126	               {
11127	                  SCIP_CALL( SCIPgetNegatedVar(scip, poscliquevars[w], &cliquevars[ncliquevars - 1]) );
11128	                  SCIPdebug( printClique(cliquevars, ncliquevars) );
11129	                  SCIP_CALL( SCIPaddClique(scip, cliquevars, NULL, ncliquevars, FALSE, cutoff, &thisnbdchgs) );
11130	                  if( *cutoff )
11131	                     goto TERMINATE;
11132	                  *nbdchgs += thisnbdchgs;
11133	               }
11134	            }
11135	         }
11136	      }
11137	   }
11138	
11139	 TERMINATE:
11140	   /* free temporary memory */
11141	   SCIPfreeBufferArray(scip, &cliqueused);
11142	   SCIPfreeBufferArray(scip, &maxweights);
11143	   SCIPfreeBufferArray(scip, &gaincliquepartition);
11144	   SCIPfreeBufferArray(scip, &gainweights);
11145	   SCIPfreeBufferArray(scip, &cliquevars);
11146	   SCIPfreeBufferArray(scip, &poscliquevars);
11147	
11148	   return SCIP_OKAY;
11149	}
11150	
11151	/** greedy clique detection by considering weights and capacity
11152	 *
11153	 *  greedily detects cliques by first sorting the items by decreasing weights (optional) and then collecting greedily
11154	 *  1) neighboring items which exceed the capacity together => one clique
11155	 *  2) looping through the remaining items and finding the largest set of preceding items to build a clique => possibly many more cliques
11156	 */
11157	static
11158	SCIP_RETCODE greedyCliqueAlgorithm(
11159	   SCIP*const            scip,               /**< SCIP data structure */
11160	   SCIP_VAR**            items,              /**< array of variable items */
11161	   SCIP_Longint*         weights,            /**< weights of the items */
11162	   int                   nitems,             /**< the number of items */
11163	   SCIP_Longint          capacity,           /**< maximum free capacity of the knapsack */
11164	   SCIP_Bool             sorteditems,        /**< are the items sorted by their weights nonincreasing? */
11165	   SCIP_Real             cliqueextractfactor,/**< lower clique size limit for greedy clique extraction algorithm (relative to largest clique) */
11166	   SCIP_Bool*const       cutoff,             /**< pointer to store whether the node can be cut off */
11167	   int*const             nbdchgs             /**< pointer to count the number of performed bound changes */
11168	   )
11169	{
11170	   SCIP_Longint lastweight;
11171	   int ncliquevars;
11172	   int i;
11173	   int thisnbdchgs;
11174	
11175	   if( nitems <= 1 )
11176	      return SCIP_OKAY;
11177	
11178	   /* sort possible gain per substitution of the clique members */
11179	   if( ! sorteditems )
11180	      SCIPsortDownLongPtr(weights,(void**) items, nitems);
11181	
11182	   ncliquevars = 1;
11183	   lastweight = weights[0];
11184	
11185	   /* taking these two weights together violates the knapsack => include into clique */
11186	   for( i = 1; i < nitems && weights[i] + lastweight > capacity; ++i )
11187	   {
11188	      lastweight = weights[i];
11189	      ++ncliquevars;
11190	   }
11191	
11192	   if( ncliquevars > 1 )
11193	   {
11194	      SCIP_Longint compareweight;
11195	      SCIP_VAR** cliquevars;
11196	      int compareweightidx;
11197	      int minclqsize;
11198	      int nnzadded;
11199	
11200	      /* add the clique to the clique table */
11201	      SCIPdebug( printClique(items, ncliquevars) );
11202	      SCIP_CALL( SCIPaddClique(scip, items, NULL, ncliquevars, FALSE, cutoff, &thisnbdchgs) );
11203	
11204	      if( *cutoff )
11205	         return SCIP_OKAY;
11206	
11207	      *nbdchgs += thisnbdchgs;
11208	      nnzadded = ncliquevars;
11209	
11210	      /* no more cliques to be found (don't know if this can actually happen, since the knapsack could be replaced by a set-packing constraint)*/
11211	      if( ncliquevars == nitems )
11212	         return SCIP_OKAY;
11213	
11214	      /* copy items in order into buffer array and deduce more cliques */
11215	      SCIP_CALL( SCIPduplicateBufferArray(scip, &cliquevars, items, ncliquevars) );
11216	
11217	      /* try to replace the last item in the clique by a different item to obtain a slightly different clique */
11218	      /* loop over remaining, smaller items and compare each item backwards against larger weights, starting with the second smallest weight */
11219	      compareweightidx = ncliquevars - 2;
11220	      assert(i == nitems || weights[i] + weights[ncliquevars - 1] <= capacity);
11221	
11222	      /* determine minimum clique size for the following loop */
11223	      minclqsize = (int)(cliqueextractfactor * ncliquevars);
11224	      minclqsize = MAX(minclqsize, 2);
11225	
11226	      /* loop over the remaining variables and the larger items of the first clique until we
11227	       * find another clique or reach the size limit */
11228	      while( compareweightidx >= 0 && i < nitems && ! (*cutoff)
11229	            && ncliquevars >= minclqsize  /* stop at a given minimum clique size */
11230	            && nnzadded <= 2 * nitems     /* stop if enough nonzeros were added to the cliquetable */
11231	            )
11232	      {
11233	         compareweight = weights[compareweightidx];
11234	         assert(compareweight > 0);
11235	
11236	         /* include this item together with all items that have a weight at least as large as the compare weight in a clique */
11237	         if( compareweight + weights[i] > capacity )
11238	         {
11239	            assert(compareweightidx == ncliquevars -2);
11240	            cliquevars[ncliquevars - 1] = items[i];
11241	            SCIPdebug( printClique(cliquevars, ncliquevars) );
11242	            SCIP_CALL( SCIPaddClique(scip, cliquevars, NULL, ncliquevars, FALSE, cutoff, &thisnbdchgs) );
11243	
11244	            nnzadded += ncliquevars;
11245	
11246	            /* stop when there is a cutoff */
11247	            if( ! (*cutoff) )
11248	               *nbdchgs += thisnbdchgs;
11249	
11250	            /* go to next smaller item */
11251	            ++i;
11252	         }
11253	         else
11254	         {
11255	            /* choose a preceding, larger weight to compare small items against. Clique size is reduced by 1 simultaneously */
11256	            compareweightidx--;
11257	            ncliquevars --;
11258	         }
11259	      }
11260	
11261	      SCIPfreeBufferArray(scip, &cliquevars);
11262	   }
11263	
11264	   return SCIP_OKAY;
11265	}
11266	
11267	/** adds cliques of the knapsack constraint to the global clique table */
11268	static
11269	SCIP_RETCODE addCliques(
11270	   SCIP*const            scip,               /**< SCIP data structure */
11271	   SCIP_CONS*const       cons,               /**< knapsack constraint */
11272	   SCIP_Real             cliqueextractfactor,/**< lower clique size limit for greedy clique extraction algorithm (relative to largest clique) */
11273	   SCIP_Bool*const       cutoff,             /**< pointer to store whether the node can be cut off */
11274	   int*const             nbdchgs             /**< pointer to count the number of performed bound changes */
11275	   )
11276	{
11277	   SCIP_CONSDATA* consdata;
11278	   SCIP_CONSHDLRDATA* conshdlrdata;
11279	   int i;
11280	   SCIP_Longint minactduetonegcliques;
11281	   SCIP_Longint freecapacity;
11282	   int nnegcliques;
11283	   int cliquenum;
11284	   SCIP_VAR** poscliquevars;
11285	   SCIP_Longint* gainweights;
11286	   int nposcliquevars;
11287	   SCIP_Longint* secondmaxweights;
11288	   int nvars;
11289	
11290	   assert(scip != NULL);
11291	   assert(cons != NULL);
11292	   assert(cutoff != NULL);
11293	   assert(nbdchgs != NULL);
11294	
11295	   *cutoff = FALSE;
11296	
11297	   consdata = SCIPconsGetData(cons);
11298	   assert(consdata != NULL);
11299	
11300	   nvars = consdata->nvars;
11301	
11302	   /* check whether the cliques have already been added */
11303	   if( consdata->cliquesadded || nvars == 0 )
11304	      return SCIP_OKAY;
11305	
11306	   /* make sure, the items are merged */
11307	   SCIP_CALL( mergeMultiples(scip, cons, cutoff) );
11308	   if( *cutoff )
11309	      return SCIP_OKAY;
11310	
11311	   /* make sure, the items are sorted by non-increasing weight */
11312	   sortItems(consdata);
11313	
11314	   assert(consdata->merged);
11315	
11316	   conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
11317	   assert(conshdlrdata != NULL);
11318	
11319	   /* calculate a clique partition */
11320	   SCIP_CALL( calcCliquepartition(scip, conshdlrdata, consdata, FALSE, TRUE) );
11321	   nnegcliques = consdata->nnegcliques;
11322	   assert(nnegcliques <= nvars);
11323	
11324	   /* get temporary memory */
11325	   SCIP_CALL( SCIPallocBufferArray(scip, &poscliquevars, nvars) );
11326	   SCIP_CALL( SCIPallocBufferArray(scip, &gainweights, nvars) );
11327	   BMSclearMemoryArray(gainweights, nvars);
11328	   SCIP_CALL( SCIPallocBufferArray(scip, &secondmaxweights, nnegcliques) );
11329	   BMSclearMemoryArray(secondmaxweights, nnegcliques);
11330	
11331	   minactduetonegcliques = 0;
11332	
11333	   /* calculate minimal activity due to negated cliques, and determine second maximal weight in each clique */
11334	   if( nnegcliques < nvars )
11335	   {
11336	      nnegcliques = 0;
11337	
11338	      for( i = 0; i < nvars; ++i )
11339	      {
11340	         SCIP_Longint weight;
11341	
11342	         cliquenum = consdata->negcliquepartition[i];
11343	         assert(0 <= cliquenum && cliquenum <= nnegcliques);
11344	
11345	         weight = consdata->weights[i];
11346	         assert(weight > 0);
11347	
11348	         if( cliquenum == nnegcliques )
11349	            nnegcliques++;
11350	         else
11351	         {
11352	            minactduetonegcliques += weight;
11353	            if( secondmaxweights[cliquenum] == 0 )
11354	               secondmaxweights[cliquenum] = weight;
11355	         }
11356	      }
11357	   }
11358	
11359	   /* add cliques, using negated cliques information */
11360	   if( minactduetonegcliques > 0 )
11361	   {
11362	      /* free capacity is the rest of not used capacity if the smallest amount of weights due to negated cliques are used */
11363	      freecapacity = consdata->capacity - minactduetonegcliques;
11364	
11365	      SCIPdebugPrintCons(scip, cons, NULL);
11366	      SCIPdebugMsg(scip, "Try to add cliques in knapsack constraint handler for constraint %s; capacity = %" SCIP_LONGINT_FORMAT ", minactivity(due to neg. cliques) = %" SCIP_LONGINT_FORMAT ", freecapacity = %" SCIP_LONGINT_FORMAT ".\n",
11367	         SCIPconsGetName(cons), consdata->capacity, minactduetonegcliques, freecapacity);
11368	
11369	      /* create negated cliques out of negated cliques, if we do not take the smallest weight of a cliques ... */
11370	      SCIP_CALL( addNegatedCliques(scip, cons, cutoff, nbdchgs ) );
11371	
11372	      if( *cutoff )
11373	         goto TERMINATE;
11374	
11375	      nposcliquevars = 0;
11376	
11377	      for( i = nvars - 1; i >= 0; --i )
11378	      {
11379	         /* if we would take the biggest weight instead of the second biggest */
11380	         cliquenum = consdata->negcliquepartition[i];
11381	         if( consdata->weights[i] > secondmaxweights[cliquenum] )
11382	         {
11383	            poscliquevars[nposcliquevars] = consdata->vars[i];
11384	            gainweights[nposcliquevars] = consdata->weights[i] - secondmaxweights[cliquenum];
11385	            ++nposcliquevars;
11386	         }
11387	      }
11388	
11389	      /* use the gain weights and free capacity to derive greedily cliques */
11390	      if( nposcliquevars > 1 )
11391	      {
11392	         SCIP_CALL( greedyCliqueAlgorithm(scip, poscliquevars, gainweights, nposcliquevars, freecapacity, FALSE, cliqueextractfactor, cutoff, nbdchgs) );
11393	
11394	         if( *cutoff )
11395	            goto TERMINATE;
11396	      }
11397	   }
11398	
11399	   /* build cliques by using the items with the maximal weights */
11400	   SCIP_CALL( greedyCliqueAlgorithm(scip, consdata->vars, consdata->weights, nvars, consdata->capacity, TRUE, cliqueextractfactor, cutoff, nbdchgs) );
11401	
11402	   TERMINATE:
11403	   /* free temporary memory and mark the constraint */
11404	   SCIPfreeBufferArray(scip, &secondmaxweights);
11405	   SCIPfreeBufferArray(scip, &gainweights);
11406	   SCIPfreeBufferArray(scip, &poscliquevars);
11407	   consdata->cliquesadded = TRUE;
11408	
11409	   return SCIP_OKAY;
11410	}
11411	
11412	
11413	/** gets the key of the given element */
11414	static
11415	SCIP_DECL_HASHGETKEY(hashGetKeyKnapsackcons)
11416	{  /*lint --e{715}*/
11417	   /* the key is the element itself */
11418	   return elem;
11419	}
11420	
11421	/** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
11422	 * same coefficients
11423	 */
11424	static
11425	SCIP_DECL_HASHKEYEQ(hashKeyEqKnapsackcons)
11426	{
11427	#ifndef NDEBUG
11428	   SCIP* scip;
11429	#endif
11430	   SCIP_CONSDATA* consdata1;
11431	   SCIP_CONSDATA* consdata2;
11432	   int i;
11433	
11434	   consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
11435	   consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
11436	   assert(consdata1->sorted);
11437	   assert(consdata2->sorted);
11438	#ifndef NDEBUG
11439	   scip = (SCIP*)userptr;
11440	   assert(scip != NULL);
11441	#endif
11442	
11443	   /* checks trivial case */
11444	   if( consdata1->nvars != consdata2->nvars )
11445	      return FALSE;
11446	
11447	   for( i = consdata1->nvars - 1; i >= 0; --i )
11448	   {
11449	      /* tests if variables are equal */
11450	      if( consdata1->vars[i] != consdata2->vars[i] )
11451	      {
11452	         assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
11453	            SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
11454	         return FALSE;
11455	      }
11456	      assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
11457	
11458	      /* tests if weights are equal too */
11459	      if( consdata1->weights[i] != consdata2->weights[i] )
11460	         return FALSE;
11461	   }
11462	
11463	   return TRUE;
11464	}
11465	
11466	/** returns the hash value of the key */
11467	static
11468	SCIP_DECL_HASHKEYVAL(hashKeyValKnapsackcons)
11469	{
11470	#ifndef NDEBUG
11471	   SCIP* scip;
11472	#endif
11473	   SCIP_CONSDATA* consdata;
11474	   uint64_t firstweight;
11475	   int minidx;
11476	   int mididx;
11477	   int maxidx;
11478	
11479	   consdata = SCIPconsGetData((SCIP_CONS*)key);
11480	   assert(consdata != NULL);
11481	   assert(consdata->nvars > 0);
11482	
11483	#ifndef NDEBUG
11484	   scip = (SCIP*)userptr;
11485	   assert(scip != NULL);
11486	#endif
11487	
11488	   /* sorts the constraints */
11489	   sortItems(consdata);
11490	
11491	   minidx = SCIPvarGetIndex(consdata->vars[0]);
11492	   mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
11493	   maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
11494	   assert(minidx >= 0 && mididx >= 0 && maxidx >= 0);
11495	
11496	   /* hash value depends on vectors of variable indices */
11497	   firstweight = (uint64_t)consdata->weights[0];
11498	   return SCIPhashSix(consdata->nvars, minidx, mididx, maxidx, firstweight>>32, firstweight);
11499	}
11500	
11501	/** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
11502	 *  accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
11503	 */
11504	static
11505	SCIP_RETCODE detectRedundantConstraints(
11506	   SCIP*                 scip,               /**< SCIP data structure */
11507	   BMS_BLKMEM*           blkmem,             /**< block memory */
11508	   SCIP_CONS**           conss,              /**< constraint set */
11509	   int                   nconss,             /**< number of constraints in constraint set */
11510	   SCIP_Bool*            cutoff,             /**< pointer to store whether the problem is infeasible */
11511	   int*                  ndelconss           /**< pointer to count number of deleted constraints */
11512	   )
11513	{
11514	   SCIP_HASHTABLE* hashtable;
11515	   int hashtablesize;
11516	   int c;
11517	
11518	   assert(scip != NULL);
11519	   assert(blkmem != NULL);
11520	   assert(conss != NULL);
11521	   assert(ndelconss != NULL);
11522	
11523	   /* create a hash table for the constraint set */
11524	   hashtablesize = nconss;
11525	   hashtablesize = MAX(hashtablesize, HASHSIZE_KNAPSACKCONS);
11526	   SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
11527	         hashGetKeyKnapsackcons, hashKeyEqKnapsackcons, hashKeyValKnapsackcons, (void*) scip) );
11528	
11529	   /* check all constraints in the given set for redundancy */
11530	   for( c = nconss - 1; c >= 0; --c )
11531	   {
11532	      SCIP_CONS* cons0;
11533	      SCIP_CONS* cons1;
11534	      SCIP_CONSDATA* consdata0;
11535	
11536	      cons0 = conss[c];
11537	
11538	      if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
11539	         continue;
11540	
11541	      consdata0 = SCIPconsGetData(cons0);
11542	      assert(consdata0 != NULL);
11543	      if( consdata0->nvars == 0 )
11544	      {
11545	         if( consdata0->capacity < 0 )
11546	         {
11547	            *cutoff = TRUE;
11548	            goto TERMINATE;
11549	         }
11550	         else
11551	         {
11552	            SCIP_CALL( SCIPdelCons(scip, cons0) );
11553	            ++(*ndelconss);
11554	            continue;
11555	         }
11556	      }
11557	
11558	      /* get constraint from current hash table with same variables and same weights as cons0 */
11559	      cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
11560	
11561	      if( cons1 != NULL )
11562	      {
11563	         SCIP_CONS* consstay;
11564	         SCIP_CONS* consdel;
11565	         SCIP_CONSDATA* consdata1;
11566	
11567	         assert(SCIPconsIsActive(cons1));
11568	         assert(!SCIPconsIsModifiable(cons1));
11569	
11570	         /* constraint found: create a new constraint with same coefficients and best left and right hand side;
11571	          * delete old constraints afterwards
11572	          */
11573	         consdata1 = SCIPconsGetData(cons1);
11574	
11575	         assert(consdata1 != NULL);
11576	         assert(consdata0->nvars > 0 && consdata0->nvars == consdata1->nvars);
11577	
11578	         assert(consdata0->sorted && consdata1->sorted);
11579	         assert(consdata0->vars[0] == consdata1->vars[0]);
11580	         assert(consdata0->weights[0] == consdata1->weights[0]);
11581	
11582	         SCIPdebugMsg(scip, "knapsack constraints <%s> and <%s> with equal coefficients\n",
11583	            SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11584	
11585	         /* check which constraint has to stay; */
11586	         if( consdata0->capacity < consdata1->capacity )
11587	         {
11588	            consstay = cons0;
11589	            consdel = cons1;
11590	
11591	            /* exchange consdel with consstay in hashtable */
11592	            SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) consdel) );
11593	            SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) consstay) );
11594	         }
11595	         else
11596	         {
11597	            consstay = cons1;
11598	            consdel = cons0;
11599	         }
11600	
11601	         /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11602	         SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
11603	
11604	         /* delete consdel */
11605	         SCIP_CALL( SCIPdelCons(scip, consdel) );
11606	         ++(*ndelconss);
11607	
11608	         assert(SCIPconsIsActive(consstay));
11609	      }
11610	      else
11611	      {
11612	         /* no such constraint in current hash table: insert cons0 into hash table */
11613	         SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
11614	      }
11615	   }
11616	
11617	 TERMINATE:
11618	   /* free hash table */
11619	   SCIPhashtableFree(&hashtable);
11620	
11621	   return SCIP_OKAY;
11622	}
11623	
11624	
11625	/** compares constraint with all prior constraints for possible redundancy or aggregation,
11626	 *  and removes or changes constraint accordingly
11627	 */
11628	static
11629	SCIP_RETCODE preprocessConstraintPairs(
11630	   SCIP*                 scip,               /**< SCIP data structure */
11631	   SCIP_CONS**           conss,              /**< constraint set */
11632	   int                   firstchange,        /**< first constraint that changed since last pair preprocessing round */
11633	   int                   chkind,             /**< index of constraint to check against all prior indices upto startind */
11634	   int*                  ndelconss           /**< pointer to count number of deleted constraints */
11635	   )
11636	{
11637	   SCIP_CONS* cons0;
11638	   SCIP_CONSDATA* consdata0;
11639	   int c;
11640	
11641	   assert(scip != NULL);
11642	   assert(conss != NULL);
11643	   assert(firstchange <= chkind);
11644	   assert(ndelconss != NULL);
11645	
11646	   /* get the constraint to be checked against all prior constraints */
11647	   cons0 = conss[chkind];
11648	   assert(cons0 != NULL);
11649	   assert(SCIPconsIsActive(cons0));
11650	   assert(!SCIPconsIsModifiable(cons0));
11651	
11652	   consdata0 = SCIPconsGetData(cons0);
11653	   assert(consdata0 != NULL);
11654	   assert(consdata0->nvars >= 1);
11655	   assert(consdata0->merged);
11656	
11657	   /* sort the constraint */
11658	   sortItems(consdata0);
11659	
11660	   /* see #2970 */
11661	   if( consdata0->capacity == 0 )
11662	      return SCIP_OKAY;
11663	
11664	   /* check constraint against all prior constraints */
11665	   for( c = (consdata0->presolvedtiming == SCIP_PRESOLTIMING_EXHAUSTIVE ? firstchange : 0); c < chkind; ++c )
11666	   {
11667	      SCIP_CONS* cons1;
11668	      SCIP_CONSDATA* consdata1;
11669	      SCIP_Bool iscons0incons1contained;
11670	      SCIP_Bool iscons1incons0contained;
11671	      SCIP_Real quotient;
11672	      int v;
11673	      int v0;
11674	      int v1;
11675	
11676	      cons1 = conss[c];
11677	      assert(cons1 != NULL);
11678	      if( !SCIPconsIsActive(cons1) || SCIPconsIsModifiable(cons1) )
11679	         continue;
11680	
11681	      consdata1 = SCIPconsGetData(cons1);
11682	      assert(consdata1 != NULL);
11683	
11684	      /* if both constraints didn't change since last pair processing, we can ignore the pair */
11685	      if( consdata0->presolvedtiming >= SCIP_PRESOLTIMING_EXHAUSTIVE && consdata1->presolvedtiming >= SCIP_PRESOLTIMING_EXHAUSTIVE ) /*lint !e574*/
11686	         continue;
11687	
11688	      assert(consdata1->nvars >= 1);
11689	      assert(consdata1->merged);
11690	
11691	      /* sort the constraint */
11692	      sortItems(consdata1);
11693	
11694	      /* see #2970 */
11695	      if( consdata1->capacity == 0 )
11696	         continue;
11697	
11698	      quotient = ((SCIP_Real) consdata0->capacity) / ((SCIP_Real) consdata1->capacity);
11699	
11700	      if( consdata0->nvars > consdata1->nvars )
11701	      {
11702	         iscons0incons1contained = FALSE;
11703	         iscons1incons0contained = TRUE;
11704	         v = consdata1->nvars - 1;
11705	      }
11706	      else if( consdata0->nvars < consdata1->nvars )
11707	      {
11708	         iscons0incons1contained = TRUE;
11709	         iscons1incons0contained = FALSE;
11710	         v = consdata0->nvars - 1;
11711	      }
11712	      else
11713	      {
11714	         iscons0incons1contained = TRUE;
11715	         iscons1incons0contained = TRUE;
11716	         v = consdata0->nvars - 1;
11717	      }
11718	
11719	      SCIPdebugMsg(scip, "preprocess knapsack constraint pair <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11720	
11721	      /* check consdata0 against consdata1:
11722	       * 1. if all variables var_i of cons1 are in cons0 and for each of these variables
11723	       *    (consdata0->weights[i] / quotient) >= consdata1->weights[i] cons1 is redundant
11724	       * 2. if all variables var_i of cons0 are in cons1 and for each of these variables
11725	       *    (consdata0->weights[i] / quotient) <= consdata1->weights[i] cons0 is redundant
11726	       */
11727	      v0 = consdata0->nvars - 1;
11728	      v1 = consdata1->nvars - 1;
11729	
11730	      while( v >= 0 )
11731	      {
11732	         assert(iscons0incons1contained || iscons1incons0contained);
11733	
11734	         /* now there are more variables in cons1 left */
11735	         if( v1 > v0 )
11736	         {
11737	            iscons1incons0contained = FALSE;
11738	            if( !iscons0incons1contained )
11739	               break;
11740	         }
11741	         /* now there are more variables in cons0 left */
11742	         else if( v1 < v0 )
11743	         {
11744	            iscons0incons1contained = FALSE;
11745	            if( !iscons1incons0contained )
11746	               break;
11747	         }
11748	
11749	         assert(v == v0 || v == v1);
11750	         assert(v0 >= 0);
11751	         assert(v1 >= 0);
11752	
11753	         /* both variables are the same */
11754	         if( consdata0->vars[v0] == consdata1->vars[v1] )
11755	         {
11756	            /* if cons1 is possible contained in cons0 (consdata0->weights[v0] / quotient) must be greater equals consdata1->weights[v1] */
11757	            if( iscons1incons0contained && SCIPisLT(scip, ((SCIP_Real) consdata0->weights[v0]) / quotient, (SCIP_Real) consdata1->weights[v1]) )
11758	            {
11759	               iscons1incons0contained = FALSE;
11760	               if( !iscons0incons1contained )
11761	                  break;
11762	            }
11763	            /* if cons0 is possible contained in cons1 (consdata0->weight[v0] / quotient) must be less equals consdata1->weight[v1] */
11764	            else if( iscons0incons1contained && SCIPisGT(scip, ((SCIP_Real) consdata0->weights[v0]) / quotient, (SCIP_Real) consdata1->weights[v1]) )
11765	            {
11766	               iscons0incons1contained = FALSE;
11767	               if( !iscons1incons0contained )
11768	                  break;
11769	            }
11770	            --v0;
11771	            --v1;
11772		    --v;
11773	         }
11774	         else
11775	         {
11776	            /* both constraints have a variables which is not part of the other constraint, so stop */
11777	            if( iscons0incons1contained && iscons1incons0contained )
11778	            {
11779	               iscons0incons1contained = FALSE;
11780	               iscons1incons0contained = FALSE;
11781	               break;
11782	            }
11783	            assert(iscons0incons1contained ? (v1 >= v0) : iscons1incons0contained);
11784	            assert(iscons1incons0contained ? (v1 <= v0) : iscons0incons1contained);
11785	            /* continue to the next variable */
11786	            if( iscons0incons1contained )
11787	               --v1;
11788	            else
11789	               --v0;
11790	         }
11791	      }
11792	      /* neither one constraint was contained in another or we checked all variables of one constraint against the
11793	       * other
11794	       */
11795	      assert(!iscons1incons0contained || !iscons0incons1contained || v0 == -1 || v1 == -1);
11796	
11797	      if( iscons1incons0contained )
11798	      {
11799	         SCIPdebugMsg(scip, "knapsack constraint <%s> is redundant\n", SCIPconsGetName(cons1));
11800	         SCIPdebugPrintCons(scip, cons1, NULL);
11801	
11802	         /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11803	         SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
11804	
11805	         SCIP_CALL( SCIPdelCons(scip, cons1) );
11806	         ++(*ndelconss);
11807	      }
11808	      else if( iscons0incons1contained )
11809	      {
11810	         SCIPdebugMsg(scip, "knapsack constraint <%s> is redundant\n", SCIPconsGetName(cons0));
11811	         SCIPdebugPrintCons(scip, cons0, NULL);
11812	
11813	         /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11814	         SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
11815	
11816	         SCIP_CALL( SCIPdelCons(scip, cons0) );
11817	         ++(*ndelconss);
11818	         break;
11819	      }
11820	   }
11821	
11822	   return SCIP_OKAY;
11823	}
11824	
11825	/** helper function to enforce constraints */
11826	static
11827	SCIP_RETCODE enforceConstraint(
11828	   SCIP*                 scip,               /**< SCIP data structure */
11829	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
11830	   SCIP_CONS**           conss,              /**< constraints to process */
11831	   int                   nconss,             /**< number of constraints */
11832	   int                   nusefulconss,       /**< number of useful (non-obsolete) constraints to process */
11833	   SCIP_SOL*             sol,                /**< solution to enforce (NULL for the LP solution) */
11834	   SCIP_RESULT*          result              /**< pointer to store the result of the enforcing call */
11835	   )
11836	{
11837	   SCIP_CONSHDLRDATA* conshdlrdata;
11838	   SCIP_Bool violated;
11839	   SCIP_Bool cutoff = FALSE;
11840	   int maxncuts;
11841	   int ncuts = 0;
11842	   int i;
11843	
11844	   *result = SCIP_FEASIBLE;
11845	
11846	   SCIPdebugMsg(scip, "knapsack enforcement of %d/%d constraints for %s solution\n", nusefulconss, nconss,
11847	         sol == NULL ? "LP" : "relaxation");
11848	
11849	   /* get maximal number of cuts per round */
11850	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
11851	   assert(conshdlrdata != NULL);
11852	   maxncuts = (SCIPgetDepth(scip) == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
11853	
11854	   /* search for violated useful knapsack constraints */
11855	   for( i = 0; i < nusefulconss && ncuts < maxncuts && ! cutoff; i++ )
11856	   {
11857	      SCIP_CALL( checkCons(scip, conss[i], sol, FALSE, FALSE, &violated) );
11858	      if( violated )
11859	      {
11860	         /* add knapsack constraint as LP row to the relaxation */
11861	         SCIP_CALL( addRelaxation(scip, conss[i], &cutoff) );
11862	         ncuts++;
11863	      }
11864	   }
11865	
11866	   /* as long as no violations were found, search for violated obsolete knapsack constraints */
11867	   for( i = nusefulconss; i < nconss && ncuts == 0 && ! cutoff; i++ )
11868	   {
11869	      SCIP_CALL( checkCons(scip, conss[i], sol, FALSE, FALSE, &violated) );
11870	      if( violated )
11871	      {
11872	         /* add knapsack constraint as LP row to the relaxation */
11873	         SCIP_CALL( addRelaxation(scip, conss[i], &cutoff) );
11874	         ncuts++;
11875	      }
11876	   }
11877	
11878	   /* adjust the result code */
11879	   if ( cutoff )
11880	      *result = SCIP_CUTOFF;
11881	   else if ( ncuts > 0 )
11882	      *result = SCIP_SEPARATED;
11883	
11884	   return SCIP_OKAY;
11885	}
11886	
11887	/*
11888	 * Linear constraint upgrading
11889	 */
11890	
11891	/** creates and captures a knapsack constraint out of a linear inequality */
11892	static
11893	SCIP_RETCODE createNormalizedKnapsack(
11894	   SCIP*                 scip,               /**< SCIP data structure */
11895	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
11896	   const char*           name,               /**< name of constraint */
11897	   int                   nvars,              /**< number of variables in the constraint */
11898	   SCIP_VAR**            vars,               /**< array with variables of constraint entries */
11899	   SCIP_Real*            vals,               /**< array with inequality coefficients */
11900	   SCIP_Real             lhs,                /**< left hand side of inequality */
11901	   SCIP_Real             rhs,                /**< right hand side of inequality */
11902	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
11903	                                              *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
11904	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
11905	                                              *   Usually set to TRUE. */
11906	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
11907	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
11908	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
11909	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
11910	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
11911	                                              *   Usually set to TRUE. */
11912	   SCIP_Bool             local,              /**< is constraint only valid locally?
11913	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
11914	   SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)?
11915	                                              *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
11916	                                              *   adds coefficients to this constraint. */
11917	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
11918	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
11919	                                              *   are separated as constraints. */
11920	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
11921	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
11922	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
11923	                                              *   if it may be moved to a more global node?
11924	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
11925	   )
11926	{
11927	   SCIP_VAR** transvars;
11928	   SCIP_Longint* weights;
11929	   SCIP_Longint capacity;
11930	   SCIP_Longint weight;
11931	   int mult;
11932	   int v;
11933	
11934	   assert(nvars == 0 || vars != NULL);
11935	   assert(nvars == 0 || vals != NULL);
11936	   assert(SCIPisInfinity(scip, -lhs) != SCIPisInfinity(scip, rhs));
11937	
11938	   /* get temporary memory */
11939	   SCIP_CALL( SCIPallocBufferArray(scip, &transvars, nvars) );
11940	   SCIP_CALL( SCIPallocBufferArray(scip, &weights, nvars) );
11941	
11942	   /* if the right hand side is non-infinite, we have to negate all variables with negative coefficient;
11943	    * otherwise, we have to negate all variables with positive coefficient and multiply the row with -1
11944	    */
11945	   if( SCIPisInfinity(scip, rhs) )
11946	   {
11947	      mult = -1;
11948	      capacity = (SCIP_Longint)SCIPfeasFloor(scip, -lhs);
11949	   }
11950	   else
11951	   {
11952	      mult = +1;
11953	      capacity = (SCIP_Longint)SCIPfeasFloor(scip, rhs);
11954	   }
11955	
11956	   /* negate positive or negative variables */
11957	   for( v = 0; v < nvars; ++v )
11958	   {
11959	      assert(SCIPisFeasIntegral(scip, vals[v]));
11960	      weight = mult * (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11961	      if( weight > 0 )
11962	      {
11963	         transvars[v] = vars[v];
11964	         weights[v] = weight;
11965	      }
11966	      else
11967	      {
11968	         SCIP_CALL( SCIPgetNegatedVar(scip, vars[v], &transvars[v]) );
11969	         weights[v] = -weight; /*lint !e2704*/
11970	         capacity -= weight;
11971	      }
11972	      assert(transvars[v] != NULL);
11973	   }
11974	
11975	   /* create the constraint */
11976	   SCIP_CALL( SCIPcreateConsKnapsack(scip, cons, name, nvars, transvars, weights, capacity,
11977	         initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
11978	
11979	   /* free temporary memory */
11980	   SCIPfreeBufferArray(scip, &weights);
11981	   SCIPfreeBufferArray(scip, &transvars);
11982	
11983	   return SCIP_OKAY;
11984	}
11985	
11986	/** tries to upgrade a linear constraint into a knapsack constraint */
11987	static
11988	SCIP_DECL_LINCONSUPGD(linconsUpgdKnapsack)
11989	{  /*lint --e{715}*/
11990	   SCIP_Bool upgrade;
11991	
11992	   assert(upgdcons != NULL);
11993	
11994	   /* check, if linear constraint can be upgraded to a knapsack constraint
11995	    * - all variables must be binary
11996	    * - all coefficients must be integral
11997	    * - exactly one of the sides must be infinite
11998	    * note that this includes the case of negative capacity, which has been
11999	    * observed to occur, e.g., when upgrading a conflict constraint
12000	    */
12001	   upgrade = (nposbin + nnegbin + nposimplbin + nnegimplbin == nvars)
12002	      && (ncoeffspone + ncoeffsnone + ncoeffspint + ncoeffsnint == nvars)
12003	      && (SCIPisInfinity(scip, -lhs) != SCIPisInfinity(scip, rhs));
12004	
12005	   if( upgrade )
12006	   {
12007	      SCIPdebugMsg(scip, "upgrading constraint <%s> to knapsack constraint\n", SCIPconsGetName(cons));
12008	
12009	      /* create the knapsack constraint (an automatically upgraded constraint is always unmodifiable) */
12010	      assert(!SCIPconsIsModifiable(cons));
12011	      SCIP_CALL( createNormalizedKnapsack(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, lhs, rhs,
12012	            SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
12013	            SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),
12014	            SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons),
12015	            SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
12016	   }
12017	
12018	   return SCIP_OKAY;
12019	}
12020	
12021	/** adds symmetry information of constraint to a symmetry detection graph */
12022	static
12023	SCIP_RETCODE addSymmetryInformation(
12024	   SCIP*                 scip,               /**< SCIP pointer */
12025	   SYM_SYMTYPE           symtype,            /**< type of symmetries that need to be added */
12026	   SCIP_CONS*            cons,               /**< constraint */
12027	   SYM_GRAPH*            graph,              /**< symmetry detection graph */
12028	   SCIP_Bool*            success             /**< pointer to store whether symmetry information could be added */
12029	   )
12030	{
12031	   SCIP_CONSDATA* consdata;
12032	   SCIP_VAR** vars;
12033	   SCIP_Real* vals;
12034	   SCIP_Real constant = 0.0;
12035	   SCIP_Real rhs;
12036	   int nlocvars;
12037	   int nvars;
12038	   int i;
12039	
12040	   assert(scip != NULL);
12041	   assert(cons != NULL);
12042	   assert(graph != NULL);
12043	   assert(success != NULL);
12044	
12045	   consdata = SCIPconsGetData(cons);
12046	   assert(consdata != NULL);
12047	   assert(graph != NULL);
12048	
12049	   /* get active variables of the constraint */
12050	   nvars = SCIPgetNVars(scip);
12051	   nlocvars = consdata->nvars;
12052	
12053	   SCIP_CALL( SCIPallocBufferArray(scip, &vars, nvars) );
12054	   SCIP_CALL( SCIPallocBufferArray(scip, &vals, nvars) );
12055	
12056	   for( i = 0; i < consdata->nvars; ++i )
12057	   {
12058	      vars[i] = consdata->vars[i];
12059	      vals[i] = (SCIP_Real) consdata->weights[i];
12060	   }
12061	
12062	   SCIP_CALL( SCIPgetActiveVariables(scip, symtype, &vars, &vals, &nlocvars, &constant, SCIPisTransformed(scip)) );
12063	   rhs = (SCIP_Real) SCIPgetCapacityKnapsack(scip, cons) - constant;
12064	
12065	   SCIP_CALL( SCIPextendPermsymDetectionGraphLinear(scip, graph, vars, vals, nlocvars,
12066	         cons, -SCIPinfinity(scip), rhs, success) );
12067	
12068	   SCIPfreeBufferArray(scip, &vals);
12069	   SCIPfreeBufferArray(scip, &vars);
12070	
12071	   return SCIP_OKAY;
12072	}
12073	
12074	/*
12075	 * Callback methods of constraint handler
12076	 */
12077	
12078	/** copy method for constraint handler plugins (called when SCIP copies plugins) */
12079	/**! [SnippetConsCopyKnapsack] */
12080	static
12081	SCIP_DECL_CONSHDLRCOPY(conshdlrCopyKnapsack)
12082	{  /*lint --e{715}*/
12083	   assert(scip != NULL);
12084	   assert(conshdlr != NULL);
12085	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12086	
12087	   /* call inclusion method of constraint handler */
12088	   SCIP_CALL( SCIPincludeConshdlrKnapsack(scip) );
12089	
12090	   *valid = TRUE;
12091	
12092	   return SCIP_OKAY;
12093	}
12094	/**! [SnippetConsCopyKnapsack] */
12095	
12096	/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
12097	/**! [SnippetConsFreeKnapsack] */
12098	static
12099	SCIP_DECL_CONSFREE(consFreeKnapsack)
12100	{  /*lint --e{715}*/
12101	   SCIP_CONSHDLRDATA* conshdlrdata;
12102	
12103	   /* free constraint handler data */
12104	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12105	   assert(conshdlrdata != NULL);
12106	
12107	   SCIPfreeBlockMemory(scip, &conshdlrdata);
12108	
12109	   SCIPconshdlrSetData(conshdlr, NULL);
12110	
12111	   return SCIP_OKAY;
12112	}
12113	/**! [SnippetConsFreeKnapsack] */
12114	
12115	
12116	/** initialization method of constraint handler (called after problem was transformed) */
12117	static
12118	SCIP_DECL_CONSINIT(consInitKnapsack)
12119	{  /*lint --e{715}*/
12120	   SCIP_CONSHDLRDATA* conshdlrdata;
12121	   int nvars;
12122	
12123	   assert( scip != NULL );
12124	   assert( conshdlr != NULL );
12125	
12126	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12127	   assert(conshdlrdata != NULL);
12128	
12129	   /* all variables which are of integral type can be binary; this can be checked via the method SCIPvarIsBinary(var) */
12130	   nvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
12131	
12132	   SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &conshdlrdata->reals1, nvars) );
12133	   conshdlrdata->reals1size = nvars;
12134	
12135	   return SCIP_OKAY;
12136	}
12137	
12138	/** deinitialization method of constraint handler (called before transformed problem is freed) */
12139	static
12140	SCIP_DECL_CONSEXIT(consExitKnapsack)
12141	{  /*lint --e{715}*/
12142	   SCIP_CONSHDLRDATA* conshdlrdata;
12143	
12144	   assert( scip != NULL );
12145	   assert( conshdlr != NULL );
12146	
12147	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12148	   assert(conshdlrdata != NULL);
12149	
12150	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->reals1, conshdlrdata->reals1size);
12151	   conshdlrdata->reals1size = 0;
12152	
12153	   return SCIP_OKAY;
12154	}
12155	
12156	
12157	/** presolving initialization method of constraint handler (called when presolving is about to begin) */
12158	static
12159	SCIP_DECL_CONSINITPRE(consInitpreKnapsack)
12160	{  /*lint --e{715}*/
12161	   SCIP_CONSHDLRDATA* conshdlrdata;
12162	   int nvars;
12163	
12164	   assert(scip != NULL);
12165	   assert(conshdlr != NULL);
12166	   assert(nconss == 0 || conss != NULL);
12167	
12168	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12169	   assert(conshdlrdata != NULL);
12170	
12171	   /* all variables which are of integral type can be binary; this can be checked via the method SCIPvarIsBinary(var) */
12172	   nvars = SCIPgetNVars(scip) - SCIPgetNContVars(scip);
12173	
12174	   SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &conshdlrdata->ints1, nvars) );
12175	   SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &conshdlrdata->ints2, nvars) );
12176	   SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &conshdlrdata->longints1, nvars) );
12177	   SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &conshdlrdata->longints2, nvars) );
12178	   SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &conshdlrdata->bools1, nvars) );
12179	   SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &conshdlrdata->bools2, nvars) );
12180	   SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &conshdlrdata->bools3, nvars) );
12181	   SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &conshdlrdata->bools4, nvars) );
12182	
12183	   conshdlrdata->ints1size = nvars;
12184	   conshdlrdata->ints2size = nvars;
12185	   conshdlrdata->longints1size = nvars;
12186	   conshdlrdata->longints2size = nvars;
12187	   conshdlrdata->bools1size = nvars;
12188	   conshdlrdata->bools2size = nvars;
12189	   conshdlrdata->bools3size = nvars;
12190	   conshdlrdata->bools4size = nvars;
12191	
12192	#ifdef WITH_CARDINALITY_UPGRADE
12193	   conshdlrdata->upgradedcard = FALSE;
12194	#endif
12195	
12196	   return SCIP_OKAY;
12197	}
12198	
12199	
12200	/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
12201	static
12202	SCIP_DECL_CONSEXITPRE(consExitpreKnapsack)
12203	{  /*lint --e{715}*/
12204	   SCIP_CONSHDLRDATA* conshdlrdata;
12205	   int c;
12206	
12207	   assert(scip != NULL);
12208	   assert(conshdlr != NULL);
12209	
12210	   for( c = 0; c < nconss; ++c )
12211	   {
12212	      if( !SCIPconsIsDeleted(conss[c]) )
12213	      {
12214	         /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
12215	         SCIP_CALL( applyFixings(scip, conss[c], NULL) );
12216	      }
12217	   }
12218	
12219	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12220	   assert(conshdlrdata != NULL);
12221	
12222	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->ints1, conshdlrdata->ints1size);
12223	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->ints2, conshdlrdata->ints2size);
12224	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->longints1, conshdlrdata->longints1size);
12225	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->longints2, conshdlrdata->longints2size);
12226	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->bools1, conshdlrdata->bools1size);
12227	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->bools2, conshdlrdata->bools2size);
12228	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->bools3, conshdlrdata->bools3size);
12229	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->bools4, conshdlrdata->bools4size);
12230	
12231	   conshdlrdata->ints1size = 0;
12232	   conshdlrdata->ints2size = 0;
12233	   conshdlrdata->longints1size = 0;
12234	   conshdlrdata->longints2size = 0;
12235	   conshdlrdata->bools1size = 0;
12236	   conshdlrdata->bools2size = 0;
12237	   conshdlrdata->bools3size = 0;
12238	   conshdlrdata->bools4size = 0;
12239	
12240	   return SCIP_OKAY;
12241	}
12242	
12243	/** solving process initialization method of constraint handler */
12244	static
12245	SCIP_DECL_CONSINITSOL(consInitsolKnapsack)
12246	{  /*lint --e{715}*/
12247	   /* add nlrow representation to NLP, if NLP had been constructed */
12248	   if( SCIPisNLPConstructed(scip) )
12249	   {
12250	      int c;
12251	      for( c = 0; c < nconss; ++c )
12252	      {
12253	         SCIP_CALL( addNlrow(scip, conss[c]) );
12254	      }
12255	   }
12256	
12257	   return SCIP_OKAY;
12258	}
12259	
12260	/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
12261	static
12262	SCIP_DECL_CONSEXITSOL(consExitsolKnapsack)
12263	{  /*lint --e{715}*/
12264	   SCIP_CONSDATA* consdata;
12265	   int c;
12266	
12267	   assert( scip != NULL );
12268	
12269	   /* release the rows and nlrows of all constraints */
12270	   for( c = 0; c < nconss; ++c )
12271	   {
12272	      consdata = SCIPconsGetData(conss[c]);
12273	      assert(consdata != NULL);
12274	
12275	      if( consdata->row != NULL )
12276	      {
12277	         SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
12278	      }
12279	
12280	      if( consdata->nlrow != NULL )
12281	      {
12282	         SCIP_CALL( SCIPreleaseNlRow(scip, &consdata->nlrow) );
12283	      }
12284	   }
12285	
12286	   return SCIP_OKAY;
12287	}
12288	
12289	/** frees specific constraint data */
12290	static
12291	SCIP_DECL_CONSDELETE(consDeleteKnapsack)
12292	{  /*lint --e{715}*/
12293	   SCIP_CONSHDLRDATA* conshdlrdata;
12294	
12295	   assert(conshdlr != NULL);
12296	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12297	
12298	   /* get event handler */
12299	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12300	   assert(conshdlrdata != NULL);
12301	   assert(conshdlrdata->eventhdlr != NULL);
12302	
12303	   /* free knapsack constraint */
12304	   SCIP_CALL( consdataFree(scip, consdata, conshdlrdata->eventhdlr) );
12305	
12306	   return SCIP_OKAY;
12307	}
12308	
12309	/** transforms constraint data into data belonging to the transformed problem */
12310	/**! [SnippetConsTransKnapsack]*/
12311	static
12312	SCIP_DECL_CONSTRANS(consTransKnapsack)
12313	{  /*lint --e{715}*/
12314	   SCIP_CONSHDLRDATA* conshdlrdata;
12315	   SCIP_CONSDATA* sourcedata;
12316	   SCIP_CONSDATA* targetdata;
12317	
12318	   assert(conshdlr != NULL);
12319	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12320	   assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
12321	   assert(sourcecons != NULL);
12322	   assert(targetcons != NULL);
12323	
12324	   sourcedata = SCIPconsGetData(sourcecons);
12325	   assert(sourcedata != NULL);
12326	   assert(sourcedata->row == NULL);  /* in original problem, there cannot be LP rows */
12327	
12328	   /* get event handler */
12329	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12330	   assert(conshdlrdata != NULL);
12331	   assert(conshdlrdata->eventhdlr != NULL);
12332	
12333	   /* create target constraint data */
12334	   SCIP_CALL( consdataCreate(scip, &targetdata,
12335	         sourcedata->nvars, sourcedata->vars, sourcedata->weights, sourcedata->capacity) );
12336	
12337	   /* create target constraint */
12338	   SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
12339	         SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
12340	         SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
12341	         SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
12342	         SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
12343	
12344	   /* catch events for variables */
12345	   SCIP_CALL( catchEvents(scip, *targetcons, targetdata, conshdlrdata->eventhdlr) );
12346	
12347	   return SCIP_OKAY;
12348	}
12349	/**! [SnippetConsTransKnapsack]*/
12350	
12351	/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
12352	static
12353	SCIP_DECL_CONSINITLP(consInitlpKnapsack)
12354	{  /*lint --e{715}*/
12355	   int i;
12356	
12357	   *infeasible = FALSE;
12358	
12359	   for( i = 0; i < nconss && !(*infeasible); i++ )
12360	   {
12361	      assert(SCIPconsIsInitial(conss[i]));
12362	      SCIP_CALL( addRelaxation(scip, conss[i], infeasible) );
12363	   }
12364	
12365	   return SCIP_OKAY;
12366	}
12367	
12368	/** separation method of constraint handler for LP solutions */
12369	static
12370	SCIP_DECL_CONSSEPALP(consSepalpKnapsack)
12371	{  /*lint --e{715}*/
12372	   SCIP_CONSHDLRDATA* conshdlrdata;
12373	   SCIP_Bool sepacardinality;
12374	   SCIP_Bool cutoff;
12375	
12376	   SCIP_Real loclowerbound;
12377	   SCIP_Real glblowerbound;
12378	   SCIP_Real cutoffbound;
12379	   SCIP_Real maxbound;
12380	
12381	   int depth;
12382	   int nrounds;
12383	   int sepafreq;
12384	   int sepacardfreq;
12385	   int ncuts;
12386	   int maxsepacuts;
12387	   int i;
12388	
12389	   *result = SCIP_DIDNOTRUN;
12390	
12391	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12392	   assert(conshdlrdata != NULL);
12393	
12394	   depth = SCIPgetDepth(scip);
12395	   nrounds = SCIPgetNSepaRounds(scip);
12396	
12397	   SCIPdebugMsg(scip, "knapsack separation of %d/%d constraints, round %d (max %d/%d)\n",
12398	      nusefulconss, nconss, nrounds, conshdlrdata->maxroundsroot, conshdlrdata->maxrounds);
12399	
12400	   /* only call the separator a given number of times at each node */
12401	   if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
12402	      || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
12403	      return SCIP_OKAY;
12404	
12405	   /* check, if we should additionally separate knapsack cuts */
12406	   sepafreq = SCIPconshdlrGetSepaFreq(conshdlr);
12407	   sepacardfreq = sepafreq * conshdlrdata->sepacardfreq;
12408	   sepacardinality = (conshdlrdata->sepacardfreq >= 0)
12409	      && ((sepacardfreq == 0 && depth == 0) || (sepacardfreq >= 1 && (depth % sepacardfreq == 0)));
12410	
12411	   /* check dual bound to see if we want to produce knapsack cuts at this node */
12412	   loclowerbound = SCIPgetLocalLowerbound(scip);
12413	   glblowerbound = SCIPgetLowerbound(scip);
12414	   cutoffbound = SCIPgetCutoffbound(scip);
12415	   maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
12416	   sepacardinality = sepacardinality && SCIPisLE(scip, loclowerbound, maxbound);
12417	   sepacardinality = sepacardinality && (SCIPgetNLPBranchCands(scip) > 0);
12418	
12419	   /* get the maximal number of cuts allowed in a separation round */
12420	   maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
12421	
12422	   *result = SCIP_DIDNOTFIND;
12423	   ncuts = 0;
12424	   cutoff = FALSE;
12425	
12426	   /* separate useful constraints */
12427	   for( i = 0; i < nusefulconss && ncuts < maxsepacuts && !SCIPisStopped(scip); i++ )
12428	   {
12429	      SCIP_CALL( separateCons(scip, conss[i], NULL, sepacardinality, conshdlrdata->usegubs, &cutoff, &ncuts) );
12430	   }
12431	
12432	   /* adjust return value */
12433	   if ( cutoff )
12434	      *result = SCIP_CUTOFF;
12435	   else if ( ncuts > 0 )
12436	      *result = SCIP_SEPARATED;
12437	
12438	   return SCIP_OKAY;
12439	}
12440	
12441	
12442	/** separation method of constraint handler for arbitrary primal solutions */
12443	static
12444	SCIP_DECL_CONSSEPASOL(consSepasolKnapsack)
12445	{  /*lint --e{715}*/
12446	   SCIP_CONSHDLRDATA* conshdlrdata;
12447	   SCIP_Bool sepacardinality;
12448	   SCIP_Bool cutoff;
12449	
12450	   int depth;
12451	   int nrounds;
12452	   int sepafreq;
12453	   int sepacardfreq;
12454	   int ncuts;
12455	   int maxsepacuts;
12456	   int i;
12457	
12458	   *result = SCIP_DIDNOTRUN;
12459	
12460	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12461	   assert(conshdlrdata != NULL);
12462	
12463	   depth = SCIPgetDepth(scip);
12464	   nrounds = SCIPgetNSepaRounds(scip);
12465	
12466	   SCIPdebugMsg(scip, "knapsack separation of %d/%d constraints, round %d (max %d/%d)\n",
12467	      nusefulconss, nconss, nrounds, conshdlrdata->maxroundsroot, conshdlrdata->maxrounds);
12468	
12469	   /* only call the separator a given number of times at each node */
12470	   if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
12471	      || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
12472	      return SCIP_OKAY;
12473	
12474	   /* check, if we should additionally separate knapsack cuts */
12475	   sepafreq = SCIPconshdlrGetSepaFreq(conshdlr);
12476	   sepacardfreq = sepafreq * conshdlrdata->sepacardfreq;
12477	   sepacardinality = (conshdlrdata->sepacardfreq >= 0)
12478	      && ((sepacardfreq == 0 && depth == 0) || (sepacardfreq >= 1 && (depth % sepacardfreq == 0)));
12479	
12480	   /* get the maximal number of cuts allowed in a separation round */
12481	   maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
12482	
12483	   *result = SCIP_DIDNOTFIND;
12484	   ncuts = 0;
12485	   cutoff = FALSE;
12486	
12487	   /* separate useful constraints */
12488	   for( i = 0; i < nusefulconss && ncuts < maxsepacuts && !SCIPisStopped(scip); i++ )
12489	   {
12490	      SCIP_CALL( separateCons(scip, conss[i], sol, sepacardinality, conshdlrdata->usegubs, &cutoff, &ncuts) );
12491	   }
12492	
12493	   /* adjust return value */
12494	   if ( cutoff )
12495	      *result = SCIP_CUTOFF;
12496	   else if( ncuts > 0 )
12497	      *result = SCIP_SEPARATED;
12498	
12499	   return SCIP_OKAY;
12500	}
12501	
12502	/** constraint enforcing method of constraint handler for LP solutions */
12503	static
12504	SCIP_DECL_CONSENFOLP(consEnfolpKnapsack)
12505	{  /*lint --e{715}*/
12506	   SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
12507	
12508	   return SCIP_OKAY;
12509	}
12510	
12511	/** constraint enforcing method of constraint handler for relaxation solutions */
12512	static
12513	SCIP_DECL_CONSENFORELAX(consEnforelaxKnapsack)
12514	{  /*lint --e{715}*/
12515	   SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
12516	
12517	   return SCIP_OKAY;
12518	}
12519	
12520	/** constraint enforcing method of constraint handler for pseudo solutions */
12521	static
12522	SCIP_DECL_CONSENFOPS(consEnfopsKnapsack)
12523	{  /*lint --e{715}*/
12524	   SCIP_Bool violated;
12525	   int i;
12526	
12527	   for( i = 0; i < nconss; i++ )
12528	   {
12529	      SCIP_CALL( checkCons(scip, conss[i], NULL, TRUE, FALSE, &violated) );
12530	      if( violated )
12531	      {
12532	         *result = SCIP_INFEASIBLE;
12533	         return SCIP_OKAY;
12534	      }
12535	   }
12536	   *result = SCIP_FEASIBLE;
12537	
12538	   return SCIP_OKAY;
12539	}
12540	
12541	/** feasibility check method of constraint handler for integral solutions */
12542	static
12543	SCIP_DECL_CONSCHECK(consCheckKnapsack)
12544	{  /*lint --e{715}*/
12545	   SCIP_Bool violated;
12546	   int i;
12547	
12548	   *result = SCIP_FEASIBLE;
12549	
12550	   for( i = 0; i < nconss && (*result == SCIP_FEASIBLE || completely); i++ )
12551	   {
12552	      SCIP_CALL( checkCons(scip, conss[i], sol, checklprows, printreason, &violated) );
12553	      if( violated )
12554	         *result = SCIP_INFEASIBLE;
12555	   }
12556	
12557	   return SCIP_OKAY;
12558	}
12559	
12560	/** domain propagation method of constraint handler */
12561	static
12562	SCIP_DECL_CONSPROP(consPropKnapsack)
12563	{  /*lint --e{715}*/
12564	   SCIP_CONSHDLRDATA* conshdlrdata;
12565	   SCIP_Bool cutoff;
12566	   SCIP_Bool redundant;
12567	   SCIP_Bool inpresolve;
12568	   int nfixedvars;
12569	   int i;
12570	
12571	   cutoff = FALSE;
12572	   nfixedvars = 0;
12573	
12574	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12575	   assert(conshdlrdata != NULL);
12576	
12577	   inpresolve = (SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE);
12578	   assert(!inpresolve || SCIPinProbing(scip));
12579	
12580	   /* process useful constraints */
12581	   for( i = 0; i < nmarkedconss && !cutoff; i++ )
12582	   {
12583	      /* do not propagate constraints with multi-aggregated variables, which should only happen in probing mode,
12584	       * otherwise the multi-aggregation should be resolved
12585	       */
12586	      if( inpresolve && SCIPconsGetData(conss[i])->existmultaggr )
12587	         continue;
12588	#ifndef NDEBUG
12589	      else
12590	         assert(!(SCIPconsGetData(conss[i])->existmultaggr));
12591	#endif
12592	
12593	      SCIP_CALL( propagateCons(scip, conss[i], &cutoff, &redundant, &nfixedvars, conshdlrdata->negatedclique) );
12594	
12595	      /* unmark the constraint to be propagated */
12596	      SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
12597	   }
12598	
12599	   /* adjust result code */
12600	   if( cutoff )
12601	      *result = SCIP_CUTOFF;
12602	   else if( nfixedvars > 0 )
12603	      *result = SCIP_REDUCEDDOM;
12604	   else
12605	      *result = SCIP_DIDNOTFIND;
12606	
12607	   return SCIP_OKAY; /*lint !e438*/
12608	}
12609	
12610	/** presolving method of constraint handler */
12611	static
12612	SCIP_DECL_CONSPRESOL(consPresolKnapsack)
12613	{  /*lint --e{574,715}*/
12614	   SCIP_CONSHDLRDATA* conshdlrdata;
12615	   SCIP_CONSDATA* consdata;
12616	   SCIP_CONS* cons;
12617	   SCIP_Bool cutoff;
12618	   SCIP_Bool redundant;
12619	   SCIP_Bool success;
12620	   int oldnfixedvars;
12621	   int oldnchgbds;
12622	   int oldndelconss;
12623	   int oldnaddconss;
12624	   int oldnchgcoefs;
12625	   int oldnchgsides;
12626	   int firstchange;
12627	   int c;
12628	   SCIP_Bool newchanges;
12629	
12630	   /* remember old preprocessing counters */
12631	   cutoff = FALSE;
12632	   oldnfixedvars = *nfixedvars;
12633	   oldnchgbds = *nchgbds;
12634	   oldndelconss = *ndelconss;
12635	   oldnaddconss = *naddconss;
12636	   oldnchgcoefs = *nchgcoefs;
12637	   oldnchgsides = *nchgsides;
12638	   firstchange = INT_MAX;
12639	
12640	   newchanges = (nrounds == 0 || nnewfixedvars > 0 || nnewaggrvars > 0 || nnewchgbds > 0 || nnewupgdconss > 0);
12641	
12642	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
12643	   assert(conshdlrdata != NULL);
12644	
12645	   for( c = 0; c < nconss && !SCIPisStopped(scip); c++ )
12646	   {
12647	      int thisnfixedvars;
12648	      int thisnchgbds;
12649	
12650	      cons = conss[c];
12651	      consdata = SCIPconsGetData(cons);
12652	      assert(consdata != NULL);
12653	
12654	      /* update data structures */
12655	      /* todo if UBTIGHTENED events were caught, we could move this block after the continue */
12656	      if( newchanges || *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds )
12657	      {
12658	         SCIP_CALL( applyFixings(scip, cons, &cutoff) );
12659	         if( cutoff )
12660	            break;
12661	      }
12662	
12663	      /* force presolving the constraint in the initial round */
12664	      if( nrounds == 0 )
12665	         consdata->presolvedtiming = 0;
12666	      else if( consdata->presolvedtiming >= presoltiming )
12667	         continue;
12668	
12669	      SCIPdebugMsg(scip, "presolving knapsack constraint <%s>\n", SCIPconsGetName(cons));
12670	      SCIPdebugPrintCons(scip, cons, NULL);
12671	      consdata->presolvedtiming = presoltiming;
12672	
12673	      thisnfixedvars = *nfixedvars;
12674	      thisnchgbds = *nchgbds;
12675	
12676	      /* merge constraint, so propagation works better */
12677	      SCIP_CALL( mergeMultiples(scip, cons, &cutoff) );
12678	      if( cutoff )
12679	         break;
12680	
12681	      /* add cliques in the knapsack to the clique table */
12682	      if( (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
12683	      {
12684	         SCIP_CALL( addCliques(scip, cons, conshdlrdata->cliqueextractfactor, &cutoff, nchgbds) );
12685	         if( cutoff )
12686	            break;
12687	      }
12688	
12689	      /* propagate constraint */
12690	      if( presoltiming < SCIP_PRESOLTIMING_EXHAUSTIVE )
12691	      {
12692	         SCIP_CALL( propagateCons(scip, cons, &cutoff, &redundant, nfixedvars, (presoltiming & SCIP_PRESOLTIMING_MEDIUM)) );
12693	
12694	         if( cutoff )
12695	            break;
12696	         if( redundant )
12697	         {
12698	            (*ndelconss)++;
12699	            continue;
12700	         }
12701	      }
12702	
12703	      /* remove again all fixed variables, if further fixings were found */
12704	      if( *nfixedvars > thisnfixedvars || *nchgbds > thisnchgbds )
12705	      {
12706	         SCIP_CALL( applyFixings(scip, cons, &cutoff) );
12707	         if( cutoff )
12708	            break;
12709	
12710	         thisnfixedvars = *nfixedvars;
12711	      }
12712	
12713	      if( !SCIPconsIsModifiable(cons) )
12714	      {
12715	         /* check again for redundancy (applyFixings() might have decreased weightsum due to fixed-to-zero vars) */
12716	         if( consdata->weightsum <= consdata->capacity )
12717	         {
12718	            SCIPdebugMsg(scip, " -> knapsack constraint <%s> is redundant: weightsum=%" SCIP_LONGINT_FORMAT ", capacity=%" SCIP_LONGINT_FORMAT "\n",
12719	               SCIPconsGetName(cons), consdata->weightsum, consdata->capacity);
12720	            SCIP_CALL( SCIPdelConsLocal(scip, cons) );
12721	            continue;
12722	         }
12723	
12724	         /* divide weights by their greatest common divisor */
12725	         normalizeWeights(cons, nchgcoefs, nchgsides);
12726	
12727	         /* try to simplify inequalities */
12728	         if( conshdlrdata->simplifyinequalities && (presoltiming & SCIP_PRESOLTIMING_FAST) != 0 )
12729	         {
12730	            SCIP_CALL( simplifyInequalities(scip, cons, nfixedvars, ndelconss, nchgcoefs, nchgsides, naddconss, &cutoff) );
12731	            if( cutoff )
12732	               break;
12733	
12734	            if( SCIPconsIsDeleted(cons) )
12735	               continue;
12736	
12737	            /* remove again all fixed variables, if further fixings were found */
12738	            if( *nfixedvars > thisnfixedvars )
12739	            {
12740	               SCIP_CALL(applyFixings(scip, cons, &cutoff));
12741	               if( cutoff )
12742	                  break;
12743	            }
12744	         }
12745	
12746	         /* tighten capacity and weights */
12747	         SCIP_CALL( tightenWeights(scip, cons, presoltiming, nchgcoefs, nchgsides, naddconss, ndelconss, &cutoff) );
12748	         if( cutoff )
12749	            break;
12750	
12751	         if( SCIPconsIsActive(cons) )
12752	         {
12753	            if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
12754	            {
12755	               /* in case the knapsack constraints is independent of everything else, solve the knapsack and apply the
12756	                * dual reduction
12757	                */
12758	               SCIP_CALL( dualPresolving(scip, cons, nchgbds, ndelconss, &redundant) );
12759	               if( redundant )
12760	                  continue;
12761	            }
12762	
12763	            /* check if knapsack constraint is parallel to objective function */
12764	            SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
12765	         }
12766	      }
12767	      /* remember the first changed constraint to begin the next aggregation round with */
12768	      if( firstchange == INT_MAX && consdata->presolvedtiming != SCIP_PRESOLTIMING_EXHAUSTIVE )
12769	         firstchange = c;
12770	   }
12771	
12772	   /* preprocess pairs of knapsack constraints */
12773	   if( !cutoff && conshdlrdata->presolusehashing && (presoltiming & SCIP_PRESOLTIMING_MEDIUM) != 0 )
12774	   {
12775	      /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
12776	      SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &cutoff, ndelconss) );
12777	   }
12778	
12779	   if( (*ndelconss != oldndelconss) || (*nchgsides != oldnchgsides) || (*nchgcoefs != oldnchgcoefs) || (*naddconss != oldnaddconss) )
12780	      success = TRUE;
12781	   else
12782	      success = FALSE;
12783	
12784	   if( !cutoff && firstchange < nconss && conshdlrdata->presolpairwise && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 )
12785	   {
12786	      SCIP_Longint npaircomparisons;
12787	
12788	      npaircomparisons = 0;
12789	      oldndelconss = *ndelconss;
12790	      oldnchgsides = *nchgsides;
12791	      oldnchgcoefs = *nchgcoefs;
12792	
12793	      for( c = firstchange; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
12794	      {
12795	         cons = conss[c];
12796	         if( !SCIPconsIsActive(cons) || SCIPconsIsModifiable(cons) )
12797	            continue;
12798	
12799	         npaircomparisons += ((SCIPconsGetData(cons)->presolvedtiming < SCIP_PRESOLTIMING_EXHAUSTIVE) ? (SCIP_Longint) c : ((SCIP_Longint) c - (SCIP_Longint) firstchange));
12800	
12801	         SCIP_CALL( preprocessConstraintPairs(scip, conss, firstchange, c, ndelconss) );
12802	
12803	         if( npaircomparisons > NMINCOMPARISONS )
12804	         {
12805	            if( (*ndelconss != oldndelconss) || (*nchgsides != oldnchgsides) || (*nchgcoefs != oldnchgcoefs) )
12806	               success = TRUE;
12807	            if( ((SCIP_Real) (*ndelconss - oldndelconss) + ((SCIP_Real) (*nchgsides - oldnchgsides))/2.0 +
12808	                  ((SCIP_Real) (*nchgcoefs - oldnchgcoefs))/10.0) / ((SCIP_Real) npaircomparisons) < MINGAINPERNMINCOMPARISONS )
12809	               break;
12810	            oldndelconss = *ndelconss;
12811	            oldnchgsides = *nchgsides;
12812	            oldnchgcoefs = *nchgcoefs;
12813	            npaircomparisons = 0;
12814	         }
12815	      }
12816	   }
12817	#ifdef WITH_CARDINALITY_UPGRADE
12818	   /* @todo upgrade to cardinality constraints: the code below relies on disabling the checking of the knapsack
12819	    * constraint in the original problem, because the upgrade ensures that at most the given number of continuous
12820	    * variables has a nonzero value, but not that the binary variables corresponding to the continuous variables with
12821	    * value zero are set to zero as well. This can cause problems if the user accesses the values of the binary
12822	    * variables (as the MIPLIB solution checker does), or the transformed problem is freed and the original problem
12823	    * (possibly with some user modifications) is re-optimized. Until there is a way to force the binary variables to 0
12824	    * as well, we better keep this code disabled. */
12825	   /* upgrade to cardinality constraints - only try to upgrade towards the end of presolving, since the process below is quite expensive */
12826	   if ( ! cutoff && conshdlrdata->upgdcardinality && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) && ! conshdlrdata->upgradedcard )
12827	   {
12828	      SCIP_HASHMAP* varhash;
12829	      SCIP_VAR** cardvars;
12830	      SCIP_Real* cardweights;
12831	      int noldupgdconss;
12832	      int nscipvars;
12833	      int makeupgrade;
12834	
12835	      noldupgdconss = *nupgdconss;
12836	      nscipvars = SCIPgetNVars(scip);
12837	      SCIP_CALL( SCIPallocClearBufferArray(scip, &cardvars, nscipvars) );
12838	      SCIP_CALL( SCIPallocClearBufferArray(scip, &cardweights, nscipvars) );
12839	
12840	      /* set up hash map */
12841	      SCIP_CALL( SCIPhashmapCreate(&varhash, SCIPblkmem(scip), nscipvars) );
12842	
12843	      /* We loop through all cardinality constraints twice:
12844	       * - First, determine for each binary variable the number of cardinality constraints that can be upgraded to a
12845	       *   knapsack constraint and contain this variable; this number has to coincide with the number of variable up
12846	       *   locks; otherwise it would be infeasible to delete the knapsack constraints after the constraint update.
12847	       * - Second, upgrade knapsack constraints to cardinality constraints. */
12848	      for (makeupgrade = 0; makeupgrade < 2; ++makeupgrade)
12849	      {
12850	         for (c = nconss-1; c >= 0 && ! SCIPisStopped(scip); --c)
12851	         {
12852	            SCIP_CONS* cardcons;
12853	            SCIP_VAR** vars;
12854	            SCIP_Longint* weights;
12855	            int nvars;
12856	            int v;
12857	
12858	            cons = conss[c];
12859	            assert( cons != NULL );
12860	            consdata = SCIPconsGetData(cons);
12861	            assert( consdata != NULL );
12862	
12863	            nvars = consdata->nvars;
12864	            vars = consdata->vars;
12865	            weights = consdata->weights;
12866	
12867	            /* Check, whether linear knapsack can be upgraded to a cardinality constraint:
12868	             * - all variables must be binary (always true)
12869	             * - all coefficients must be 1.0
12870	             * - the right hand side must be smaller than nvars
12871	             */
12872	            if ( consdata->capacity >= nvars )
12873	               continue;
12874	
12875	            /* the weights are sorted: check first and last weight */
12876	            assert( consdata->sorted );
12877	            if ( weights[0] != 1 || weights[nvars-1] != 1 )
12878	               continue;
12879	
12880	            /* check whether all variables are of the form 0 <= x_v <= u_v y_v for y_v \in \{0,1\} and zero objective */
12881	            for (v = 0; v < nvars; ++v)
12882	            {
12883	               SCIP_BOUNDTYPE* impltypes;
12884	               SCIP_Real* implbounds;
12885	               SCIP_VAR** implvars;
12886	               SCIP_VAR* var;
12887	               int nimpls;
12888	               int j;
12889	
12890	               var = consdata->vars[v];
12891	               assert( var != NULL );
12892	               assert( SCIPvarIsBinary(var) );
12893	
12894	               /* ignore non-active variables */
12895	               if ( ! SCIPvarIsActive(var) )
12896	                  break;
12897	
12898	               /* be sure that implication variable has zero objective */
12899	               if ( ! SCIPisZero(scip, SCIPvarGetObj(var)) )
12900	                  break;
12901	
12902	               nimpls = SCIPvarGetNImpls(var, FALSE);
12903	               implvars = SCIPvarGetImplVars(var, FALSE);
12904	               implbounds = SCIPvarGetImplBounds(var, FALSE);
12905	               impltypes = SCIPvarGetImplTypes(var, FALSE);
12906	
12907	               for (j = 0; j < nimpls; ++j)
12908	               {
12909	                  /* be sure that continuous variable is fixed to 0 */
12910	                  if ( impltypes[j] != SCIP_BOUNDTYPE_UPPER )
12911	                     continue;
12912	
12913	                  /* cannot currently deal with nonzero fixings */
12914	                  if ( ! SCIPisZero(scip, implbounds[j]) )
12915	                     continue;
12916	
12917	                  /* number of down locks should be one */
12918	                  if ( SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) != 1 )
12919	                     continue;
12920	
12921	                  cardvars[v] = implvars[j];
12922	                  cardweights[v] = (SCIP_Real) v;
12923	
12924	                  break;
12925	               }
12926	
12927	               /* found no variable upper bound candidate -> exit */
12928	               if ( j >= nimpls )
12929	                  break;
12930	            }
12931	
12932	            /* did not find fitting variable upper bound for some variable -> exit */
12933	            if ( v < nvars )
12934	               break;
12935	
12936	            /* save number of knapsack constraints that can be upgraded to a cardinality constraint,
12937	             * in which the binary variable is involved in */
12938	            if ( makeupgrade == 0 )
12939	            {
12940	               for (v = 0; v < nvars; ++v)
12941	               {
12942	                  if ( SCIPhashmapExists(varhash, vars[v]) )
12943	                  {
12944	                     int image;
12945	
12946	                     image = SCIPhashmapGetImageInt(varhash, vars[v]);
12947	                     SCIP_CALL( SCIPhashmapSetImageInt(varhash, vars[v], image + 1) );
12948	                     assert( image + 1 == SCIPhashmapGetImageInt(varhash, vars[v]) );
12949	                  }
12950	                  else
12951	                  {
12952	                     SCIP_CALL( SCIPhashmapInsertInt(varhash, vars[v], 1) );
12953	                     assert( 1 == SCIPhashmapGetImageInt(varhash, vars[v]) );
12954	                     assert( SCIPhashmapExists(varhash, vars[v]) );
12955	                  }
12956	               }
12957	            }
12958	            else
12959	            {
12960	               SCIP_CONS* origcons;
12961	
12962	               /* for each variable: check whether the number of cardinality constraints that can be upgraded to a
12963	                * knapsack constraint coincides with the number of variable up locks */
12964	               for (v = 0; v < nvars; ++v)
12965	               {
12966	                  assert( SCIPhashmapExists(varhash, vars[v]) );
12967	                  if ( SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) != SCIPhashmapGetImageInt(varhash, vars[v]) )
12968	                     break;
12969	               }
12970	               if ( v < nvars )
12971	                  break;
12972	
12973	               /* store that we have upgraded */
12974	               conshdlrdata->upgradedcard = TRUE;
12975	
12976	               /* at this point we found suitable variable upper bounds */
12977	               SCIPdebugMessage("Upgrading knapsack constraint <%s> to cardinality constraint ...\n", SCIPconsGetName(cons));
12978	
12979	               /* create cardinality constraint */
12980	               assert( ! SCIPconsIsModifiable(cons) );
12981	               SCIP_CALL( SCIPcreateConsCardinality(scip, &cardcons, SCIPconsGetName(cons), nvars, cardvars, (int) consdata->capacity, vars, cardweights,
12982	                     SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
12983	                     SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),
12984	                     SCIPconsIsLocal(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
12985	#ifdef SCIP_DEBUG
12986	               SCIPprintCons(scip, cons, NULL);
12987	               SCIPinfoMessage(scip, NULL, "\n");
12988	               SCIPprintCons(scip, cardcons, NULL);
12989	               SCIPinfoMessage(scip, NULL, "\n");
12990	#endif
12991	               SCIP_CALL( SCIPaddCons(scip, cardcons) );
12992	               SCIP_CALL( SCIPreleaseCons(scip, &cardcons) );
12993	               ++(*nupgdconss);
12994	
12995	               /* delete oknapsack constraint */
12996	               SCIP_CALL( SCIPdelCons(scip, cons) );
12997	               ++(*ndelconss);
12998	
12999	               /* We need to disable the original knapsack constraint, since it might happen that the binary variables
13000	                * are 1 although the continuous variables are 0. Thus, the knapsack constraint might be violated,
13001	                * although the cardinality constraint is satisfied. */
13002	               origcons = SCIPfindOrigCons(scip, SCIPconsGetName(cons));
13003	               assert( origcons != NULL );
13004	               SCIP_CALL( SCIPsetConsChecked(scip, origcons, FALSE) );
13005	
13006	               for (v = 0; v < nvars; ++v)
13007	               {
13008	                  int image;
13009	
13010	                  assert ( SCIPhashmapExists(varhash, vars[v]) );
13011	                  image = SCIPhashmapGetImageInt(varhash, vars[v]);
13012	                  SCIP_CALL( SCIPhashmapSetImageInt(varhash, vars[v], image - 1) );
13013	                  assert( image - 1 == SCIPhashmapGetImageInt(varhash, vars[v]) );
13014	               }
13015	            }
13016	         }
13017	      }
13018	      SCIPhashmapFree(&varhash);
13019	      SCIPfreeBufferArray(scip, &cardweights);
13020	      SCIPfreeBufferArray(scip, &cardvars);
13021	
13022	      if ( *nupgdconss > noldupgdconss )
13023	         success = TRUE;
13024	   }
13025	#endif
13026	
13027	   if( cutoff )
13028	      *result = SCIP_CUTOFF;
13029	   else if( success || *nfixedvars > oldnfixedvars || *nchgbds > oldnchgbds )
13030	      *result = SCIP_SUCCESS;
13031	   else
13032	      *result = SCIP_DIDNOTFIND;
13033	
13034	   return SCIP_OKAY;
13035	}
13036	
13037	/** propagation conflict resolving method of constraint handler */
13038	static
13039	SCIP_DECL_CONSRESPROP(consRespropKnapsack)
13040	{  /*lint --e{715}*/
13041	   SCIP_CONSDATA* consdata;
13042	   SCIP_Longint capsum;
13043	   int i;
13044	
13045	   assert(result != NULL);
13046	
13047	   consdata = SCIPconsGetData(cons);
13048	   assert(consdata != NULL);
13049	
13050	   /* check if we fixed a binary variable to one (due to negated clique) */
13051	   if( inferinfo >= 0 && SCIPvarGetLbLocal(infervar) > 0.5 )
13052	   {
13053	      for( i = 0; i < consdata->nvars; ++i )
13054	      {
13055	         if( SCIPvarGetIndex(consdata->vars[i]) == inferinfo )
13056	         {
13057	            assert( SCIPgetVarUbAtIndex(scip, consdata->vars[i], bdchgidx, FALSE) < 0.5 );
13058	            SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[i]) );
13059	            break;
13060	         }
13061	      }
13062	      assert(i < consdata->nvars);
13063	   }
13064	   else
13065	   {
13066	      /* according to negated cliques the minweightsum and all variables which are fixed to one which led to a fixing of
13067	       * another negated clique variable to one, the inferinfo was chosen to be the negative of the position in the
13068	       * knapsack constraint, see one above call of SCIPinferBinvarCons
13069	       */
13070	      if( inferinfo < 0 )
13071	         capsum = 0;
13072	      else
13073	      {
13074	         /* locate the inference variable and calculate the capacity that has to be used up to conclude infervar == 0;
13075	          * inferinfo stores the position of the inference variable (but maybe the variables were resorted)
13076	          */
13077	         if( inferinfo < consdata->nvars && consdata->vars[inferinfo] == infervar )
13078	            capsum = consdata->weights[inferinfo];
13079	         else
13080	         {
13081	            for( i = 0; i < consdata->nvars && consdata->vars[i] != infervar; ++i )
13082	            {}
13083	            assert(i < consdata->nvars);
13084	            capsum = consdata->weights[i];
13085	         }
13086	      }
13087	
13088	      /* add fixed-to-one variables up to the point, that their weight plus the weight of the conflict variable exceeds
13089	       * the capacity
13090	       */
13091	      if( capsum <= consdata->capacity )
13092	      {
13093	         for( i = 0; i < consdata->nvars; i++ )
13094	         {
13095	            if( SCIPgetVarLbAtIndex(scip, consdata->vars[i], bdchgidx, FALSE) > 0.5 )
13096	            {
13097	               SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->vars[i]) );
13098	               capsum += consdata->weights[i];
13099	               if( capsum > consdata->capacity )
13100	                  break;
13101	            }
13102	         }
13103	      }
13104	   }
13105	
13106	   /* NOTE: It might be the case that capsum < consdata->capacity. This is due the fact that the fixing of the variable
13107	    *       to zero can included negated clique information. A negated clique means, that at most one of the clique
13108	    *       variables can be zero. These information can be used to compute a minimum activity of the constraint and
13109	    *       used to fix variables to zero.
13110	    *
13111	    *       Even if capsum < consdata->capacity we still reported a complete reason since the minimum activity is based
13112	    *       on global variable bounds. It might even be the case that we reported to many variables which are fixed to
13113	    *       one.
13114	    */
13115	   *result = SCIP_SUCCESS;
13116	
13117	   return SCIP_OKAY;
13118	}
13119	
13120	/** variable rounding lock method of constraint handler */
13121	/**! [SnippetConsLockKnapsack] */
13122	static
13123	SCIP_DECL_CONSLOCK(consLockKnapsack)
13124	{  /*lint --e{715}*/
13125	   SCIP_CONSDATA* consdata;
13126	   int i;
13127	
13128	   consdata = SCIPconsGetData(cons);
13129	   assert(consdata != NULL);
13130	
13131	   for( i = 0; i < consdata->nvars; i++)
13132	   {
13133	      SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
13134	   }
13135	
13136	   return SCIP_OKAY;
13137	}
13138	/**! [SnippetConsLockKnapsack] */
13139	
13140	/** constraint activation notification method of constraint handler */
13141	static
13142	SCIP_DECL_CONSACTIVE(consActiveKnapsack)
13143	{  /*lint --e{715}*/
13144	   if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisNLPConstructed(scip) )
13145	   {
13146	      SCIP_CALL( addNlrow(scip, cons) );
13147	   }
13148	
13149	   return SCIP_OKAY;
13150	}
13151	
13152	/** constraint deactivation notification method of constraint handler */
13153	static
13154	SCIP_DECL_CONSDEACTIVE(consDeactiveKnapsack)
13155	{  /*lint --e{715}*/
13156	   SCIP_CONSDATA* consdata;
13157	
13158	   assert(cons != NULL);
13159	
13160	   consdata = SCIPconsGetData(cons);
13161	   assert(consdata != NULL);
13162	
13163	   /* remove row from NLP, if still in solving
13164	    * if we are in exitsolve, the whole NLP will be freed anyway
13165	    */
13166	   if( SCIPgetStage(scip) == SCIP_STAGE_SOLVING && consdata->nlrow != NULL )
13167	   {
13168	      SCIP_CALL( SCIPdelNlRow(scip, consdata->nlrow) );
13169	   }
13170	
13171	   return SCIP_OKAY;
13172	}
13173	
13174	/** variable deletion method of constraint handler */
13175	static
13176	SCIP_DECL_CONSDELVARS(consDelvarsKnapsack)
13177	{
13178	   assert(scip != NULL);
13179	   assert(conshdlr != NULL);
13180	   assert(conss != NULL || nconss == 0);
13181	
13182	   if( nconss > 0 )
13183	   {
13184	      SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
13185	   }
13186	
13187	   return SCIP_OKAY;
13188	}
13189	
13190	/** constraint display method of constraint handler */
13191	static
13192	SCIP_DECL_CONSPRINT(consPrintKnapsack)
13193	{  /*lint --e{715}*/
13194	   SCIP_CONSDATA* consdata;
13195	   int i;
13196	
13197	   assert( scip != NULL );
13198	   assert( conshdlr != NULL );
13199	   assert( cons != NULL );
13200	
13201	   consdata = SCIPconsGetData(cons);
13202	   assert(consdata != NULL);
13203	
13204	   for( i = 0; i < consdata->nvars; ++i )
13205	   {
13206	      if( i > 0 )
13207	         SCIPinfoMessage(scip, file, " ");
13208	      SCIPinfoMessage(scip, file, "%+" SCIP_LONGINT_FORMAT, consdata->weights[i]);
13209	      SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[i], TRUE) );
13210	   }
13211	   SCIPinfoMessage(scip, file, " <= %" SCIP_LONGINT_FORMAT "", consdata->capacity);
13212	
13213	   return SCIP_OKAY;
13214	}
13215	
13216	/** constraint copying method of constraint handler */
13217	static
13218	SCIP_DECL_CONSCOPY(consCopyKnapsack)
13219	{  /*lint --e{715}*/
13220	   SCIP_VAR** sourcevars;
13221	   SCIP_Longint* weights;
13222	   SCIP_Real* coefs;
13223	   const char* consname;
13224	   int nvars;
13225	   int v;
13226	
13227	   /* get variables and coefficients of the source constraint */
13228	   sourcevars = SCIPgetVarsKnapsack(sourcescip, sourcecons);
13229	   nvars = SCIPgetNVarsKnapsack(sourcescip, sourcecons);
13230	   weights = SCIPgetWeightsKnapsack(sourcescip, sourcecons);
13231	
13232	   SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
13233	   for( v = 0; v < nvars; ++v )
13234	      coefs[v] = (SCIP_Real) weights[v];
13235	
13236	   if( name != NULL )
13237	      consname = name;
13238	   else
13239	      consname = SCIPconsGetName(sourcecons);
13240	
13241	   /* copy the logic using the linear constraint copy method */
13242	   SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, coefs,
13243	         -SCIPinfinity(scip), (SCIP_Real) SCIPgetCapacityKnapsack(sourcescip, sourcecons), varmap, consmap,
13244	         initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
13245	   assert(cons != NULL);
13246	
13247	   SCIPfreeBufferArray(scip, &coefs);
13248	
13249	   return SCIP_OKAY;
13250	}
13251	
13252	/** constraint parsing method of constraint handler */
13253	static
13254	SCIP_DECL_CONSPARSE(consParseKnapsack)
13255	{  /*lint --e{715}*/
13256	   SCIP_VAR* var;
13257	   SCIP_Longint weight;
13258	   SCIP_VAR** vars;
13259	   SCIP_Longint* weights;
13260	   SCIP_Longint capacity;
13261	   char* endptr;
13262	   int nread;
13263	   int nvars;
13264	   int varssize;
13265	
13266	   assert(scip != NULL);
13267	   assert(success != NULL);
13268	   assert(str != NULL);
13269	   assert(name != NULL);
13270	   assert(cons != NULL);
13271	
13272	   *success = TRUE;
13273	
13274	   nvars = 0;
13275	   varssize = 5;
13276	   SCIP_CALL( SCIPallocBufferArray(scip, &vars,    varssize) );
13277	   SCIP_CALL( SCIPallocBufferArray(scip, &weights, varssize) );
13278	
13279	   while( *str != '\0' )
13280	   {
13281	      /* try to parse coefficient, and use 1 if not successful */
13282	      weight = 1;
13283	      nread = 0;
13284	      sscanf(str, "%" SCIP_LONGINT_FORMAT "%n", &weight, &nread);
13285	      str += nread;
13286	
13287	      /* parse variable name */
13288	      SCIP_CALL( SCIPparseVarName(scip, str, &var, &endptr) );
13289	
13290	      if( var == NULL )
13291	      {
13292	         endptr = strchr(endptr, '<');
13293	
13294	         if( endptr == NULL )
13295	         {
13296	            SCIPerrorMessage("no capacity found\n");
13297	            *success = FALSE;
13298	         }
13299	         else
13300	            str = endptr;
13301	
13302	         break;
13303	      }
13304	
13305	      str = endptr;
13306	
13307	      /* store weight and variable */
13308	      if( varssize <= nvars )
13309	      {
13310	         varssize = SCIPcalcMemGrowSize(scip, varssize+1);
13311	         SCIP_CALL( SCIPreallocBufferArray(scip, &vars,    varssize) );
13312	         SCIP_CALL( SCIPreallocBufferArray(scip, &weights, varssize) );
13313	      }
13314	
13315	      vars[nvars]    = var;
13316	      weights[nvars] = weight;
13317	      ++nvars;
13318	
13319	      /* skip whitespace */
13320	      SCIP_CALL( SCIPskipSpace((char**)&str) );
13321	   }
13322	
13323	   if( *success )
13324	   {
13325	      if( strncmp(str, "<=", 2) != 0 )
13326	      {
13327	         SCIPerrorMessage("expected '<=' at begin of '%s'\n", str);
13328	         *success = FALSE;
13329	      }
13330	      else
13331	      {
13332	         str += 2;
13333	      }
13334	   }
13335	
13336	   if( *success )
13337	   {
13338	      /* skip whitespace */
13339	      SCIP_CALL( SCIPskipSpace((char**)&str) );
13340	
13341	      /* coverity[secure_coding] */
13342	      if( sscanf(str, "%" SCIP_LONGINT_FORMAT, &capacity) != 1 )
13343	      {
13344	         SCIPerrorMessage("error parsing capacity from '%s'\n", str);
13345	         *success = FALSE;
13346	      }
13347	      else
13348	      {
13349		 SCIP_CALL( SCIPcreateConsKnapsack(scip, cons, name, nvars, vars, weights, capacity,
13350		       initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
13351	      }
13352	   }
13353	
13354	   SCIPfreeBufferArray(scip, &vars);
13355	   SCIPfreeBufferArray(scip, &weights);
13356	
13357	   return SCIP_OKAY;
13358	}
13359	
13360	/** constraint method of constraint handler which returns the variables (if possible) */
13361	static
13362	SCIP_DECL_CONSGETVARS(consGetVarsKnapsack)
13363	{  /*lint --e{715}*/
13364	   SCIP_CONSDATA* consdata;
13365	
13366	   consdata = SCIPconsGetData(cons);
13367	   assert(consdata != NULL);
13368	
13369	   if( varssize < consdata->nvars )
13370	      (*success) = FALSE;
13371	   else
13372	   {
13373	      assert(vars != NULL);
13374	
13375	      BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
13376	      (*success) = TRUE;
13377	   }
13378	
13379	   return SCIP_OKAY;
13380	}
13381	
13382	/** constraint method of constraint handler which returns the number of variables (if possible) */
13383	static
13384	SCIP_DECL_CONSGETNVARS(consGetNVarsKnapsack)
13385	{  /*lint --e{715}*/
13386	   SCIP_CONSDATA* consdata;
13387	
13388	   consdata = SCIPconsGetData(cons);
13389	   assert(consdata != NULL);
13390	
13391	   (*nvars) = consdata->nvars;
13392	   (*success) = TRUE;
13393	
13394	   return SCIP_OKAY;
13395	}
13396	
13397	/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
13398	static
13399	SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphKnapsack)
13400	{  /*lint --e{715}*/
13401	   SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_PERM, cons, graph, success) );
13402	
13403	   return SCIP_OKAY;
13404	}
13405	
13406	/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
13407	static
13408	SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphKnapsack)
13409	{  /*lint --e{715}*/
13410	   SCIP_CALL( addSymmetryInformation(scip, SYM_SYMTYPE_SIGNPERM, cons, graph, success) );
13411	
13412	   return SCIP_OKAY;
13413	}
13414	
13415	/*
13416	 * Event handler
13417	 */
13418	
13419	/** execution method of bound change event handler */
13420	static
13421	SCIP_DECL_EVENTEXEC(eventExecKnapsack)
13422	{  /*lint --e{715}*/
13423	   SCIP_CONSDATA* consdata;
13424	
13425	   assert(eventdata != NULL);
13426	   assert(eventdata->cons != NULL);
13427	
13428	   consdata = SCIPconsGetData(eventdata->cons);
13429	   assert(consdata != NULL);
13430	
13431	   switch( SCIPeventGetType(event) )
13432	   {
13433	   case SCIP_EVENTTYPE_LBTIGHTENED:
13434	      consdata->onesweightsum += eventdata->weight;
13435	      consdata->presolvedtiming = 0;
13436	      SCIP_CALL( SCIPmarkConsPropagate(scip, eventdata->cons) );
13437	      break;
13438	   case SCIP_EVENTTYPE_LBRELAXED:
13439	      consdata->onesweightsum -= eventdata->weight;
13440	      break;
13441	   case SCIP_EVENTTYPE_UBTIGHTENED:
13442	      consdata->presolvedtiming = 0;
13443	      SCIP_CALL( SCIPmarkConsPropagate(scip, eventdata->cons) );
13444	      break;
13445	   case SCIP_EVENTTYPE_VARFIXED:  /* the variable should be removed from the constraint in presolving */
13446	      if( !consdata->existmultaggr )
13447	      {
13448	         SCIP_VAR* var;
13449	         var = SCIPeventGetVar(event);
13450	         assert(var != NULL);
13451	
13452	         /* if the variable was aggregated or multiaggregated, we must signal to propagation that we are no longer merged */
13453	         if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
13454	         {
13455	            consdata->existmultaggr = TRUE;
13456	            consdata->merged = FALSE;
13457	         }
13458	         else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED ||
13459	            (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED && SCIPvarGetStatus(SCIPvarGetNegatedVar(var)) == SCIP_VARSTATUS_AGGREGATED) )
13460	            consdata->merged = FALSE;
13461	      }
13462	      /*lint -fallthrough*/
13463	   case SCIP_EVENTTYPE_IMPLADDED: /* further preprocessing might be possible due to additional implications */
13464	      consdata->presolvedtiming = 0;
13465	      break;
13466	   case SCIP_EVENTTYPE_VARDELETED:
13467	      consdata->varsdeleted = TRUE;
13468	      break;
13469	   default:
13470	      SCIPerrorMessage("invalid event type %" SCIP_EVENTTYPE_FORMAT "\n", SCIPeventGetType(event));
13471	      return SCIP_INVALIDDATA;
13472	   }
13473	
13474	   return SCIP_OKAY;
13475	}
13476	
13477	
13478	/*
13479	 * constraint specific interface methods
13480	 */
13481	
13482	/** creates the handler for knapsack constraints and includes it in SCIP */
13483	SCIP_RETCODE SCIPincludeConshdlrKnapsack(
13484	   SCIP*                 scip                /**< SCIP data structure */
13485	   )
13486	{
13487	   SCIP_EVENTHDLRDATA* eventhdlrdata;
13488	   SCIP_CONSHDLRDATA* conshdlrdata;
13489	   SCIP_CONSHDLR* conshdlr;
13490	
13491	   /* create knapsack constraint handler data */
13492	   SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
13493	
13494	   /* include event handler for bound change events */
13495	   eventhdlrdata = NULL;
13496	   conshdlrdata->eventhdlr = NULL;
13497	   SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &(conshdlrdata->eventhdlr), EVENTHDLR_NAME, EVENTHDLR_DESC,
13498	         eventExecKnapsack, eventhdlrdata) );
13499	
13500	   /* get event handler for bound change events */
13501	   if( conshdlrdata->eventhdlr == NULL )
13502	   {
13503	      SCIPerrorMessage("event handler for knapsack constraints not found\n");
13504	      return SCIP_PLUGINNOTFOUND;
13505	   }
13506	
13507	   /* include constraint handler */
13508	   SCIP_CALL( SCIPincludeConshdlrBasic(scip, &conshdlr, CONSHDLR_NAME, CONSHDLR_DESC,
13509	         CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY, CONSHDLR_EAGERFREQ, CONSHDLR_NEEDSCONS,
13510	         consEnfolpKnapsack, consEnfopsKnapsack, consCheckKnapsack, consLockKnapsack,
13511	         conshdlrdata) );
13512	
13513	   assert(conshdlr != NULL);
13514	
13515	   /* set non-fundamental callbacks via specific setter functions */
13516	   SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyKnapsack, consCopyKnapsack) );
13517	   SCIP_CALL( SCIPsetConshdlrActive(scip, conshdlr, consActiveKnapsack) );
13518	   SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveKnapsack) );
13519	   SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteKnapsack) );
13520	   SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsKnapsack) );
13521	   SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitKnapsack) );
13522	   SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreKnapsack) );
13523	   SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolKnapsack) );
13524	   SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolKnapsack) );
13525	   SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeKnapsack) );
13526	   SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsKnapsack) );
13527	   SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsKnapsack) );
13528	   SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitKnapsack) );
13529	   SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreKnapsack) );
13530	   SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpKnapsack) );
13531	   SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseKnapsack) );
13532	   SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolKnapsack,CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
13533	   SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintKnapsack) );
13534	   SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropKnapsack, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
13535	         CONSHDLR_PROP_TIMING) );
13536	   SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropKnapsack) );
13537	   SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpKnapsack, consSepasolKnapsack, CONSHDLR_SEPAFREQ,
13538	         CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
13539	   SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransKnapsack) );
13540	   SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxKnapsack) );
13541	   SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphKnapsack) );
13542	   SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphKnapsack) );
13543	
13544	   if( SCIPfindConshdlr(scip,"linear") != NULL )
13545	   {
13546	      /* include the linear constraint to knapsack constraint upgrade in the linear constraint handler */
13547	      SCIP_CALL( SCIPincludeLinconsUpgrade(scip, linconsUpgdKnapsack, LINCONSUPGD_PRIORITY, CONSHDLR_NAME) );
13548	   }
13549	
13550	   /* add knapsack constraint handler parameters */
13551	   SCIP_CALL( SCIPaddIntParam(scip,
13552	         "constraints/" CONSHDLR_NAME "/sepacardfreq",
13553	         "multiplier on separation frequency, how often knapsack cuts are separated (-1: never, 0: only at root)",
13554	         &conshdlrdata->sepacardfreq, TRUE, DEFAULT_SEPACARDFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
13555	   SCIP_CALL( SCIPaddRealParam(scip,
13556	         "constraints/" CONSHDLR_NAME "/maxcardbounddist",
13557	         "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cuts",
13558	         &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
13559	   SCIP_CALL( SCIPaddRealParam(scip,
13560	         "constraints/" CONSHDLR_NAME "/cliqueextractfactor",
13561	         "lower clique size limit for greedy clique extraction algorithm (relative to largest clique)",
13562	         &conshdlrdata->cliqueextractfactor, TRUE, DEFAULT_CLIQUEEXTRACTFACTOR, 0.0, 1.0, NULL, NULL) );
13563	   SCIP_CALL( SCIPaddIntParam(scip,
13564	         "constraints/" CONSHDLR_NAME "/maxrounds",
13565	         "maximal number of separation rounds per node (-1: unlimited)",
13566	         &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
13567	   SCIP_CALL( SCIPaddIntParam(scip,
13568	         "constraints/" CONSHDLR_NAME "/maxroundsroot",
13569	         "maximal number of separation rounds per node in the root node (-1: unlimited)",
13570	         &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
13571	   SCIP_CALL( SCIPaddIntParam(scip,
13572	         "constraints/" CONSHDLR_NAME "/maxsepacuts",
13573	         "maximal number of cuts separated per separation round",
13574	         &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
13575	   SCIP_CALL( SCIPaddIntParam(scip,
13576	         "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
13577	         "maximal number of cuts separated per separation round in the root node",
13578	         &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
13579	   SCIP_CALL( SCIPaddBoolParam(scip,
13580	         "constraints/" CONSHDLR_NAME "/disaggregation",
13581	         "should disaggregation of knapsack constraints be allowed in preprocessing?",
13582	         &conshdlrdata->disaggregation, TRUE, DEFAULT_DISAGGREGATION, NULL, NULL) );
13583	   SCIP_CALL( SCIPaddBoolParam(scip,
13584	         "constraints/" CONSHDLR_NAME "/simplifyinequalities",
13585	         "should presolving try to simplify knapsacks",
13586	         &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
13587	   SCIP_CALL( SCIPaddBoolParam(scip,
13588	         "constraints/" CONSHDLR_NAME "/negatedclique",
13589	         "should negated clique information be used in solving process",
13590	         &conshdlrdata->negatedclique, TRUE, DEFAULT_NEGATEDCLIQUE, NULL, NULL) );
13591	   SCIP_CALL( SCIPaddBoolParam(scip,
13592	         "constraints/" CONSHDLR_NAME "/presolpairwise",
13593	         "should pairwise constraint comparison be performed in presolving?",
13594	         &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
13595	   SCIP_CALL( SCIPaddBoolParam(scip,
13596	         "constraints/" CONSHDLR_NAME "/presolusehashing",
13597	         "should hash table be used for detecting redundant constraints in advance",
13598	         &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
13599	   SCIP_CALL( SCIPaddBoolParam(scip,
13600	         "constraints/" CONSHDLR_NAME "/dualpresolving",
13601	         "should dual presolving steps be performed?",
13602	         &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
13603	   SCIP_CALL( SCIPaddBoolParam(scip,
13604	         "constraints/" CONSHDLR_NAME "/usegubs",
13605	         "should GUB information be used for separation?",
13606	         &conshdlrdata->usegubs, TRUE, DEFAULT_USEGUBS, NULL, NULL) );
13607	   SCIP_CALL( SCIPaddBoolParam(scip,
13608	         "constraints/" CONSHDLR_NAME "/detectcutoffbound",
13609	         "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
13610	         &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
13611	   SCIP_CALL( SCIPaddBoolParam(scip,
13612	         "constraints/" CONSHDLR_NAME "/detectlowerbound",
13613	         "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
13614	         &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
13615	    SCIP_CALL( SCIPaddBoolParam(scip,
13616	          "constraints/" CONSHDLR_NAME "/updatecliquepartitions",
13617	          "should clique partition information be updated when old partition seems outdated?",
13618	          &conshdlrdata->updatecliquepartitions, TRUE, DEFAULT_UPDATECLIQUEPARTITIONS, NULL, NULL) );
13619	    SCIP_CALL( SCIPaddRealParam(scip,
13620	          "constraints/" CONSHDLR_NAME "/clqpartupdatefac",
13621	          "factor on the growth of global cliques to decide when to update a previous "
13622	          "(negated) clique partition (used only if updatecliquepartitions is set to TRUE)",
13623	          &conshdlrdata->clqpartupdatefac, TRUE, DEFAULT_CLQPARTUPDATEFAC, 1.0, 10.0, NULL, NULL) );
13624	#ifdef WITH_CARDINALITY_UPGRADE
13625	    SCIP_CALL( SCIPaddBoolParam(scip,
13626	         "constraints/" CONSHDLR_NAME "/upgdcardinality",
13627	         "if TRUE then try to update knapsack constraints to cardinality constraints",
13628	         &conshdlrdata->upgdcardinality, TRUE, DEFAULT_UPGDCARDINALITY, NULL, NULL) );
13629	#endif
13630	   return SCIP_OKAY;
13631	}
13632	
13633	/** creates and captures a knapsack constraint
13634	 *
13635	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
13636	 */
13637	/**! [SnippetConsCreationKnapsack] */
13638	SCIP_RETCODE SCIPcreateConsKnapsack(
13639	   SCIP*                 scip,               /**< SCIP data structure */
13640	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
13641	   const char*           name,               /**< name of constraint */
13642	   int                   nvars,              /**< number of items in the knapsack */
13643	   SCIP_VAR**            vars,               /**< array with item variables */
13644	   SCIP_Longint*         weights,            /**< array with item weights */
13645	   SCIP_Longint          capacity,           /**< capacity of knapsack (right hand side of inequality) */
13646	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
13647	                                              *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
13648	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
13649	                                              *   Usually set to TRUE. */
13650	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
13651	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
13652	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
13653	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
13654	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
13655	                                              *   Usually set to TRUE. */
13656	   SCIP_Bool             local,              /**< is constraint only valid locally?
13657	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
13658	   SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)?
13659	                                              *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
13660	                                              *   adds coefficients to this constraint. */
13661	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
13662	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
13663	                                              *   are separated as constraints. */
13664	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
13665	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
13666	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
13667	                                              *   if it may be moved to a more global node?
13668	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
13669	   )
13670	{
13671	   SCIP_CONSHDLRDATA* conshdlrdata;
13672	   SCIP_CONSHDLR* conshdlr;
13673	   SCIP_CONSDATA* consdata;
13674	
13675	   /* find the knapsack constraint handler */
13676	   conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
13677	   if( conshdlr == NULL )
13678	   {
13679	      SCIPerrorMessage("knapsack constraint handler not found\n");
13680	      return SCIP_PLUGINNOTFOUND;
13681	   }
13682	
13683	   /* get event handler */
13684	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
13685	   assert(conshdlrdata != NULL);
13686	   assert(conshdlrdata->eventhdlr != NULL);
13687	
13688	   /* create constraint data */
13689	   SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, weights, capacity) );
13690	
13691	   /* create constraint */
13692	   SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
13693	         local, modifiable, dynamic, removable, stickingatnode) );
13694	
13695	   /* catch events for variables */
13696	   if( SCIPisTransformed(scip) )
13697	   {
13698	      SCIP_CALL( catchEvents(scip, *cons, consdata, conshdlrdata->eventhdlr) );
13699	   }
13700	
13701	   return SCIP_OKAY;
13702	}
13703	/**! [SnippetConsCreationKnapsack] */
13704	
13705	/** creates and captures a knapsack constraint
13706	 *  in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
13707	 *  method SCIPcreateConsKnapsack(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
13708	 *
13709	 *  @see SCIPcreateConsKnapsack() for information about the basic constraint flag configuration
13710	 *
13711	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
13712	 */
13713	SCIP_RETCODE SCIPcreateConsBasicKnapsack(
13714	   SCIP*                 scip,               /**< SCIP data structure */
13715	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
13716	   const char*           name,               /**< name of constraint */
13717	   int                   nvars,              /**< number of items in the knapsack */
13718	   SCIP_VAR**            vars,               /**< array with item variables */
13719	   SCIP_Longint*         weights,            /**< array with item weights */
13720	   SCIP_Longint          capacity            /**< capacity of knapsack */
13721	   )
13722	{
13723	   assert(scip != NULL);
13724	
13725	   SCIP_CALL( SCIPcreateConsKnapsack(scip, cons, name, nvars, vars, weights, capacity,
13726	         TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
13727	
13728	   return SCIP_OKAY;
13729	}
13730	
13731	/** adds new item to knapsack constraint */
13732	SCIP_RETCODE SCIPaddCoefKnapsack(
13733	   SCIP*                 scip,               /**< SCIP data structure */
13734	   SCIP_CONS*            cons,               /**< constraint data */
13735	   SCIP_VAR*             var,                /**< item variable */
13736	   SCIP_Longint          weight              /**< item weight */
13737	   )
13738	{
13739	   assert(var != NULL);
13740	   assert(scip != NULL);
13741	
13742	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
13743	   {
13744	      SCIPerrorMessage("constraint is not a knapsack constraint\n");
13745	      return SCIP_INVALIDDATA;
13746	   }
13747	
13748	   SCIP_CALL( addCoef(scip, cons, var, weight) );
13749	
13750	   return SCIP_OKAY;
13751	}
13752	
13753	/** gets the capacity of the knapsack constraint */
13754	SCIP_Longint SCIPgetCapacityKnapsack(
13755	   SCIP*                 scip,               /**< SCIP data structure */
13756	   SCIP_CONS*            cons                /**< constraint data */
13757	   )
13758	{
13759	   SCIP_CONSDATA* consdata;
13760	
13761	   assert(scip != NULL);
13762	
13763	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
13764	   {
13765	      SCIPerrorMessage("constraint is not a knapsack constraint\n");
13766	      SCIPABORT();
13767	      return 0;  /*lint !e527*/
13768	   }
13769	
13770	   consdata = SCIPconsGetData(cons);
13771	   assert(consdata != NULL);
13772	
13773	   return consdata->capacity;
13774	}
13775	
13776	/** changes capacity of the knapsack constraint
13777	 *
13778	 *  @note This method can only be called during problem creation stage (SCIP_STAGE_PROBLEM)
13779	 */
13780	SCIP_RETCODE SCIPchgCapacityKnapsack(
13781	   SCIP*                 scip,               /**< SCIP data structure */
13782	   SCIP_CONS*            cons,               /**< constraint data */
13783	   SCIP_Longint          capacity            /**< new capacity of knapsack */
13784	   )
13785	{
13786	   SCIP_CONSDATA* consdata;
13787	
13788	   assert(scip != NULL);
13789	
13790	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
13791	   {
13792	      SCIPerrorMessage("constraint is not a knapsack constraint\n");
13793	      return SCIP_INVALIDDATA;
13794	   }
13795	
13796	   if( SCIPgetStage(scip) != SCIP_STAGE_PROBLEM )
13797	   {
13798	      SCIPerrorMessage("method can only be called during problem creation stage\n");
13799	      return SCIP_INVALIDDATA;
13800	   }
13801	
13802	   consdata = SCIPconsGetData(cons);
13803	   assert(consdata != NULL);
13804	
13805	   consdata->capacity = capacity;
13806	
13807	   return SCIP_OKAY;
13808	}
13809	
13810	/** gets the number of items in the knapsack constraint */
13811	int SCIPgetNVarsKnapsack(
13812	   SCIP*                 scip,               /**< SCIP data structure */
13813	   SCIP_CONS*            cons                /**< constraint data */
13814	   )
13815	{
13816	   SCIP_CONSDATA* consdata;
13817	
13818	   assert(scip != NULL);
13819	
13820	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
13821	   {
13822	      SCIPerrorMessage("constraint is not a knapsack constraint\n");
13823	      SCIPABORT();
13824	      return -1;  /*lint !e527*/
13825	   }
13826	
13827	   consdata = SCIPconsGetData(cons);
13828	   assert(consdata != NULL);
13829	
13830	   return consdata->nvars;
13831	}
13832	
13833	/** gets the array of variables in the knapsack constraint; the user must not modify this array! */
13834	SCIP_VAR** SCIPgetVarsKnapsack(
13835	   SCIP*                 scip,               /**< SCIP data structure */
13836	   SCIP_CONS*            cons                /**< constraint data */
13837	   )
13838	{
13839	   SCIP_CONSDATA* consdata;
13840	
13841	   assert(scip != NULL);
13842	
13843	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
13844	   {
13845	      SCIPerrorMessage("constraint is not a knapsack constraint\n");
13846	      SCIPABORT();
13847	      return NULL;  /*lint !e527*/
13848	   }
13849	
13850	   consdata = SCIPconsGetData(cons);
13851	   assert(consdata != NULL);
13852	
13853	   return consdata->vars;
13854	}
13855	
13856	/** gets the array of weights in the knapsack constraint; the user must not modify this array! */
13857	SCIP_Longint* SCIPgetWeightsKnapsack(
13858	   SCIP*                 scip,               /**< SCIP data structure */
13859	   SCIP_CONS*            cons                /**< constraint data */
13860	   )
13861	{
13862	   SCIP_CONSDATA* consdata;
13863	
13864	   assert(scip != NULL);
13865	
13866	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
13867	   {
13868	      SCIPerrorMessage("constraint is not a knapsack constraint\n");
13869	      SCIPABORT();
13870	      return NULL;  /*lint !e527*/
13871	   }
13872	
13873	   consdata = SCIPconsGetData(cons);
13874	   assert(consdata != NULL);
13875	
13876	   return consdata->weights;
13877	}
13878	
13879	/** gets the dual solution of the knapsack constraint in the current LP */
13880	SCIP_Real SCIPgetDualsolKnapsack(
13881	   SCIP*                 scip,               /**< SCIP data structure */
13882	   SCIP_CONS*            cons                /**< constraint data */
13883	   )
13884	{
13885	   SCIP_CONSDATA* consdata;
13886	
13887	   assert(scip != NULL);
13888	
13889	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
13890	   {
13891	      SCIPerrorMessage("constraint is not a knapsack constraint\n");
13892	      SCIPABORT();
13893	      return SCIP_INVALID;  /*lint !e527*/
13894	   }
13895	
13896	   consdata = SCIPconsGetData(cons);
13897	   assert(consdata != NULL);
13898	
13899	   if( consdata->row != NULL )
13900	      return SCIProwGetDualsol(consdata->row);
13901	   else
13902	      return 0.0;
13903	}
13904	
13905	/** gets the dual Farkas value of the knapsack constraint in the current infeasible LP */
13906	SCIP_Real SCIPgetDualfarkasKnapsack(
13907	   SCIP*                 scip,               /**< SCIP data structure */
13908	   SCIP_CONS*            cons                /**< constraint data */
13909	   )
13910	{
13911	   SCIP_CONSDATA* consdata;
13912	
13913	   assert(scip != NULL);
13914	
13915	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
13916	   {
13917	      SCIPerrorMessage("constraint is not a knapsack constraint\n");
13918	      SCIPABORT();
13919	      return SCIP_INVALID;  /*lint !e527*/
13920	   }
13921	
13922	   consdata = SCIPconsGetData(cons);
13923	   assert(consdata != NULL);
13924	
13925	   if( consdata->row != NULL )
13926	      return SCIProwGetDualfarkas(consdata->row);
13927	   else
13928	      return 0.0;
13929	}
13930	
13931	/** returns the linear relaxation of the given knapsack constraint; may return NULL if no LP row was yet created;
13932	 *  the user must not modify the row!
13933	 */
13934	SCIP_ROW* SCIPgetRowKnapsack(
13935	   SCIP*                 scip,               /**< SCIP data structure */
13936	   SCIP_CONS*            cons                /**< constraint data */
13937	   )
13938	{
13939	   SCIP_CONSDATA* consdata;
13940	
13941	   assert(scip != NULL);
13942	
13943	   if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
13944	   {
13945	      SCIPerrorMessage("constraint is not a knapsack\n");
13946	      SCIPABORT();
13947	      return NULL;  /*lint !e527*/
13948	   }
13949	
13950	   consdata = SCIPconsGetData(cons);
13951	   assert(consdata != NULL);
13952	
13953	   return consdata->row;
13954	}
13955	
13956	/** cleans up (multi-)aggregations and fixings from knapsack constraints */
13957	SCIP_RETCODE SCIPcleanupConssKnapsack(
13958	   SCIP*                 scip,               /**< SCIP data structure */
13959	   SCIP_Bool             onlychecked,        /**< should only checked constraints be cleaned up? */
13960	   SCIP_Bool*            infeasible          /**< pointer to return whether the problem was detected to be infeasible */
13961	   )
13962	{
13963	   SCIP_CONSHDLR* conshdlr;
13964	   SCIP_CONS** conss;
13965	   int nconss;
13966	   int i;
13967	
13968	   conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
13969	   if( conshdlr == NULL )
13970	      return SCIP_OKAY;
13971	
13972	   assert(infeasible != NULL);
13973	   *infeasible = FALSE;
13974	
13975	   nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
13976	   conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
13977	
13978	   for( i = 0; i < nconss; ++i )
13979	   {
13980	      SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
13981	
13982	      if( *infeasible )
13983	         break;
13984	   }
13985	
13986	   return SCIP_OKAY;
13987	}
13988