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_sos1.c
26   	 * @ingroup DEFPLUGINS_CONS
27   	 * @brief  constraint handler for SOS type 1 constraints
28   	 * @author Tobias Fischer
29   	 * @author Marc Pfetsch
30   	 *
31   	 * A specially ordered set of type 1 (SOS1) is a sequence of variables such that at most one
32   	 * variable is nonzero. The special case of two variables arises, for instance, from equilibrium or
33   	 * complementary conditions like \f$x \cdot y = 0\f$. Note that it is in principle allowed that a
34   	 * variables appears twice, but it then can be fixed to 0.
35   	 *
36   	 * This implementation of this constraint handler is based on classical ideas, see e.g.@n
37   	 *  "Special Facilities in General Mathematical Programming System for
38   	 *  Non-Convex Problems Using Ordered Sets of Variables"@n
39   	 *  E. Beale and J. Tomlin, Proc. 5th IFORS Conference, 447-454 (1970)
40   	 *
41   	 *
42   	 * The order of the variables is determined as follows:
43   	 *
44   	 * - If the constraint is created with SCIPcreateConsSOS1() and weights are given, the weights
45   	 *   determine the order (decreasing weights). Additional variables can be added with
46   	 *   SCIPaddVarSOS1(), which adds a variable with given weight.
47   	 *
48   	 * - If an empty constraint is created and then variables are added with SCIPaddVarSOS1(), weights
49   	 *   are needed and stored.
50   	 *
51   	 * - All other calls ignore the weights, i.e., if a nonempty constraint is created or variables are
52   	 *   added with SCIPappendVarSOS1().
53   	 *
54   	 * The validity of the SOS1 constraints can be enforced by different branching rules:
55   	 *
56   	 * - If classical SOS branching is used, branching is performed on only one SOS1 constraint.
57   	 *   Depending on the parameters, there are two ways to choose this branching constraint. Either
58   	 *   the constraint with the most number of nonzeros or the one with the largest nonzero-variable
59   	 *   weight. The later version allows the user to specify an order for the branching importance of
60   	 *   the constraints. Constraint branching can also be turned off.
61   	 *
62   	 * - Another way is to branch on the neighborhood of a single variable @p i, i.e., in one branch
63   	 *   \f$x_i\f$ is fixed to zero and in the other its neighbors from the conflict graph.
64   	 *
65   	 * - If bipartite branching is used, then we branch using complete bipartite subgraphs of the
66   	 *   conflict graph, i.e., in one branch fix the variables from the first bipartite partition and
67   	 *   the variables from the second bipartite partition in the other.
68   	 *
69   	 * - In addition to variable domain fixings, it is sometimes also possible to add new SOS1
70   	 *   constraints to the branching nodes. This results in a nonstatic conflict graph, which may
71   	 *   change dynamically with every branching node.
72   	 *
73   	 *
74   	 * @todo Possibly allow to generate local cuts via strengthened local cuts (would need to modified coefficients of rows).
75   	 *
76   	 * @todo Check whether we can avoid turning off multi-aggregation (it is sometimes possible to fix a multi-aggregated
77   	 * variable to 0 by fixing the aggregating variables to 0).
78   	 */
79   	
80   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
81   	
82   	#include "blockmemshell/memory.h"
83   	#include "scip/cons_linear.h"
84   	#include "scip/cons_setppc.h"
85   	#include "scip/cons_sos1.h"
86   	#include "scip/pub_cons.h"
87   	#include "scip/pub_event.h"
88   	#include "scip/pub_heur.h"
89   	#include "scip/pub_lp.h"
90   	#include "scip/pub_message.h"
91   	#include "scip/pub_misc.h"
92   	#include "scip/pub_misc_sort.h"
93   	#include "scip/pub_tree.h"
94   	#include "scip/pub_var.h"
95   	#include "scip/scip_branch.h"
96   	#include "scip/scip_conflict.h"
97   	#include "scip/scip_cons.h"
98   	#include "scip/scip_copy.h"
99   	#include "scip/scip_cut.h"
100  	#include "scip/scip_datastructures.h"
101  	#include "scip/scip_event.h"
102  	#include "scip/scip_general.h"
103  	#include "scip/scip_lp.h"
104  	#include "scip/scip_mem.h"
105  	#include "scip/scip_message.h"
106  	#include "scip/scip_numerics.h"
107  	#include "scip/scip_param.h"
108  	#include "scip/scip_prob.h"
109  	#include "scip/scip_probing.h"
110  	#include "scip/scip_sol.h"
111  	#include "scip/scip_solvingstats.h"
112  	#include "scip/scip_tree.h"
113  	#include "scip/scip_var.h"
114  	#include "scip/symmetry_graph.h"
115  	#include "symmetry/struct_symmetry.h"
116  	#include "tclique/tclique.h"
117  	
118  	
119  	/* constraint handler properties */
120  	#define CONSHDLR_NAME          "SOS1"
121  	#define CONSHDLR_DESC          "SOS1 constraint handler"
122  	#define CONSHDLR_SEPAPRIORITY      1000 /**< priority of the constraint handler for separation */
123  	#define CONSHDLR_ENFOPRIORITY       100 /**< priority of the constraint handler for constraint enforcing */
124  	#define CONSHDLR_CHECKPRIORITY      -10 /**< priority of the constraint handler for checking feasibility */
125  	#define CONSHDLR_SEPAFREQ            10 /**< frequency for separating cuts; zero means to separate only in the root node */
126  	#define CONSHDLR_PROPFREQ             1 /**< frequency for propagating domains; zero means only preprocessing propagation */
127  	#define CONSHDLR_EAGERFREQ          100 /**< frequency for using all instead of only the useful constraints in separation,
128  	                                         *   propagation and enforcement, -1 for no eager evaluations, 0 for first only */
129  	#define CONSHDLR_MAXPREROUNDS        -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
130  	#define CONSHDLR_DELAYSEPA        FALSE /**< should separation method be delayed, if other separators found cuts? */
131  	#define CONSHDLR_DELAYPROP        FALSE /**< should propagation method be delayed, if other propagators found reductions? */
132  	#define CONSHDLR_NEEDSCONS         TRUE /**< should the constraint handler be skipped, if no constraints are available? */
133  	#define CONSHDLR_PROP_TIMING       SCIP_PROPTIMING_BEFORELP
134  	#define CONSHDLR_PRESOLTIMING      SCIP_PRESOLTIMING_MEDIUM
135  	
136  	/* adjacency matrix */
137  	#define DEFAULT_MAXSOSADJACENCY   10000 /**< do not create an adjacency matrix if number of SOS1 variables is larger than predefined value
138  	                                         *   (-1: no limit) */
139  	
140  	/* presolving */
141  	#define DEFAULT_MAXEXTENSIONS         1 /**< maximal number of extensions that will be computed for each SOS1 constraint */
142  	#define DEFAULT_MAXTIGHTENBDS         5 /**< maximal number of bound tightening rounds per presolving round (-1: no limit) */
143  	#define DEFAULT_PERFIMPLANALYSIS  FALSE /**< if TRUE then perform implication graph analysis (might add additional SOS1 constraints) */
144  	#define DEFAULT_DEPTHIMPLANALYSIS    -1 /**< number of recursive calls of implication graph analysis (-1: no limit) */
145  	
146  	/* propagation */
147  	#define DEFAULT_CONFLICTPROP      TRUE /**< whether to use conflict graph propagation */
148  	#define DEFAULT_IMPLPROP          TRUE /**< whether to use implication graph propagation */
149  	#define DEFAULT_SOSCONSPROP      FALSE /**< whether to use SOS1 constraint propagation */
150  	
151  	/* branching rules */
152  	#define DEFAULT_BRANCHSTRATEGIES  "nbs" /**< possible branching strategies (see parameter DEFAULT_BRANCHINGRULE) */
153  	#define DEFAULT_BRANCHINGRULE       'n' /**< which branching rule should be applied ? ('n': neighborhood, 'b': bipartite, 's': SOS1/clique)
154  	                                         *   (note: in some cases an automatic switching to SOS1 branching is possible) */
155  	#define DEFAULT_AUTOSOS1BRANCH     TRUE /**< if TRUE then automatically switch to SOS1 branching if the SOS1 constraints do not overlap */
156  	#define DEFAULT_FIXNONZERO        FALSE /**< if neighborhood branching is used, then fix the branching variable (if positive in sign) to the value of the
157  	                                         *   feasibility tolerance */
158  	#define DEFAULT_ADDCOMPS          FALSE /**< if TRUE then add complementarity constraints to the branching nodes (can be used in combination with
159  	                                         *   neighborhood or bipartite branching) */
160  	#define DEFAULT_MAXADDCOMPS          -1 /**< maximal number of complementarity constraints added per branching node (-1: no limit) */
161  	#define DEFAULT_ADDCOMPSDEPTH        30 /**< only add complementarity constraints to branching nodes for predefined depth (-1: no limit) */
162  	#define DEFAULT_ADDCOMPSFEAS       -0.6 /**< minimal feasibility value for complementarity constraints in order to be added to the branching node */
163  	#define DEFAULT_ADDBDSFEAS          1.0 /**< minimal feasibility value for bound inequalities in order to be added to the branching node */
164  	#define DEFAULT_ADDEXTENDEDBDS     TRUE /**< should added complementarity constraints be extended to SOS1 constraints to get tighter bound inequalities */
165  	
166  	/* selection rules */
167  	#define DEFAULT_NSTRONGROUNDS         0 /**< maximal number of strong branching rounds to perform for each node (-1: auto)
168  	                                         *   (only available for neighborhood and bipartite branching) */
169  	#define DEFAULT_NSTRONGITER       10000 /**< maximal number LP iterations to perform for each strong branching round (-2: auto, -1: no limit) */
170  	
171  	/* separation */
172  	#define DEFAULT_BOUNDCUTSFROMSOS1 FALSE /**< if TRUE separate bound inequalities from SOS1 constraints */
173  	#define DEFAULT_BOUNDCUTSFROMGRAPH TRUE /**< if TRUE separate bound inequalities from the conflict graph */
174  	#define DEFAULT_AUTOCUTSFROMSOS1   TRUE /**< if TRUE then automatically switch to separating from SOS1 constraints if the SOS1 constraints do not overlap */
175  	#define DEFAULT_BOUNDCUTSFREQ        10 /**< frequency for separating bound cuts; zero means to separate only in the root node */
176  	#define DEFAULT_BOUNDCUTSDEPTH       40 /**< node depth of separating bound cuts (-1: no limit) */
177  	#define DEFAULT_MAXBOUNDCUTS         50 /**< maximal number of bound cuts separated per branching node */
178  	#define DEFAULT_MAXBOUNDCUTSROOT    150 /**< maximal number of bound cuts separated per iteration in the root node */
179  	#define DEFAULT_STRTHENBOUNDCUTS   TRUE /**< if TRUE then bound cuts are strengthened in case bound variables are available */
180  	#define DEFAULT_IMPLCUTSFREQ          0 /**< frequency for separating implied bound cuts; zero means to separate only in the root node */
181  	#define DEFAULT_IMPLCUTSDEPTH        40 /**< node depth of separating implied bound cuts (-1: no limit) */
182  	#define DEFAULT_MAXIMPLCUTS          50 /**< maximal number of implied bound cuts separated per branching node */
183  	#define DEFAULT_MAXIMPLCUTSROOT     150 /**< maximal number of implied bound cuts separated per iteration in the root node */
184  	
185  	/* event handler properties */
186  	#define EVENTHDLR_NAME         "SOS1"
187  	#define EVENTHDLR_DESC         "bound change event handler for SOS1 constraints"
188  	
189  	#define EVENTHDLR_EVENT_TYPE   (SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_GBDCHANGED)
190  	
191  	/* defines */
192  	#define DIVINGCUTOFFVALUE     1e6
193  	
194  	
195  	/** constraint data for SOS1 constraints */
196  	struct SCIP_ConsData
197  	{
198  	   int                   nvars;              /**< number of variables in the constraint */
199  	   int                   maxvars;            /**< maximal number of variables (= size of storage) */
200  	   int                   nfixednonzeros;     /**< number of variables fixed to be nonzero */
201  	   SCIP_Bool             local;              /**< TRUE if constraint is only valid locally */
202  	   SCIP_VAR**            vars;               /**< variables in constraint */
203  	   SCIP_ROW*             rowlb;              /**< row corresponding to lower bounds, or NULL if not yet created */
204  	   SCIP_ROW*             rowub;              /**< row corresponding to upper bounds, or NULL if not yet created */
205  	   SCIP_Real*            weights;            /**< weights determining the order (ascending), or NULL if not used */
206  	};
207  	
208  	
209  	/** node data of a given node in the conflict graph */
210  	struct SCIP_NodeData
211  	{
212  	   SCIP_VAR*             var;                /**< variable belonging to node */
213  	   SCIP_VAR*             lbboundvar;         /**< bound variable @p z from constraint \f$x \geq \mu \cdot z\f$ (or NULL if not existent) */
214  	   SCIP_VAR*             ubboundvar;         /**< bound variable @p z from constraint \f$x \leq \mu \cdot z\f$ (or NULL if not existent) */
215  	   SCIP_Real             lbboundcoef;        /**< value \f$\mu\f$ from constraint \f$x \geq \mu z \f$ (0.0 if not existent) */
216  	   SCIP_Real             ubboundcoef;        /**< value \f$\mu\f$ from constraint \f$x \leq \mu z \f$ (0.0 if not existent) */
217  	   SCIP_Bool             lbboundcomp;        /**< TRUE if the nodes from the connected component of the conflict graph the given node belongs to
218  	                                              *   all have the same lower bound variable */
219  	   SCIP_Bool             ubboundcomp;        /**< TRUE if the nodes from the connected component of the conflict graph the given node belongs to
220  	                                              *   all have the same lower bound variable */
221  	};
222  	typedef struct SCIP_NodeData SCIP_NODEDATA;
223  	
224  	
225  	/** successor data of a given nodes successor in the implication graph */
226  	struct SCIP_SuccData
227  	{
228  	   SCIP_Real             lbimpl;             /**< lower bound implication */
229  	   SCIP_Real             ubimpl;             /**< upper bound implication */
230  	};
231  	typedef struct SCIP_SuccData SCIP_SUCCDATA;
232  	
233  	
234  	/** tclique data for bound cut generation */
235  	struct TCLIQUE_Data
236  	{
237  	   SCIP*                 scip;               /**< SCIP data structure */
238  	   SCIP_CONSHDLR*        conshdlr;           /**< SOS1 constraint handler */
239  	   SCIP_DIGRAPH*         conflictgraph;      /**< conflict graph */
240  	   SCIP_SOL*             sol;                /**< LP solution to be separated (or NULL) */
241  	   SCIP_Real             scaleval;           /**< factor for scaling weights */
242  	   SCIP_Bool             cutoff;             /**< whether a cutoff occurred */
243  	   int                   ncuts;              /**< number of bound cuts found in this iteration */
244  	   int                   nboundcuts;         /**< number of bound cuts found so far */
245  	   int                   maxboundcuts;       /**< maximal number of clique cuts separated per separation round (-1: no limit) */
246  	   SCIP_Bool             strthenboundcuts;   /**< if TRUE then bound cuts are strengthened in case bound variables are available */
247  	};
248  	
249  	
250  	/** SOS1 constraint handler data */
251  	struct SCIP_ConshdlrData
252  	{
253  	   /* conflict graph */
254  	   SCIP_DIGRAPH*         conflictgraph;      /**< conflict graph */
255  	   SCIP_DIGRAPH*         localconflicts;     /**< local conflicts */
256  	   SCIP_Bool             isconflocal;        /**< if TRUE then local conflicts are present and conflict graph has to be updated for each node */
257  	   SCIP_HASHMAP*         varhash;            /**< hash map from variable to node in the conflict graph */
258  	   int                   nsos1vars;          /**< number of problem variables that are part of the SOS1 conflict graph */
259  	   /* adjacency matrix */
260  	   int                   maxsosadjacency;    /**< do not create an adjacency matrix if number of SOS1 variables is larger than predefined
261  	                                              *   value (-1: no limit) */
262  	   /* implication graph */
263  	   SCIP_DIGRAPH*         implgraph;          /**< implication graph (@p j is successor of @p i if and only if \f$ x_i\not = 0 \Rightarrow x_j\not = 0\f$) */
264  	   int                   nimplnodes;         /**< number of nodes in the implication graph */
265  	   /* tclique graph */
266  	   TCLIQUE_GRAPH*        tcliquegraph;       /**< tclique graph data structure */
267  	   TCLIQUE_DATA*         tcliquedata;        /**< tclique data */
268  	   /* event handler */
269  	   SCIP_EVENTHDLR*       eventhdlr;          /**< event handler for bound change events */
270  	   SCIP_VAR**            fixnonzerovars;     /**< stack of variables fixed to nonzero marked by event handler */
271  	   int                   maxnfixnonzerovars; /**< size of stack fixnonzerovars */
272  	   int                   nfixnonzerovars;    /**< number of variables fixed to nonzero marked by event handler */
273  	   /* presolving */
274  	   int                   cntextsos1;         /**< counts number of extended SOS1 constraints */
275  	   int                   maxextensions;      /**< maximal number of extensions that will be computed for each SOS1 constraint */
276  	   int                   maxtightenbds;      /**< maximal number of bound tightening rounds per presolving round (-1: no limit) */
277  	   SCIP_Bool             perfimplanalysis;   /**< if TRUE then perform implication graph analysis (might add additional SOS1 constraints) */
278  	   int                   depthimplanalysis;  /**< number of recursive calls of implication graph analysis (-1: no limit) */
279  	   /* propagation */
280  	   SCIP_Bool             conflictprop;       /**< whether to use conflict graph propagation */
281  	   SCIP_Bool             implprop;           /**< whether to use implication graph propagation */
282  	   SCIP_Bool             sosconsprop;        /**< whether to use SOS1 constraint propagation */
283  	   /* branching */
284  	   char                  branchingrule;      /**< which branching rule should be applied ? ('n': neighborhood, 'b': bipartite, 's': SOS1/clique)
285  	                                              *   (note: in some cases an automatic switching to SOS1 branching is possible) */
286  	   SCIP_Bool             autosos1branch;     /**< if TRUE then automatically switch to SOS1 branching if the SOS1 constraints do not overlap */
287  	   SCIP_Bool             fixnonzero;         /**< if neighborhood branching is used, then fix the branching variable (if positive in sign) to the value of the
288  	                                              *   feasibility tolerance */
289  	   SCIP_Bool             addcomps;           /**< if TRUE then add complementarity constraints to the branching nodes additionally to domain fixings
290  	                                              *   (can be used in combination with neighborhood or bipartite branching) */
291  	   int                   maxaddcomps;        /**< maximal number of complementarity cons. and cor. bound ineq. added per branching node (-1: no limit) */
292  	   int                   addcompsdepth;      /**< only add complementarity constraints to branching nodes for predefined depth (-1: no limit) */
293  	   SCIP_Real             addcompsfeas;       /**< minimal feasibility value for complementarity constraints in order to be added to the branching node */
294  	   SCIP_Real             addbdsfeas;         /**< minimal feasibility value for bound inequalities in order to be added to the branching node */
295  	   SCIP_Bool             addextendedbds;     /**< should added complementarity constraints be extended to SOS1 constraints to get tighter bound inequalities */
296  	   SCIP_Bool             branchsos;          /**< Branch on SOS condition in enforcing? This value can only be set to false if all SOS1 variables are binary */
297  	   SCIP_Bool             branchnonzeros;     /**< Branch on SOS cons. with most number of nonzeros? */
298  	   SCIP_Bool             branchweight;       /**< Branch on SOS cons. with highest nonzero-variable weight for branching - needs branchnonzeros to be false */
299  	   SCIP_Bool             switchsos1branch;   /**< whether to switch to SOS1 branching */
300  	   /* selection rules */
301  	   int                   nstrongrounds;      /**< maximal number of strong branching rounds to perform for each node (-1: auto)
302  	                                              *   (only available for neighborhood and bipartite branching) */
303  	   int                   nstrongiter;        /**< maximal number LP iterations to perform for each strong branching round (-2: auto, -1: no limit) */
304  	   /* separation */
305  	   SCIP_Bool             boundcutsfromsos1;  /**< if TRUE separate bound inequalities from SOS1 constraints */
306  	   SCIP_Bool             boundcutsfromgraph; /**< if TRUE separate bound inequalities from the conflict graph */
307  	   SCIP_Bool             autocutsfromsos1;   /**< if TRUE then automatically switch to separating SOS1 constraints if the SOS1 constraints do not overlap */
308  	   SCIP_Bool             switchcutsfromsos1; /**< whether to switch to separate bound inequalities from SOS1 constraints */
309  	   int                   boundcutsfreq;      /**< frequency for separating bound cuts; zero means to separate only in the root node */
310  	   int                   boundcutsdepth;     /**< node depth of separating bound cuts (-1: no limit) */
311  	   int                   maxboundcuts;       /**< maximal number of bound cuts separated per branching node */
312  	   int                   maxboundcutsroot;   /**< maximal number of bound cuts separated per iteration in the root node */
313  	   int                   nboundcuts;         /**< number of bound cuts found so far */
314  	   SCIP_Bool             strthenboundcuts;   /**< if TRUE then bound cuts are strengthened in case bound variables are available */
315  	   int                   implcutsfreq;       /**< frequency for separating implied bound cuts; zero means to separate only in the root node */
316  	   int                   implcutsdepth;      /**< node depth of separating implied bound cuts (-1: no limit) */
317  	   int                   maximplcuts;        /**< maximal number of implied bound cuts separated per branching node */
318  	   int                   maximplcutsroot;    /**< maximal number of implied bound cuts separated per iteration in the root node */
319  	};
320  	
321  	
322  	
323  	/*
324  	 * local methods
325  	 */
326  	
327  	/** returns whether two vertices are adjacent in the conflict graph */
328  	static
329  	SCIP_Bool isConnectedSOS1(
330  	   SCIP_Bool**           adjacencymatrix,    /**< adjacency matrix of conflict graph (lower half) (or NULL if an adjacencymatrix is not at hand) */
331  	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph (or NULL if an adjacencymatrix is at hand) */
332  	   int                   vertex1,            /**< first vertex */
333  	   int                   vertex2             /**< second vertex */
334  	   )
335  	{
336  	   assert( adjacencymatrix != NULL || conflictgraph != NULL );
337  	
338  	   /* we do not allow self-loops */
339  	   if ( vertex1 == vertex2 )
340  	      return FALSE;
341  	
342  	   /* for debugging */
343  	   if ( adjacencymatrix == NULL )
344  	   {
345  	      int succvertex;
346  	      int* succ;
347  	      int nsucc1;
348  	      int nsucc2;
349  	      int j;
350  	
351  	      nsucc1 = SCIPdigraphGetNSuccessors(conflictgraph, vertex1);
352  	      nsucc2 = SCIPdigraphGetNSuccessors(conflictgraph, vertex2);
353  	
354  	      if ( nsucc1 < 1 || nsucc2 < 1 )
355  	         return FALSE;
356  	
357  	      if ( nsucc1 > nsucc2 )
358  	      {
359  	         SCIPswapInts(&vertex1, &vertex2);
360  	         SCIPswapInts(&nsucc1, &nsucc2);
361  	      }
362  	
363  	      succ = SCIPdigraphGetSuccessors(conflictgraph, vertex1);
364  	      SCIPsortInt(succ, nsucc1);
365  	
366  	      for (j = 0; j < nsucc1; ++j)
367  	      {
368  	         succvertex = succ[j];
369  	         if ( succvertex == vertex2 )
370  	            return TRUE;
371  	         else if ( succvertex > vertex2 )
372  	            return FALSE;
373  	      }
374  	   }
375  	   else
376  	   {
377  	      if ( vertex1 < vertex2 )
378  	         return adjacencymatrix[vertex2][vertex1];
379  	      else
380  	         return adjacencymatrix[vertex1][vertex2];
381  	   }
382  	
383  	   return FALSE;
384  	}
385  	
386  	
387  	/** checks whether a variable violates an SOS1 constraint w.r.t. sol together with at least one other variable */
388  	static
389  	SCIP_Bool isViolatedSOS1(
390  	   SCIP*                 scip,               /**< SCIP data structure */
391  	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph (or NULL if an adjacencymatrix is at hand) */
392  	   int                   node,               /**< node of variable in the conflict graph */
393  	   SCIP_SOL*             sol                 /**< solution, or NULL to use current node's solution */
394  	   )
395  	{
396  	   SCIP_Real solval;
397  	   SCIP_VAR* var;
398  	
399  	   assert( scip != NULL );
400  	   assert( conflictgraph != NULL );
401  	   assert( node >= 0 );
402  	
403  	   var = SCIPnodeGetVarSOS1(conflictgraph, node);
404  	   assert( var != NULL );
405  	   solval = SCIPgetSolVal(scip, sol, var);
406  	
407  	   /* check whether variable is nonzero w.r.t. sol and the bounds have not been fixed to zero by propagation */
408  	   if ( ! SCIPisFeasZero(scip, solval) && ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) || ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) ) )
409  	   {
410  	      int* succ;
411  	      int nsucc;
412  	      int s;
413  	
414  	      nsucc = SCIPdigraphGetNSuccessors(conflictgraph, node);
415  	      succ = SCIPdigraphGetSuccessors(conflictgraph, node);
416  	
417  	      /* check whether a neighbor variable is nonzero w.r.t. sol */
418  	      for (s = 0; s < nsucc; ++s)
419  	      {
420  	         var = SCIPnodeGetVarSOS1(conflictgraph, succ[s]);
421  	         assert( var != NULL );
422  	         solval = SCIPgetSolVal(scip, sol, var);
423  	         if ( ! SCIPisFeasZero(scip, solval) && ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) || ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) ) )
424  	            return TRUE;
425  	      }
426  	   }
427  	
428  	   return FALSE;
429  	}
430  	
431  	
432  	/** returns solution value of imaginary binary big-M variable of a given node from the conflict graph */
433  	static
434  	SCIP_Real nodeGetSolvalBinaryBigMSOS1(
435  	   SCIP*                 scip,               /**< SCIP pointer */
436  	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
437  	   SCIP_SOL*             sol,                /**< primal solution, or NULL for current LP/pseudo solution */
438  	   int                   node                /**< node of the conflict graph */
439  	   )
440  	{
441  	   SCIP_Real bound;
442  	   SCIP_VAR* var;
443  	   SCIP_Real val;
444  	
445  	   assert( scip != NULL );
446  	   assert( conflictgraph != NULL );
447  	   assert( node >= 0 && node < SCIPdigraphGetNNodes(conflictgraph) );
448  	
449  	   var = SCIPnodeGetVarSOS1(conflictgraph, node);
450  	   val = SCIPgetSolVal(scip, sol, var);
451  	
452  	   if ( SCIPisFeasNegative(scip, val) )
453  	   {
454  	      bound = SCIPvarGetLbLocal(var);
455  	      assert( SCIPisFeasNegative(scip, bound) );
456  	
457  	      if ( SCIPisInfinity(scip, -val) )
458  	         return 1.0;
459  	      else if ( SCIPisInfinity(scip, -bound) )
460  	         return 0.0;
461  	      else
462  	         return (val/bound);
463  	   }
464  	   else if ( SCIPisFeasPositive(scip, val) )
465  	   {
466  	      bound = SCIPvarGetUbLocal(var);
467  	      assert( SCIPisFeasPositive(scip, bound) );
468  	      assert( SCIPisFeasPositive(scip, val) );
469  	
470  	      if ( SCIPisInfinity(scip, val) )
471  	         return 1.0;
472  	      else if ( SCIPisInfinity(scip, bound) )
473  	         return 0.0;
474  	      else
475  	         return (val/bound);
476  	   }
477  	   else
478  	      return 0.0;
479  	}
480  	
481  	
482  	/** gets (variable) lower bound value of current LP relaxation solution for a given node from the conflict graph */
483  	static
484  	SCIP_Real nodeGetSolvalVarboundLbSOS1(
485  	   SCIP*                 scip,               /**< SCIP pointer */
486  	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
487  	   SCIP_SOL*             sol,                /**< primal solution, or NULL for current LP/pseudo solution */
488  	   int                   node                /**< node of the conflict graph */
489  	   )
490  	{
491  	   SCIP_NODEDATA* nodedata;
492  	
493  	   assert( scip != NULL );
494  	   assert( conflictgraph != NULL );
495  	   assert( node >= 0 && node < SCIPdigraphGetNNodes(conflictgraph) );
496  	
497  	   /* get node data */
498  	   nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, node);
499  	   assert( nodedata != NULL );
500  	
501  	   /* if variable is not involved in a variable upper bound constraint */
502  	   if ( nodedata->lbboundvar == NULL || ! nodedata->lbboundcomp )
503  	      return SCIPvarGetLbLocal(nodedata->var);
504  	
505  	   return nodedata->lbboundcoef * SCIPgetSolVal(scip, sol, nodedata->lbboundvar);
506  	}
507  	
508  	
509  	/** gets (variable) upper bound value of current LP relaxation solution for a given node from the conflict graph */
510  	static
511  	SCIP_Real nodeGetSolvalVarboundUbSOS1(
512  	   SCIP*                 scip,               /**< SCIP pointer */
513  	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
514  	   SCIP_SOL*             sol,                /**< primal solution, or NULL for current LP/pseudo solution */
515  	   int                   node                /**< node of the conflict graph */
516  	   )
517  	{
518  	   SCIP_NODEDATA* nodedata;
519  	
520  	   assert( scip != NULL );
521  	   assert( conflictgraph != NULL );
522  	   assert( node >= 0 && node < SCIPdigraphGetNNodes(conflictgraph) );
523  	
524  	   /* get node data */
525  	   nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, node);
526  	   assert( nodedata != NULL );
527  	
528  	   /* if variable is not involved in a variable upper bound constraint */
529  	   if ( nodedata->ubboundvar == NULL || ! nodedata->ubboundcomp )
530  	      return SCIPvarGetUbLocal(nodedata->var);
531  	
532  	   return nodedata->ubboundcoef * SCIPgetSolVal(scip, sol, nodedata->ubboundvar);
533  	}
534  	
535  	
536  	/** returns whether variable is part of the SOS1 conflict graph */
537  	static
538  	SCIP_Bool varIsSOS1(
539  	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< SOS1 constraint handler */
540  	   SCIP_VAR*             var                 /**< variable */
541  	   )
542  	{
543  	   assert( conshdlrdata != NULL );
544  	   assert( var != NULL );
545  	
546  	   if ( conshdlrdata->varhash == NULL || ! SCIPhashmapExists(conshdlrdata->varhash, var) )
547  	      return FALSE;
548  	
549  	   return TRUE;
550  	}
551  	
552  	
553  	/** returns SOS1 index of variable or -1 if variable is not part of the SOS1 conflict graph */
554  	static
555  	int varGetNodeSOS1(
556  	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< SOS1 constraint handler */
557  	   SCIP_VAR*             var                 /**< variable */
558  	   )
559  	{
560  	   assert( conshdlrdata != NULL );
561  	   assert( var != NULL );
562  	   assert( conshdlrdata->varhash != NULL );
563  	
564  	   if ( ! SCIPhashmapExists(conshdlrdata->varhash, var) )
565  	      return -1;
566  	
567  	   return SCIPhashmapGetImageInt(conshdlrdata->varhash, var);
568  	}
569  	
570  	
571  	/** fix variable in given node to 0 or add constraint if variable is multi-aggregated
572  	 *
573  	 *  @todo Try to handle multi-aggregated variables as in fixVariableZero() below.
574  	 */
575  	static
576  	SCIP_RETCODE fixVariableZeroNode(
577  	   SCIP*                 scip,               /**< SCIP pointer */
578  	   SCIP_VAR*             var,                /**< variable to be fixed to 0*/
579  	   SCIP_NODE*            node,               /**< node */
580  	   SCIP_Bool*            infeasible          /**< if fixing is infeasible */
581  	   )
582  	{
583  	   /* if variable cannot be nonzero */
584  	   *infeasible = FALSE;
585  	   if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var)) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(var)) )
586  	   {
587  	      *infeasible = TRUE;
588  	      return SCIP_OKAY;
589  	   }
590  	
591  	   /* if variable is multi-aggregated */
592  	   if ( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
593  	   {
594  	      SCIP_CONS* cons;
595  	      SCIP_Real val;
596  	
597  	      val = 1.0;
598  	
599  	      if ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) || ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
600  	      {
601  	         SCIPdebugMsg(scip, "creating constraint to force multi-aggregated variable <%s> to 0.\n", SCIPvarGetName(var));
602  	         /* we have to insert a local constraint var = 0 */
603  	         SCIP_CALL( SCIPcreateConsLinear(scip, &cons, "branch", 1, &var, &val, 0.0, 0.0, TRUE, TRUE, TRUE, TRUE, TRUE,
604  	               TRUE, FALSE, FALSE, FALSE, FALSE) );
605  	         SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
606  	         SCIP_CALL( SCIPreleaseCons(scip, &cons) );
607  	      }
608  	   }
609  	   else
610  	   {
611  	      if ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) )
612  	         SCIP_CALL( SCIPchgVarLbNode(scip, node, var, 0.0) );
613  	      if ( ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
614  	         SCIP_CALL( SCIPchgVarUbNode(scip, node, var, 0.0) );
615  	   }
616  	
617  	   return SCIP_OKAY;
618  	}
619  	
620  	
621  	/** try to fix variable to 0
622  	 *
623  	 *  Try to treat fixing by special consideration of multiaggregated variables. For a multi-aggregation
624  	 *  \f[
625  	 *  x = \sum_{i=1}^n \alpha_i x_i + c,
626  	 *  \f]
627  	 *  we can express the fixing \f$x = 0\f$ by fixing all \f$x_i\f$ to 0 if \f$c = 0\f$ and the lower bounds of \f$x_i\f$
628  	 *  are nonnegative if \f$\alpha_i > 0\f$ or the upper bounds are nonpositive if \f$\alpha_i < 0\f$.
629  	 */
630  	static
631  	SCIP_RETCODE fixVariableZero(
632  	   SCIP*                 scip,               /**< SCIP pointer */
633  	   SCIP_VAR*             var,                /**< variable to be fixed to 0*/
634  	   SCIP_Bool*            infeasible,         /**< if fixing is infeasible */
635  	   SCIP_Bool*            tightened           /**< if fixing was performed */
636  	   )
637  	{
638  	   assert( scip != NULL );
639  	   assert( var != NULL );
640  	   assert( infeasible != NULL );
641  	   assert( tightened != NULL );
642  	
643  	   *infeasible = FALSE;
644  	   *tightened = FALSE;
645  	
646  	   if ( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
647  	   {
648  	      SCIP_Real aggrconst;
649  	
650  	      /* if constant is 0 */
651  	      aggrconst = SCIPvarGetMultaggrConstant(var);
652  	      if ( SCIPisZero(scip, aggrconst) )
653  	      {
654  	         SCIP_VAR** aggrvars;
655  	         SCIP_Real* aggrvals;
656  	         SCIP_Bool allnonnegative = TRUE;
657  	         int naggrvars;
658  	         int i;
659  	
660  	         SCIP_CALL( SCIPflattenVarAggregationGraph(scip, var) );
661  	
662  	         /* check whether all variables are "nonnegative" */
663  	         naggrvars = SCIPvarGetMultaggrNVars(var);
664  	         aggrvars = SCIPvarGetMultaggrVars(var);
665  	         aggrvals = SCIPvarGetMultaggrScalars(var);
666  	         for (i = 0; i < naggrvars; ++i)
667  	         {
668  	            if ( (SCIPisPositive(scip, aggrvals[i]) && SCIPisNegative(scip, SCIPvarGetLbLocal(aggrvars[i]))) ||
669  	                 (SCIPisNegative(scip, aggrvals[i]) && SCIPisPositive(scip, SCIPvarGetUbLocal(aggrvars[i]))) )
670  	            {
671  	               allnonnegative = FALSE;
672  	               break;
673  	            }
674  	         }
675  	
676  	         if ( allnonnegative )
677  	         {
678  	            /* all variables are nonnegative -> fix variables */
679  	            for (i = 0; i < naggrvars; ++i)
680  	            {
681  	               SCIP_Bool fixed;
682  	               SCIP_CALL( SCIPfixVar(scip, aggrvars[i], 0.0, infeasible, &fixed) );
683  	               if ( *infeasible )
684  	                  return SCIP_OKAY;
685  	               *tightened = *tightened || fixed;
686  	            }
687  	         }
688  	      }
689  	   }
690  	   else
691  	   {
692  	      SCIP_CALL( SCIPfixVar(scip, var, 0.0, infeasible, tightened) );
693  	   }
694  	
695  	   return SCIP_OKAY;
696  	}
697  	
698  	
699  	/** fix variable in local node to 0, and return whether the operation was feasible
700  	 *
701  	 *  @note We do not add a linear constraint if the variable is multi-aggregated as in
702  	 *  fixVariableZeroNode(), since this would be too time consuming.
703  	 */
704  	static
705  	SCIP_RETCODE inferVariableZero(
706  	   SCIP*                 scip,               /**< SCIP pointer */
707  	   SCIP_VAR*             var,                /**< variable to be fixed to 0*/
708  	   SCIP_CONS*            cons,               /**< constraint */
709  	   int                   inferinfo,          /**< info for reverse prop. */
710  	   SCIP_Bool*            infeasible,         /**< if fixing is infeasible */
711  	   SCIP_Bool*            tightened,          /**< if fixing was performed */
712  	   SCIP_Bool*            success             /**< whether fixing was successful, i.e., variable is not multi-aggregated */
713  	   )
714  	{
715  	   *infeasible = FALSE;
716  	   *tightened = FALSE;
717  	   *success = FALSE;
718  	
719  	   /* if variable cannot be nonzero */
720  	   if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var)) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(var)) )
721  	   {
722  	      *infeasible = TRUE;
723  	      return SCIP_OKAY;
724  	   }
725  	
726  	   /* directly fix variable if it is not multi-aggregated */
727  	   if ( SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
728  	   {
729  	      SCIP_Bool tighten;
730  	
731  	      /* fix lower bound */
732  	      SCIP_CALL( SCIPinferVarLbCons(scip, var, 0.0, cons, inferinfo, FALSE, infeasible, &tighten) );
733  	      *tightened = *tightened || tighten;
734  	
735  	      /* fix upper bound */
736  	      SCIP_CALL( SCIPinferVarUbCons(scip, var, 0.0, cons, inferinfo, FALSE, infeasible, &tighten) );
737  	      *tightened = *tightened || tighten;
738  	
739  	      *success = TRUE;
740  	   }
741  	
742  	   return SCIP_OKAY;
743  	}
744  	
745  	
746  	/** add lock on variable */
747  	static
748  	SCIP_RETCODE lockVariableSOS1(
749  	   SCIP*                 scip,               /**< SCIP data structure */
750  	   SCIP_CONS*            cons,               /**< constraint */
751  	   SCIP_VAR*             var                 /**< variable */
752  	   )
753  	{
754  	   assert( scip != NULL );
755  	   assert( cons != NULL );
756  	   assert( var != NULL );
757  	
758  	   /* rounding down == bad if lb < 0, rounding up == bad if ub > 0 */
759  	   SCIP_CALL( SCIPlockVarCons(scip, var, cons, SCIPisFeasNegative(scip, SCIPvarGetLbGlobal(var)),
760  	         SCIPisFeasPositive(scip, SCIPvarGetUbGlobal(var))) );
761  	
762  	   return SCIP_OKAY;
763  	}
764  	
765  	
766  	/** remove lock on variable */
767  	static
768  	SCIP_RETCODE unlockVariableSOS1(
769  	   SCIP*                 scip,               /**< SCIP data structure */
770  	   SCIP_CONS*            cons,               /**< constraint */
771  	   SCIP_VAR*             var                 /**< variable */
772  	   )
773  	{
774  	   assert( scip != NULL );
775  	   assert( cons != NULL );
776  	   assert( var != NULL );
777  	
778  	   /* rounding down == bad if lb < 0, rounding up == bad if ub > 0 */
779  	   SCIP_CALL( SCIPunlockVarCons(scip, var, cons, SCIPisFeasNegative(scip, SCIPvarGetLbGlobal(var)),
780  	         SCIPisFeasPositive(scip, SCIPvarGetUbGlobal(var))) );
781  	
782  	   return SCIP_OKAY;
783  	}
784  	
785  	
786  	/** ensures that the vars and weights array can store at least num entries */
787  	static
788  	SCIP_RETCODE consdataEnsurevarsSizeSOS1(
789  	   SCIP*                 scip,               /**< SCIP data structure */
790  	   SCIP_CONSDATA*        consdata,           /**< constraint data */
791  	   int                   num,                /**< minimum number of entries to store */
792  	   SCIP_Bool             reserveWeights      /**< whether the weights array is handled */
793  	   )
794  	{
795  	   assert( consdata != NULL );
796  	   assert( consdata->nvars <= consdata->maxvars );
797  	
798  	   if ( num > consdata->maxvars )
799  	   {
800  	      int newsize;
801  	
802  	      newsize = SCIPcalcMemGrowSize(scip, num);
803  	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->maxvars, newsize) );
804  	      if ( reserveWeights )
805  	         SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->weights, consdata->maxvars, newsize) );
806  	      consdata->maxvars = newsize;
807  	   }
808  	   assert( num <= consdata->maxvars );
809  	
810  	   return SCIP_OKAY;
811  	}
812  	
813  	
814  	/** handle new variable */
815  	static
816  	SCIP_RETCODE handleNewVariableSOS1(
817  	   SCIP*                 scip,               /**< SCIP data structure */
818  	   SCIP_CONS*            cons,               /**< constraint */
819  	   SCIP_CONSDATA*        consdata,           /**< constraint data */
820  	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
821  	   SCIP_VAR*             var,                /**< variable */
822  	   SCIP_Bool             transformed         /**< whether original variable was transformed */
823  	   )
824  	{
825  	   SCIP_DIGRAPH* conflictgraph;
826  	   int node;
827  	
828  	   assert( scip != NULL );
829  	   assert( cons != NULL );
830  	   assert( consdata != NULL );
831  	   assert( conshdlrdata != NULL );
832  	   assert( var != NULL );
833  	
834  	   /* if we are in transformed problem, catch the variable's events */
835  	   if ( transformed )
836  	   {
837  	      assert( conshdlrdata->eventhdlr != NULL );
838  	
839  	      /* catch bound change events of variable */
840  	      SCIP_CALL( SCIPcatchVarEvent(scip, var, EVENTHDLR_EVENT_TYPE, conshdlrdata->eventhdlr,
841  	            (SCIP_EVENTDATA*)cons, NULL) ); /*lint !e740*/
842  	
843  	      /* if the variable if fixed to nonzero */
844  	      assert( consdata->nfixednonzeros >= 0 );
845  	      if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var)) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(var)) )
846  	         ++consdata->nfixednonzeros;
847  	   }
848  	
849  	   /* install the rounding locks for the new variable */
850  	   SCIP_CALL( lockVariableSOS1(scip, cons, var) );
851  	
852  	   /* branching on multiaggregated variables does not seem to work well, so avoid it */
853  	   SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, var) );
854  	
855  	   /* add the new coefficient to the upper bound LP row, if necessary */
856  	   if ( consdata->rowub != NULL && ! SCIPisInfinity(scip, SCIPvarGetUbGlobal(var)) && ! SCIPisZero(scip, SCIPvarGetUbGlobal(var)) )
857  	   {
858  	      SCIP_CALL( SCIPaddVarToRow(scip, consdata->rowub, var, 1.0/SCIPvarGetUbGlobal(var)) );
859  	   }
860  	
861  	   /* add the new coefficient to the lower bound LP row, if necessary */
862  	   if ( consdata->rowlb != NULL && ! SCIPisInfinity(scip, SCIPvarGetLbGlobal(var)) && ! SCIPisZero(scip, SCIPvarGetLbGlobal(var)) )
863  	   {
864  	      SCIP_CALL( SCIPaddVarToRow(scip, consdata->rowlb, var, 1.0/SCIPvarGetLbGlobal(var)) );
865  	   }
866  	
867  	   /* return if the conflict graph has not been created yet */
868  	   conflictgraph = conshdlrdata->conflictgraph;
869  	   if ( conflictgraph == NULL )
870  	      return SCIP_OKAY;
871  	
872  	   /* get node of variable in the conflict graph (or -1) */
873  	   node = varGetNodeSOS1(conshdlrdata, var);
874  	   assert( node < conshdlrdata->nsos1vars );
875  	
876  	   /* if the variable is not already a node of the conflict graph */
877  	   if ( node < 0 )
878  	   {
879  	      /* variable does not appear in the conflict graph: switch to SOS1 branching rule, which does not make use of a conflict graph
880  	       * @todo: maybe recompute the conflict graph, implication graph and varhash instead */
881  	      SCIPdebugMsg(scip, "Switched to SOS1 branching rule, since conflict graph could be infeasible.\n");
882  	      conshdlrdata->switchsos1branch = TRUE;
883  	      return SCIP_OKAY;
884  	   }
885  	
886  	   /* if the constraint is local, then there is no need to act, since local constraints are handled by the local conflict graph in the
887  	    * function enforceConflictgraph() */
888  	   if ( ! consdata->local )
889  	   {
890  	      SCIP_VAR** vars;
891  	      int nvars;
892  	      int v;
893  	
894  	      vars = consdata->vars;
895  	      nvars = consdata->nvars;
896  	
897  	      for (v = 0; v < nvars; ++v)
898  	      {
899  	         int nodev;
900  	
901  	         if ( var == vars[v] )
902  	            continue;
903  	
904  	         /* get node of variable in the conflict graph (or -1) */
905  	         nodev = varGetNodeSOS1(conshdlrdata, vars[v]);
906  	         assert( nodev < conshdlrdata->nsos1vars );
907  	
908  	         /* if the variable is already a node of the conflict graph */
909  	         if ( nodev >= 0 )
910  	         {
911  	            int nsucc;
912  	            int nsuccv;
913  	
914  	            nsucc = SCIPdigraphGetNSuccessors(conflictgraph, node);
915  	            nsuccv = SCIPdigraphGetNSuccessors(conflictgraph, nodev);
916  	
917  	            /* add arcs if not existent */
918  	            SCIP_CALL( SCIPdigraphAddArcSafe(conflictgraph, nodev, node, NULL) );
919  	            SCIP_CALL( SCIPdigraphAddArcSafe(conflictgraph, node, nodev, NULL) );
920  	
921  	            /* in case of new arcs: sort successors in ascending order */
922  	            if ( nsucc < SCIPdigraphGetNSuccessors(conflictgraph, node) )
923  	            {
924  	               SCIPdebugMsg(scip, "Added new conflict graph arc from variable %s to variable %s.\n", SCIPvarGetName(var), SCIPvarGetName(vars[v]));
925  	               SCIPsortInt(SCIPdigraphGetSuccessors(conflictgraph, node), SCIPdigraphGetNSuccessors(conflictgraph, node));
926  	            }
927  	
928  	            if ( nsuccv < SCIPdigraphGetNSuccessors(conflictgraph, nodev) )
929  	            {
930  	               SCIPdebugMsg(scip, "Added new conflict graph arc from variable %s to variable %s.\n", SCIPvarGetName(vars[v]), SCIPvarGetName(var));
931  	               SCIPsortInt(SCIPdigraphGetSuccessors(conflictgraph, nodev), SCIPdigraphGetNSuccessors(conflictgraph, nodev));
932  	            }
933  	         }
934  	         else
935  	         {
936  	            /* variable does not appear in the conflict graph: switch to SOS1 branching rule, which does not make use of a conflict graph
937  	             * @todo: maybe recompute the conflict graph, implication graph and varhash instead */
938  	            SCIPdebugMsg(scip, "Switched to SOS1 branching rule, since conflict graph could be infeasible.\n");
939  	            conshdlrdata->switchsos1branch = TRUE;
940  	            return SCIP_OKAY;
941  	         }
942  	      }
943  	   }
944  	
945  	   return SCIP_OKAY;
946  	}
947  	
948  	
949  	/** adds a variable to an SOS1 constraint, at position given by weight - ascending order */
950  	static
951  	SCIP_RETCODE addVarSOS1(
952  	   SCIP*                 scip,               /**< SCIP data structure */
953  	   SCIP_CONS*            cons,               /**< constraint */
954  	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
955  	   SCIP_VAR*             var,                /**< variable to add to the constraint */
956  	   SCIP_Real             weight              /**< weight to determine position */
957  	   )
958  	{
959  	   SCIP_CONSDATA* consdata;
960  	   SCIP_Bool transformed;
961  	   int pos;
962  	   int j;
963  	
964  	   assert( var != NULL );
965  	   assert( cons != NULL );
966  	   assert( conshdlrdata != NULL );
967  	
968  	   consdata = SCIPconsGetData(cons);
969  	   assert( consdata != NULL );
970  	
971  	   if ( consdata->weights == NULL && consdata->maxvars > 0 )
972  	   {
973  	      SCIPerrorMessage("cannot add variable to SOS1 constraint <%s> that does not contain weights.\n", SCIPconsGetName(cons));
974  	      return SCIP_INVALIDCALL;
975  	   }
976  	
977  	   /* are we in the transformed problem? */
978  	   transformed = SCIPconsIsTransformed(cons);
979  	
980  	   /* always use transformed variables in transformed constraints */
981  	   if ( transformed )
982  	   {
983  	      SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
984  	   }
985  	   assert( var != NULL );
986  	   assert( transformed == SCIPvarIsTransformed(var) );
987  	
988  	   SCIP_CALL( consdataEnsurevarsSizeSOS1(scip, consdata, consdata->nvars + 1, TRUE) );
989  	   assert( consdata->weights != NULL );
990  	   assert( consdata->maxvars >= consdata->nvars+1 );
991  	
992  	   /* find variable position */
993  	   for (pos = 0; pos < consdata->nvars; ++pos)
994  	   {
995  	      if ( consdata->weights[pos] > weight )
996  	         break;
997  	   }
998  	   assert( 0 <= pos && pos <= consdata->nvars );
999  	
1000 	   /* move other variables, if necessary */
1001 	   for (j = consdata->nvars; j > pos; --j)
1002 	   {
1003 	      consdata->vars[j] = consdata->vars[j-1];
1004 	      consdata->weights[j] = consdata->weights[j-1];
1005 	   }
1006 	
1007 	   /* insert variable */
1008 	   consdata->vars[pos] = var;
1009 	   consdata->weights[pos] = weight;
1010 	   ++consdata->nvars;
1011 	
1012 	   /* handle the new variable */
1013 	   SCIP_CALL( handleNewVariableSOS1(scip, cons, consdata, conshdlrdata, var, transformed) );
1014 	
1015 	   return SCIP_OKAY;
1016 	}
1017 	
1018 	
1019 	/** appends a variable to an SOS1 constraint */
1020 	static
1021 	SCIP_RETCODE appendVarSOS1(
1022 	   SCIP*                 scip,               /**< SCIP data structure */
1023 	   SCIP_CONS*            cons,               /**< constraint */
1024 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
1025 	   SCIP_VAR*             var                 /**< variable to add to the constraint */
1026 	   )
1027 	{
1028 	   SCIP_CONSDATA* consdata;
1029 	   SCIP_Bool transformed;
1030 	
1031 	   assert( var != NULL );
1032 	   assert( cons != NULL );
1033 	   assert( conshdlrdata != NULL );
1034 	
1035 	   consdata = SCIPconsGetData(cons);
1036 	   assert( consdata != NULL );
1037 	   assert( consdata->nvars >= 0 );
1038 	
1039 	   /* are we in the transformed problem? */
1040 	   transformed = SCIPconsIsTransformed(cons);
1041 	
1042 	   /* always use transformed variables in transformed constraints */
1043 	   if ( transformed )
1044 	   {
1045 	      SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
1046 	   }
1047 	   assert( var != NULL );
1048 	   assert( transformed == SCIPvarIsTransformed(var) );
1049 	
1050 	   if ( consdata->weights != NULL )
1051 	   {
1052 	      SCIP_CALL( consdataEnsurevarsSizeSOS1(scip, consdata, consdata->nvars + 1, TRUE) );
1053 	   }
1054 	   else
1055 	   {
1056 	      SCIP_CALL( consdataEnsurevarsSizeSOS1(scip, consdata, consdata->nvars + 1, FALSE) );
1057 	   }
1058 	
1059 	   /* insert variable */
1060 	   consdata->vars[consdata->nvars] = var;
1061 	   if ( consdata->weights != NULL )
1062 	   {
1063 	      if ( consdata->nvars > 0 )
1064 	         consdata->weights[consdata->nvars] = consdata->weights[consdata->nvars-1] + 1.0;
1065 	      else
1066 	         consdata->weights[consdata->nvars] = 0.0;
1067 	   }
1068 	   ++consdata->nvars;
1069 	
1070 	   /* handle the new variable */
1071 	   SCIP_CALL( handleNewVariableSOS1(scip, cons, consdata, conshdlrdata, var, transformed) );
1072 	
1073 	   return SCIP_OKAY;
1074 	}
1075 	
1076 	
1077 	/** deletes a variable of an SOS1 constraint */
1078 	static
1079 	SCIP_RETCODE deleteVarSOS1(
1080 	   SCIP*                 scip,               /**< SCIP data structure */
1081 	   SCIP_CONS*            cons,               /**< constraint */
1082 	   SCIP_CONSDATA*        consdata,           /**< constraint data */
1083 	   SCIP_EVENTHDLR*       eventhdlr,          /**< corresponding event handler */
1084 	   int                   pos                 /**< position of variable in array */
1085 	   )
1086 	{
1087 	   int j;
1088 	
1089 	   assert( 0 <= pos && pos < consdata->nvars );
1090 	
1091 	   /* remove lock of variable */
1092 	   SCIP_CALL( unlockVariableSOS1(scip, cons, consdata->vars[pos]) );
1093 	
1094 	   /* drop events on variable */
1095 	   SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos], EVENTHDLR_EVENT_TYPE, eventhdlr, (SCIP_EVENTDATA*)cons, -1) ); /*lint !e740*/
1096 	
1097 	   /* delete variable - need to copy since order is important */
1098 	   for (j = pos; j < consdata->nvars-1; ++j)
1099 	   {
1100 	      consdata->vars[j] = consdata->vars[j+1]; /*lint !e679*/
1101 	      if ( consdata->weights != NULL )
1102 	         consdata->weights[j] = consdata->weights[j+1]; /*lint !e679*/
1103 	   }
1104 	   --consdata->nvars;
1105 	
1106 	   return SCIP_OKAY;
1107 	}
1108 	
1109 	
1110 	/* ----------------------------- presolving --------------------------------------*/
1111 	
1112 	/** extends a given clique of the conflict graph
1113 	 *
1114 	 *  Implementation of the Bron-Kerbosch Algorithm from the paper:
1115 	 *  Algorithm 457: Finding all Cliques of an Undirected Graph, Bron & Kerbosch, Commun. ACM, 1973
1116 	 */
1117 	static
1118 	SCIP_RETCODE extensionOperatorSOS1(
1119 	   SCIP*                 scip,               /**< SCIP pointer */
1120 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
1121 	   SCIP_Bool**           adjacencymatrix,    /**< adjacencymatrix of the conflict graph (only lower half filled) */
1122 	   SCIP_DIGRAPH*         vertexcliquegraph,  /**< graph that contains the information which cliques contain a given vertex
1123 	                                              *   vertices of variables = 0, ..., nsos1vars-1; vertices of cliques = nsos1vars, ..., nsos1vars+ncliques-1*/
1124 	   int                   nsos1vars,          /**< number of SOS1 variables */
1125 	   int                   nconss,             /**< number of SOS1 constraints */
1126 	   SCIP_CONS*            cons,               /**< constraint to be extended */
1127 	   SCIP_VAR**            vars,               /**< variables of extended clique */
1128 	   SCIP_Real*            weights,            /**< weights of extended clique */
1129 	   SCIP_Bool             firstcall,          /**< whether this is the first call of extension operator */
1130 	   SCIP_Bool             usebacktrack,       /**< whether backtracking is needed for the computation */
1131 	   int**                 cliques,            /**< all cliques found so far */
1132 	   int*                  ncliques,           /**< number of clique found so far */
1133 	   int*                  cliquesizes,        /**< number of variables of current clique */
1134 	   int*                  newclique,          /**< clique we want to extended*/
1135 	   int*                  workingset,         /**< set of vertices that already served as extension and set of candidates that probably will lead to an extension */
1136 	   int                   nworkingset,        /**< length of array workingset */
1137 	   int                   nexts,              /**< number of vertices that already served as extension */
1138 	   int                   pos,                /**< position of potential candidate */
1139 	   int*                  maxextensions,      /**< maximal number of extensions */
1140 	   int*                  naddconss,          /**< number of added constraints */
1141 	   SCIP_Bool*            success             /**< pointer to store if at least one new clique was found */
1142 	   )
1143 	{
1144 	   int* workingsetnew = NULL;
1145 	   int nextsnew;
1146 	   int nworkingsetnew;
1147 	   int mincands;
1148 	   int btriter = 0; /* backtrack iterator */
1149 	   int selvertex;
1150 	   int selpos = -1;
1151 	   int fixvertex = -1;
1152 	   int i;
1153 	   int j;
1154 	
1155 	   assert( scip != NULL );
1156 	   assert( conshdlrdata != NULL );
1157 	   assert( adjacencymatrix != NULL );
1158 	   assert( vertexcliquegraph != NULL );
1159 	   assert( cons != NULL );
1160 	   assert( cliques != NULL );
1161 	   assert( cliquesizes != NULL );
1162 	   assert( newclique != NULL );
1163 	   assert( workingset != NULL );
1164 	   assert( maxextensions != NULL );
1165 	   assert( naddconss != NULL );
1166 	   assert( success != NULL );
1167 	
1168 	   if ( firstcall )
1169 	      *success = FALSE;
1170 	
1171 	   mincands = nworkingset;
1172 	   if ( mincands < 1 )
1173 	      return SCIP_OKAY;
1174 	
1175 	   /* allocate buffer array */
1176 	   SCIP_CALL( SCIPallocBufferArray(scip, &workingsetnew, nworkingset) );
1177 	
1178 	#ifdef SCIP_DEBUG
1179 	   for (i = 0; i < nexts; ++i)
1180 	   {
1181 	      for (j = nexts; j < nworkingset; ++j)
1182 	      {
1183 	         assert( isConnectedSOS1(adjacencymatrix, NULL, workingset[i], workingset[j]) );
1184 	      }
1185 	   }
1186 	#endif
1187 	
1188 	   /* determine candidate with minimum number of disconnections */
1189 	   for (i = 0; i < nworkingset; ++i)
1190 	   {
1191 	      int vertex;
1192 	      int cnt = 0;
1193 	
1194 	      vertex = workingset[i];
1195 	
1196 	      /* count disconnections */
1197 	      for (j = nexts; j < nworkingset && cnt < mincands; ++j)
1198 	      {
1199 	         if ( vertex != workingset[j] && ! isConnectedSOS1(adjacencymatrix, NULL, vertex, workingset[j]) )
1200 	         {
1201 	            cnt++;
1202 	
1203 	            /* save position of potential candidate */
1204 	            pos = j;
1205 	         }
1206 	      }
1207 	
1208 	      /* check whether a new minimum was found */
1209 	      if ( cnt < mincands )
1210 	      {
1211 	         fixvertex = vertex;
1212 	         mincands = cnt;
1213 	         if ( i < nexts )
1214 	         {
1215 	            assert( pos >= 0 );
1216 	            selpos = pos;
1217 	         }
1218 	         else
1219 	         {
1220 	            selpos = i;
1221 	
1222 	            /* preincrement */
1223 	            btriter = 1;
1224 	         }
1225 	      }
1226 	   }
1227 	
1228 	   /* If fixed point is initially chosen from candidates then number of disconnections will be preincreased by one. */
1229 	
1230 	   /* backtrackcycle */
1231 	   for (btriter = mincands + btriter; btriter >= 1; --btriter)
1232 	   {
1233 	      assert( selpos >= 0);
1234 	      assert( fixvertex >= 0);
1235 	
1236 	      /* interchange */
1237 	      selvertex = workingset[selpos];
1238 	      workingset[selpos] = workingset[nexts];
1239 	      workingset[nexts] = selvertex;
1240 	
1241 	      /* create new workingset */
1242 	      nextsnew = 0;
1243 	      for (j = 0 ; j < nexts; ++j)
1244 	      {
1245 	         if ( isConnectedSOS1(adjacencymatrix, NULL, selvertex, workingset[j]) )
1246 	            workingsetnew[nextsnew++] = workingset[j];
1247 	      }
1248 	      nworkingsetnew = nextsnew;
1249 	      for (j = nexts + 1; j < nworkingset; ++j)
1250 	      {
1251 	         if ( isConnectedSOS1(adjacencymatrix, NULL, selvertex, workingset[j]) )
1252 	            workingsetnew[nworkingsetnew++] = workingset[j];
1253 	      }
1254 	
1255 	      newclique[cliquesizes[*ncliques]++] = selvertex;
1256 	
1257 	      /* if we found a new clique */
1258 	      if ( nworkingsetnew == 0 )
1259 	      {
1260 	         char consname[SCIP_MAXSTRLEN];
1261 	         SCIP_CONSDATA* consdata;
1262 	         SCIP_CONS* newcons;
1263 	         int cliqueind;
1264 	
1265 	         cliqueind = nsos1vars + *ncliques; /* index of clique in the vertex-clique graph */
1266 	
1267 	         /* save new clique */
1268 	         assert( cliquesizes[*ncliques] >= 0 && cliquesizes[*ncliques] <= nsos1vars );
1269 	         assert( *ncliques < MAX(1, conshdlrdata->maxextensions) * nconss );
1270 	         SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(cliques[*ncliques]), cliquesizes[*ncliques]) );/*lint !e866*/
1271 	         for (j = 0 ; j < cliquesizes[*ncliques]; ++j)
1272 	         {
1273 	            vars[j] = SCIPnodeGetVarSOS1(conshdlrdata->conflictgraph, newclique[j]);
1274 	            weights[j] = j+1;
1275 	            cliques[*ncliques][j] = newclique[j];
1276 	         }
1277 	
1278 	         SCIPsortInt(cliques[*ncliques], cliquesizes[*ncliques]);
1279 	
1280 	         /* create new constraint */
1281 	         (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "extsos1_%d", conshdlrdata->cntextsos1);
1282 	
1283 	         SCIP_CALL( SCIPcreateConsSOS1(scip, &newcons, consname, cliquesizes[*ncliques], vars, weights,
1284 	               SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons),
1285 	               SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
1286 	               SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
1287 	               SCIPconsIsDynamic(cons),
1288 	               SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
1289 	
1290 	         consdata = SCIPconsGetData(newcons);
1291 	
1292 	         /* add directed edges to the vertex-clique graph */
1293 	         for (j = 0; j < consdata->nvars; ++j)
1294 	         {
1295 	            /* add arc from clique vertex to clique (needed in presolRoundConssSOS1() to delete redundand cliques) */
1296 	            SCIP_CALL( SCIPdigraphAddArcSafe(vertexcliquegraph, cliques[*ncliques][j], cliqueind, NULL) );
1297 	         }
1298 	
1299 	         SCIP_CALL( SCIPaddCons(scip, newcons) );
1300 	         SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
1301 	
1302 	         ++(*naddconss);
1303 	         ++(conshdlrdata->cntextsos1);
1304 	         ++(*ncliques);
1305 	         cliquesizes[*ncliques] = cliquesizes[*ncliques-1]; /* cliquesizes[*ncliques] = size of newclique */
1306 	
1307 	         *success = TRUE;
1308 	
1309 	         --(*maxextensions);
1310 	
1311 	         if ( *maxextensions <= 0 )
1312 	         {
1313 	            SCIPfreeBufferArray(scip, &workingsetnew);
1314 	            return SCIP_OKAY;
1315 	         }
1316 	      }
1317 	      else if ( nextsnew < nworkingsetnew ) /* else if the number of of candidates equals zero */
1318 	      {
1319 	         /* if backtracking is used, it is necessary to keep the memory for 'workingsetnew' */
1320 	         if ( usebacktrack )
1321 	         {
1322 	            SCIP_CALL( extensionOperatorSOS1(scip, conshdlrdata, adjacencymatrix, vertexcliquegraph, nsos1vars, nconss, cons, vars, weights, FALSE, usebacktrack,
1323 	                  cliques, ncliques, cliquesizes, newclique, workingsetnew, nworkingsetnew, nextsnew, pos, maxextensions, naddconss, success) );
1324 	            if ( *maxextensions <= 0 )
1325 	            {
1326 	               SCIPfreeBufferArrayNull(scip, &workingsetnew);
1327 	               return SCIP_OKAY;
1328 	            }
1329 	         }
1330 	         else
1331 	         {
1332 	            int w;
1333 	
1334 	            assert( nworkingset >= nworkingsetnew );
1335 	            for (w = 0; w < nworkingsetnew; ++w)
1336 	               workingset[w] = workingsetnew[w];
1337 	            nworkingset = nworkingsetnew;
1338 	
1339 	            SCIPfreeBufferArrayNull(scip, &workingsetnew);
1340 	
1341 	            SCIP_CALL( extensionOperatorSOS1(scip, conshdlrdata, adjacencymatrix, vertexcliquegraph, nsos1vars, nconss, cons, vars, weights, FALSE, usebacktrack,
1342 	                  cliques, ncliques, cliquesizes, newclique, workingset, nworkingset, nextsnew, pos, maxextensions, naddconss, success) );
1343 	            assert( *maxextensions <= 0 );
1344 	            return SCIP_OKAY;
1345 	         }
1346 	      }
1347 	      assert( workingsetnew != NULL );
1348 	      assert( workingset != NULL );
1349 	
1350 	      /* remove selvertex from clique */
1351 	      --cliquesizes[*ncliques];
1352 	
1353 	      /* add selvertex to the set of vertices that already served as extension */
1354 	      ++nexts;
1355 	
1356 	      if ( btriter > 1 )
1357 	      {
1358 	         /* select a candidate that is not connected to the fixed vertex */
1359 	         for (j = nexts; j < nworkingset; ++j)
1360 	         {
1361 	            assert( fixvertex != workingset[j] );
1362 	            if ( ! isConnectedSOS1(adjacencymatrix, NULL, fixvertex, workingset[j]) )
1363 	            {
1364 	               selpos = j;
1365 	               break;
1366 	            }
1367 	         }
1368 	      }
1369 	   }
1370 	
1371 	   SCIPfreeBufferArrayNull(scip, &workingsetnew);
1372 	
1373 	   return SCIP_OKAY;
1374 	}
1375 	
1376 	
1377 	/** generates conflict graph that is induced by the variables of a linear constraint */
1378 	static
1379 	SCIP_RETCODE genConflictgraphLinearCons(
1380 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
1381 	   SCIP_DIGRAPH*         conflictgraphlin,   /**< conflict graph of linear constraint (nodes: 1, ..., nlinvars) */
1382 	   SCIP_DIGRAPH*         conflictgraphorig,  /**< original conflict graph (nodes: 1, ..., nsos1vars) */
1383 	   SCIP_VAR**            linvars,            /**< linear variables in linear constraint */
1384 	   int                   nlinvars,           /**< number of linear variables in linear constraint */
1385 	   int*                  posinlinvars        /**< posinlinvars[i] = position (index) of SOS1 variable i in linear constraint,
1386 	                                              *   posinlinvars[i]= -1 if @p i is not a SOS1 variable or not a variable of the linear constraint */
1387 	   )
1388 	{
1389 	   int indexinsosvars;
1390 	   int indexinlinvars;
1391 	   int* succ;
1392 	   int nsucc;
1393 	   int v;
1394 	   int s;
1395 	
1396 	   assert( conflictgraphlin != NULL );
1397 	   assert( conflictgraphorig != NULL );
1398 	   assert( linvars != NULL );
1399 	   assert( posinlinvars != NULL );
1400 	
1401 	   for (v = 1; v < nlinvars; ++v) /* we start with v = 1, since "indexinlinvars < v" (see below) is never fulfilled for v = 0 */
1402 	   {
1403 	      indexinsosvars = varGetNodeSOS1(conshdlrdata, linvars[v]);
1404 	
1405 	      /* if linvars[v] is contained in at least one SOS1 constraint */
1406 	      if ( indexinsosvars >= 0 )
1407 	      {
1408 	         succ = SCIPdigraphGetSuccessors(conflictgraphorig, indexinsosvars);
1409 	         nsucc = SCIPdigraphGetNSuccessors(conflictgraphorig, indexinsosvars);
1410 	
1411 	         for (s = 0; s < nsucc; ++s)
1412 	         {
1413 	            assert( succ[s] >= 0 );
1414 	            indexinlinvars = posinlinvars[succ[s]];
1415 	            assert( indexinlinvars < nlinvars );
1416 	
1417 	            if ( indexinlinvars >= 0 && indexinlinvars < v )
1418 	            {
1419 	               SCIP_CALL( SCIPdigraphAddArcSafe(conflictgraphlin, v, indexinlinvars, NULL) );
1420 	               SCIP_CALL( SCIPdigraphAddArcSafe(conflictgraphlin, indexinlinvars, v, NULL) );
1421 	            }
1422 	         }
1423 	      }
1424 	   }
1425 	
1426 	   return SCIP_OKAY;
1427 	}
1428 	
1429 	
1430 	/** determine the common successors of the vertices from the considered clique */
1431 	static
1432 	SCIP_RETCODE cliqueGetCommonSuccessorsSOS1(
1433 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
1434 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
1435 	   int*                  clique,             /**< current clique */
1436 	   SCIP_VAR**            vars,               /**< clique variables */
1437 	   int                   nvars,              /**< number of clique variables */
1438 	   int*                  comsucc,            /**< pointer to store common successors of clique vertices (size = nvars) */
1439 	   int*                  ncomsucc            /**< pointer to store number common successors of clique vertices */
1440 	   )
1441 	{
1442 	   int nsucc;
1443 	   int* succ;
1444 	   int ind;
1445 	   int k = 0;
1446 	   int v;
1447 	   int i;
1448 	   int j;
1449 	
1450 	   assert( conflictgraph != NULL );
1451 	   assert( clique != NULL );
1452 	   assert( vars != NULL );
1453 	   assert( comsucc != NULL );
1454 	   assert( ncomsucc != NULL );
1455 	
1456 	   *ncomsucc = 0;
1457 	
1458 	   /* determine the common successors of the vertices from the considered clique */
1459 	
1460 	   /* determine successors of variable var[0] that are not in the clique */
1461 	   assert(vars[0] != NULL );
1462 	   ind =  varGetNodeSOS1(conshdlrdata, vars[0]);
1463 	
1464 	   if( ind == -1 )
1465 	      return SCIP_INVALIDDATA;
1466 	
1467 	   assert( ind < SCIPdigraphGetNNodes(conflictgraph) );
1468 	   nsucc = SCIPdigraphGetNSuccessors(conflictgraph, ind);
1469 	   succ = SCIPdigraphGetSuccessors(conflictgraph, ind);
1470 	
1471 	   for (j = 0; j < nvars; ++j)
1472 	   {
1473 	      for (i = k; i < nsucc; ++i)
1474 	      {
1475 	         if ( succ[i] > clique[j] )
1476 	         {
1477 	            k = i;
1478 	            break;
1479 	         }
1480 	         else if ( succ[i] == clique[j] )
1481 	         {
1482 	            k = i + 1;
1483 	            break;
1484 	         }
1485 	         else
1486 	            comsucc[(*ncomsucc)++] = succ[i];
1487 	      }
1488 	   }
1489 	
1490 	   /* for all variables except the first one */
1491 	   for (v = 1; v < nvars; ++v)
1492 	   {
1493 	      int ncomsuccsave = 0;
1494 	      k = 0;
1495 	
1496 	      assert(vars[v] != NULL );
1497 	      ind =  varGetNodeSOS1(conshdlrdata, vars[v]);
1498 	      assert( ind >= 0 && ind < SCIPdigraphGetNNodes(conflictgraph) );
1499 	
1500 	      if ( ind >= 0 )
1501 	      {
1502 	         nsucc = SCIPdigraphGetNSuccessors(conflictgraph, ind);
1503 	         succ = SCIPdigraphGetSuccessors(conflictgraph, ind);
1504 	
1505 	         /* determine successors that are in comsucc */
1506 	         for (j = 0; j < *ncomsucc; ++j)
1507 	         {
1508 	            for (i = k; i < nsucc; ++i)
1509 	            {
1510 	               if ( succ[i] > comsucc[j] )
1511 	               {
1512 	                  k = i;
1513 	                  break;
1514 	               }
1515 	               else if ( succ[i] == comsucc[j] )
1516 	               {
1517 	                  comsucc[ncomsuccsave++] = succ[i];
1518 	                  k = i + 1;
1519 	                  break;
1520 	               }
1521 	            }
1522 	         }
1523 	         *ncomsucc = ncomsuccsave;
1524 	      }
1525 	   }
1526 	
1527 	   return SCIP_OKAY;
1528 	}
1529 	
1530 	
1531 	/** get nodes whose corresponding SOS1 variables are nonzero if an SOS1 variable of a given node is nonzero */
1532 	static
1533 	SCIP_RETCODE getSOS1Implications(
1534 	   SCIP*                 scip,               /**< SCIP pointer */
1535 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
1536 	   SCIP_VAR**            vars,               /**< problem and SOS1 variables */
1537 	   SCIP_DIGRAPH*         implgraph,          /**< implication graph (@p j is successor of @p i if and only if \f$ x_i\not = 0 \Rightarrow x_j\not = 0\f$) */
1538 	   SCIP_HASHMAP*         implhash,           /**< hash map from variable to node in implication graph */
1539 	   SCIP_Bool*            implnodes,          /**< implnodes[i] = TRUE if the SOS1 variable corresponding to node i in the implication graph is implied to be nonzero */
1540 	   int                   node                /**< node of the implication graph */
1541 	   )
1542 	{
1543 	   SCIP_SUCCDATA** succdatas;
1544 	   int sos1node;
1545 	   int* succ;
1546 	   int nsucc;
1547 	   int s;
1548 	
1549 	   assert( scip != NULL );
1550 	   assert( implgraph != NULL );
1551 	   assert( implnodes != NULL );
1552 	   assert( node >= 0 );
1553 	   assert( vars[node] != NULL );
1554 	   assert( SCIPhashmapGetImageInt(implhash, vars[node]) == node );
1555 	
1556 	   /* get node of variable in the conflict graph (-1 if variable is no SOS1 variable) */
1557 	   sos1node = varGetNodeSOS1(conshdlrdata, vars[node]);
1558 	   if ( sos1node < 0 )
1559 	      return SCIP_OKAY;
1560 	
1561 	   succdatas = (SCIP_SUCCDATA**) SCIPdigraphGetSuccessorsData(implgraph, node);
1562 	   nsucc = SCIPdigraphGetNSuccessors(implgraph, node);
1563 	   succ = SCIPdigraphGetSuccessors(implgraph, node);
1564 	
1565 	   for (s = 0; s < nsucc; ++s)
1566 	   {
1567 	      SCIP_SUCCDATA* data;
1568 	      int succnode;
1569 	      succnode = succ[s];
1570 	      data = succdatas[s];
1571 	      sos1node = varGetNodeSOS1(conshdlrdata, vars[succnode]);
1572 	
1573 	      /* if node is SOS1 and the corresponding variable is implied to be nonzero */
1574 	      assert( succdatas[s] != NULL );
1575 	      if ( sos1node >= 0 && ! implnodes[sos1node] && ( SCIPisFeasPositive(scip, data->lbimpl) || SCIPisFeasNegative(scip, data->ubimpl) ) )
1576 	      {
1577 	         assert( sos1node == succnode );
1578 	         implnodes[sos1node] = TRUE;
1579 	         SCIP_CALL( getSOS1Implications(scip, conshdlrdata, vars, implgraph, implhash, implnodes, succnode) );
1580 	      }
1581 	   }
1582 	
1583 	   return SCIP_OKAY;
1584 	}
1585 	
1586 	
1587 	/** perform one presolving round for a single SOS1 constraint
1588 	 *
1589 	 *  We perform the following presolving steps.
1590 	 *
1591 	 *  - If the bounds of some variable force it to be nonzero, we can
1592 	 *    fix all other variables to zero and remove the SOS1 constraints
1593 	 *    that contain it.
1594 	 *  - If a variable is fixed to zero, we can remove the variable.
1595 	 *  - If a variable appears twice, it can be fixed to 0.
1596 	 *  - We substitute appregated variables.
1597 	 */
1598 	static
1599 	SCIP_RETCODE presolRoundConsSOS1(
1600 	   SCIP*                 scip,               /**< SCIP pointer */
1601 	   SCIP_CONS*            cons,               /**< constraint */
1602 	   SCIP_CONSDATA*        consdata,           /**< constraint data */
1603 	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
1604 	   SCIP_Bool*            substituted,        /**< whether a variable was substituted */
1605 	   SCIP_Bool*            cutoff,             /**< whether a cutoff happened */
1606 	   SCIP_Bool*            success,            /**< whether we performed a successful reduction */
1607 	   int*                  ndelconss,          /**< number of deleted constraints */
1608 	   int*                  nupgdconss,         /**< number of upgraded constraints */
1609 	   int*                  nfixedvars,         /**< number of fixed variables */
1610 	   int*                  nremovedvars        /**< number of variables removed */
1611 	   )
1612 	{
1613 	   SCIP_VAR** vars;
1614 	   SCIP_Bool allvarsbinary;
1615 	   SCIP_Bool infeasible;
1616 	   SCIP_Bool fixed;
1617 	   int nfixednonzeros;
1618 	   int lastFixedNonzero;
1619 	   int j;
1620 	
1621 	   assert( scip != NULL );
1622 	   assert( cons != NULL );
1623 	   assert( consdata != NULL );
1624 	   assert( eventhdlr != NULL );
1625 	   assert( cutoff != NULL );
1626 	   assert( success != NULL );
1627 	   assert( ndelconss != NULL );
1628 	   assert( nfixedvars != NULL );
1629 	   assert( nremovedvars != NULL );
1630 	
1631 	   *substituted = FALSE;
1632 	   *cutoff = FALSE;
1633 	   *success = FALSE;
1634 	
1635 	   SCIPdebugMsg(scip, "Presolving SOS1 constraint <%s>.\n", SCIPconsGetName(cons) );
1636 	
1637 	   j = 0;
1638 	   nfixednonzeros = 0;
1639 	   lastFixedNonzero = -1;
1640 	   allvarsbinary = TRUE;
1641 	   vars = consdata->vars;
1642 	
1643 	   /* check for variables fixed to 0 and bounds that fix a variable to be nonzero */
1644 	   while ( j < consdata->nvars )
1645 	   {
1646 	      int l;
1647 	      SCIP_VAR* var;
1648 	      SCIP_Real lb;
1649 	      SCIP_Real ub;
1650 	      SCIP_Real scalar;
1651 	      SCIP_Real constant;
1652 	
1653 	      scalar = 1.0;
1654 	      constant = 0.0;
1655 	
1656 	      /* check for aggregation: if the constant is zero the variable is zero iff the aggregated
1657 	       * variable is 0 */
1658 	      var = vars[j];
1659 	      SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
1660 	
1661 	      /* if constant is zero and we get a different variable, substitute variable */
1662 	      if ( SCIPisZero(scip, constant) && ! SCIPisZero(scip, scalar) && var != vars[j] )
1663 	      {
1664 	         SCIPdebugMsg(scip, "substituted variable <%s> by <%s>.\n", SCIPvarGetName(vars[j]), SCIPvarGetName(var));
1665 	         SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[j], EVENTHDLR_EVENT_TYPE, eventhdlr, (SCIP_EVENTDATA*)cons, -1) ); /*lint !e740*/
1666 	         SCIP_CALL( SCIPcatchVarEvent(scip, var, EVENTHDLR_EVENT_TYPE, eventhdlr, (SCIP_EVENTDATA*)cons, NULL) ); /*lint !e740*/
1667 	
1668 	         /* change the rounding locks */
1669 	         SCIP_CALL( unlockVariableSOS1(scip, cons, consdata->vars[j]) );
1670 	         SCIP_CALL( lockVariableSOS1(scip, cons, var) );
1671 	
1672 	         vars[j] = var;
1673 	         *substituted = TRUE;
1674 	      }
1675 	
1676 	      /* check whether the variable appears again later */
1677 	      for (l = j+1; l < consdata->nvars; ++l)
1678 	      {
1679 	         /* if variable appeared before, we can fix it to 0 and remove it */
1680 	         if ( vars[j] == vars[l] )
1681 	         {
1682 	            SCIPdebugMsg(scip, "variable <%s> appears twice in constraint, fixing it to 0.\n", SCIPvarGetName(vars[j]));
1683 	            SCIP_CALL( SCIPfixVar(scip, vars[j], 0.0, &infeasible, &fixed) );
1684 	
1685 	            if ( infeasible )
1686 	            {
1687 	               *cutoff = TRUE;
1688 	               return SCIP_OKAY;
1689 	            }
1690 	            if ( fixed )
1691 	               ++(*nfixedvars);
1692 	         }
1693 	      }
1694 	
1695 	      /* get bounds */
1696 	      lb = SCIPvarGetLbLocal(vars[j]);
1697 	      ub = SCIPvarGetUbLocal(vars[j]);
1698 	
1699 	      /* if the variable if fixed to nonzero */
1700 	      if ( SCIPisFeasPositive(scip, lb) || SCIPisFeasNegative(scip, ub) )
1701 	      {
1702 	         ++nfixednonzeros;
1703 	         lastFixedNonzero = j;
1704 	      }
1705 	
1706 	      /* if the variable is fixed to 0 */
1707 	      if ( SCIPisFeasZero(scip, lb) && SCIPisFeasZero(scip, ub) )
1708 	      {
1709 	         SCIPdebugMsg(scip, "deleting variable <%s> fixed to 0.\n", SCIPvarGetName(vars[j]));
1710 	         SCIP_CALL( deleteVarSOS1(scip, cons, consdata, eventhdlr, j) );
1711 	         ++(*nremovedvars);
1712 	      }
1713 	      else
1714 	      {
1715 	         /* check whether all variables are binary */
1716 	         if ( ! SCIPvarIsBinary(vars[j]) )
1717 	            allvarsbinary = FALSE;
1718 	
1719 	         ++j;
1720 	      }
1721 	   }
1722 	
1723 	   /* if the number of variables is less than 2 */
1724 	   if ( consdata->nvars < 2 )
1725 	   {
1726 	      SCIPdebugMsg(scip, "Deleting SOS1 constraint <%s> with < 2 variables.\n", SCIPconsGetName(cons));
1727 	
1728 	      /* delete constraint */
1729 	      assert( ! SCIPconsIsModifiable(cons) );
1730 	      SCIP_CALL( SCIPdelCons(scip, cons) );
1731 	      ++(*ndelconss);
1732 	      *success = TRUE;
1733 	      return SCIP_OKAY;
1734 	   }
1735 	
1736 	   /* if more than one variable are fixed to be nonzero, we are infeasible */
1737 	   if ( nfixednonzeros > 1 )
1738 	   {
1739 	      SCIPdebugMsg(scip, "The problem is infeasible: more than one variable has bounds that keep it from being 0.\n");
1740 	      assert( lastFixedNonzero >= 0 );
1741 	      *cutoff = TRUE;
1742 	      return SCIP_OKAY;
1743 	   }
1744 	
1745 	   /* if there is exactly one fixed nonzero variable */
1746 	   if ( nfixednonzeros == 1 )
1747 	   {
1748 	      assert( lastFixedNonzero >= 0 );
1749 	
1750 	      /* fix all other variables to zero */
1751 	      for (j = 0; j < consdata->nvars; ++j)
1752 	      {
1753 	         if ( j != lastFixedNonzero )
1754 	         {
1755 	            SCIP_CALL( fixVariableZero(scip, vars[j], &infeasible, &fixed) );
1756 	            if ( infeasible )
1757 	            {
1758 	               *cutoff = TRUE;
1759 	               return SCIP_OKAY;
1760 	            }
1761 	            if ( fixed )
1762 	               ++(*nfixedvars);
1763 	         }
1764 	      }
1765 	
1766 	      SCIPdebugMsg(scip, "Deleting redundant SOS1 constraint <%s> with one variable.\n", SCIPconsGetName(cons));
1767 	
1768 	      /* delete original constraint */
1769 	      assert( ! SCIPconsIsModifiable(cons) );
1770 	      SCIP_CALL( SCIPdelCons(scip, cons) );
1771 	      ++(*ndelconss);
1772 	      *success = TRUE;
1773 	   }
1774 	   /* note: there is no need to update consdata->nfixednonzeros, since the constraint is deleted as soon nfixednonzeros > 0. */
1775 	   else
1776 	   {
1777 	      /* if all variables are binary create a set packing constraint */
1778 	      if ( allvarsbinary && SCIPfindConshdlr(scip, "setppc") != NULL )
1779 	      {
1780 	         SCIP_CONS* setpackcons;
1781 	
1782 	         /* create, add, and release the logicor constraint */
1783 	         SCIP_CALL( SCIPcreateConsSetpack(scip, &setpackcons, SCIPconsGetName(cons), consdata->nvars, consdata->vars,
1784 	               SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
1785 	               SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons),
1786 	               SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
1787 	         SCIP_CALL( SCIPaddCons(scip, setpackcons) );
1788 	         SCIP_CALL( SCIPreleaseCons(scip, &setpackcons) );
1789 	
1790 	         SCIPdebugMsg(scip, "Upgrading SOS1 constraint <%s> to set packing constraint.\n", SCIPconsGetName(cons));
1791 	
1792 	         /* remove the SOS1 constraint globally */
1793 	         assert( ! SCIPconsIsModifiable(cons) );
1794 	         SCIP_CALL( SCIPdelCons(scip, cons) );
1795 	         ++(*nupgdconss);
1796 	         *success = TRUE;
1797 	      }
1798 	   }
1799 	
1800 	   return SCIP_OKAY;
1801 	}
1802 	
1803 	
1804 	
1805 	/** perform one presolving round for all SOS1 constraints
1806 	 *
1807 	 *  We perform the following presolving steps.
1808 	 *
1809 	 *  - If the bounds of some variable force it to be nonzero, we can
1810 	 *    fix all other variables to zero and remove the SOS1 constraints
1811 	 *    that contain it.
1812 	 *  - If a variable is fixed to zero, we can remove the variable.
1813 	 *  - If a variable appears twice, it can be fixed to 0.
1814 	 *  - We substitute appregated variables.
1815 	 *  - Remove redundant SOS1 constraints
1816 	 *
1817 	 *  If the adjacency matrix of the conflict graph is present, then
1818 	 *  we perform the following additional presolving steps
1819 	 *
1820 	 *  - Search for larger SOS1 constraints in the conflict graph
1821 	 *
1822 	 *  @todo Use one long array for storing cliques.
1823 	 */
1824 	static
1825 	SCIP_RETCODE presolRoundConssSOS1(
1826 	   SCIP*                 scip,               /**< SCIP pointer */
1827 	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
1828 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
1829 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
1830 	   SCIP_Bool**           adjacencymatrix,    /**< adjacency matrix of conflict graph (or NULL) */
1831 	   SCIP_CONS**           conss,              /**< SOS1 constraints */
1832 	   int                   nconss,             /**< number of SOS1 constraints */
1833 	   int                   nsos1vars,          /**< number of SOS1 variables */
1834 	   int*                  naddconss,          /**< number of added constraints */
1835 	   int*                  ndelconss,          /**< number of deleted constraints */
1836 	   int*                  nupgdconss,         /**< number of upgraded constraints */
1837 	   int*                  nfixedvars,         /**< number of fixed variables */
1838 	   int*                  nremovedvars,       /**< number of variables removed */
1839 	   SCIP_RESULT*          result              /**< result */
1840 	   )
1841 	{
1842 	   SCIP_DIGRAPH* vertexcliquegraph;
1843 	   SCIP_VAR** consvars;
1844 	   SCIP_Real* consweights;
1845 	   int** cliques = NULL;
1846 	   int ncliques = 0;
1847 	   int* cliquesizes = NULL;
1848 	   int* newclique = NULL;
1849 	   int* indconss = NULL;
1850 	   int* lengthconss = NULL;
1851 	   int* comsucc = NULL;
1852 	   int csize;
1853 	   int iter;
1854 	   int c;
1855 	
1856 	   assert( scip != NULL );
1857 	   assert( eventhdlr != NULL );
1858 	   assert( conshdlrdata != NULL );
1859 	   assert( conflictgraph != NULL );
1860 	   assert( conss != NULL );
1861 	   assert( naddconss != NULL );
1862 	   assert( ndelconss != NULL );
1863 	   assert( nupgdconss != NULL );
1864 	   assert( nfixedvars != NULL );
1865 	   assert( nremovedvars != NULL );
1866 	   assert( result != NULL );
1867 	
1868 	   /* create digraph whose nodes represent variables and cliques in the conflict graph */
1869 	   csize = MAX(1, conshdlrdata->maxextensions) * nconss;
1870 	   SCIP_CALL( SCIPcreateDigraph(scip, &vertexcliquegraph, nsos1vars + csize) );
1871 	
1872 	   /* allocate buffer arrays */
1873 	   SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nsos1vars) );
1874 	   SCIP_CALL( SCIPallocBufferArray(scip, &consweights, nsos1vars) );
1875 	   SCIP_CALL( SCIPallocBufferArray(scip, &newclique, nsos1vars) );
1876 	   SCIP_CALL( SCIPallocBufferArray(scip, &indconss, csize) );
1877 	   SCIP_CALL( SCIPallocBufferArray(scip, &lengthconss, csize) );
1878 	   SCIP_CALL( SCIPallocBufferArray(scip, &comsucc, MAX(nsos1vars, csize)) );
1879 	
1880 	   /* Use block memory for cliques, because sizes might be quite different and allocation interfers with workingset. */
1881 	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &cliquesizes, csize) );
1882 	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &cliques, csize) );
1883 	
1884 	   /* get constraint indices and sort them in descending order of their lengths */
1885 	   for (c = 0; c < nconss; ++c)
1886 	   {
1887 	      SCIP_CONSDATA* consdata;
1888 	
1889 	      consdata = SCIPconsGetData(conss[c]);
1890 	      assert( consdata != NULL );
1891 	
1892 	      indconss[c] = c;
1893 	      lengthconss[c] = consdata->nvars;
1894 	   }
1895 	   SCIPsortDownIntInt(lengthconss, indconss, nconss);
1896 	
1897 	   /* check each constraint */
1898 	   for (iter = 0; iter < nconss; ++iter)
1899 	   {
1900 	      SCIP_CONSDATA* consdata;
1901 	      SCIP_CONS* cons;
1902 	      SCIP_Bool substituted;
1903 	      SCIP_Bool success;
1904 	      SCIP_Bool cutoff;
1905 	      int savennupgdconss;
1906 	      int savendelconss;
1907 	
1908 	      SCIP_VAR** vars;
1909 	      int nvars;
1910 	
1911 	      c = indconss[iter];
1912 	
1913 	      assert( conss != NULL );
1914 	      assert( conss[c] != NULL );
1915 	      cons = conss[c];
1916 	      consdata = SCIPconsGetData(cons);
1917 	
1918 	      assert( consdata != NULL );
1919 	      assert( consdata->nvars >= 0 );
1920 	      assert( consdata->nvars <= consdata->maxvars );
1921 	      assert( ! SCIPconsIsModifiable(cons) );
1922 	      assert( ncliques < csize );
1923 	
1924 	      savendelconss = *ndelconss;
1925 	      savennupgdconss = *nupgdconss;
1926 	
1927 	      /* perform one presolving round for SOS1 constraint */
1928 	      SCIP_CALL( presolRoundConsSOS1(scip, cons, consdata, eventhdlr, &substituted, &cutoff, &success, ndelconss, nupgdconss, nfixedvars, nremovedvars) );
1929 	
1930 	      if ( cutoff )
1931 	      {
1932 	         *result = SCIP_CUTOFF;
1933 	         break;
1934 	      }
1935 	
1936 	      if ( *ndelconss > savendelconss || *nupgdconss > savennupgdconss || substituted )
1937 	      {
1938 	         *result = SCIP_SUCCESS;
1939 	         continue;
1940 	      }
1941 	
1942 	      if ( success )
1943 	         *result = SCIP_SUCCESS;
1944 	
1945 	      /* get number of variables of constraint */
1946 	      nvars = consdata->nvars;
1947 	
1948 	      /* get variables of constraint */
1949 	      vars = consdata->vars;
1950 	
1951 	      if ( nvars > 1 && conshdlrdata->maxextensions != 0 )
1952 	      {
1953 	         SCIP_Bool extended = FALSE;
1954 	         int cliquesize = 0;
1955 	         int ncomsucc = 0;
1956 	         int varprobind;
1957 	         int j;
1958 	
1959 	         /* get clique and size of clique */
1960 	         for (j = 0; j < nvars; ++j)
1961 	         {
1962 	            varprobind = varGetNodeSOS1(conshdlrdata, vars[j]);
1963 	
1964 	            if ( varprobind >= 0 )
1965 	               newclique[cliquesize++] = varprobind;
1966 	         }
1967 	
1968 	         if ( cliquesize > 1 )
1969 	         {
1970 	            cliquesizes[ncliques] = cliquesize;
1971 	
1972 	            /* sort clique vertices */
1973 	            SCIPsortInt(newclique, cliquesizes[ncliques]);
1974 	
1975 	            /* check if clique is contained in an already known clique */
1976 	            if ( ncliques > 0 )
1977 	            {
1978 	               int* succ;
1979 	               int nsucc;
1980 	               int v;
1981 	
1982 	               varprobind = newclique[0];
1983 	               ncomsucc = SCIPdigraphGetNSuccessors(vertexcliquegraph, varprobind);
1984 	               succ = SCIPdigraphGetSuccessors(vertexcliquegraph, varprobind);
1985 	
1986 	               /* get all (already processed) cliques that contain 'varpropind' */
1987 	               for (j = 0; j < ncomsucc; ++j)
1988 	               {
1989 	                  /* successors should have been sorted in a former step of the algorithm */
1990 	                  assert( j == 0 || succ[j] > succ[j-1] );
1991 	                  comsucc[j] = succ[j];
1992 	               }
1993 	
1994 	               /* loop through remaining nodes of clique (case v = 0 already processed) */
1995 	               for (v = 1; v < cliquesize && ncomsucc > 0; ++v)
1996 	               {
1997 	                  varprobind = newclique[v];
1998 	
1999 	                  /* get all (already processed) cliques that contain 'varpropind' */
2000 	                  nsucc = SCIPdigraphGetNSuccessors(vertexcliquegraph, varprobind);
2001 	                  succ = SCIPdigraphGetSuccessors(vertexcliquegraph, varprobind);
2002 	                  assert( succ != NULL || nsucc == 0 );
2003 	
2004 	                  if ( nsucc < 1 )
2005 	                  {
2006 	                     ncomsucc = 0;
2007 	                     break;
2008 	                  }
2009 	
2010 	                  /* get intersection with comsucc */
2011 	                  SCIPcomputeArraysIntersectionInt(comsucc, ncomsucc, succ, nsucc, comsucc, &ncomsucc);
2012 	               }
2013 	            }
2014 	
2015 	            /* if constraint is redundand then delete it */
2016 	            if ( ncomsucc > 0 )
2017 	            {
2018 	               assert( ! SCIPconsIsModifiable(cons) );
2019 	               SCIP_CALL( SCIPdelCons(scip, cons) );
2020 	               ++(*ndelconss);
2021 	               *result = SCIP_SUCCESS;
2022 	               continue;
2023 	            }
2024 	
2025 	            if ( conshdlrdata->maxextensions != 0 && adjacencymatrix != NULL )
2026 	            {
2027 	               int maxextensions;
2028 	               ncomsucc = 0;
2029 	
2030 	               /* determine the common successors of the vertices from the considered clique */
2031 	               SCIP_CALL( cliqueGetCommonSuccessorsSOS1(conshdlrdata, conflictgraph, newclique, vars, nvars, comsucc, &ncomsucc) );
2032 	
2033 	               /* find extensions for the clique */
2034 	               maxextensions = conshdlrdata->maxextensions;
2035 	               extended = FALSE;
2036 	               SCIP_CALL( extensionOperatorSOS1(scip, conshdlrdata, adjacencymatrix, vertexcliquegraph, nsos1vars, nconss, cons, consvars, consweights,
2037 	                     TRUE, (maxextensions <= 1) ? FALSE : TRUE, cliques, &ncliques, cliquesizes, newclique, comsucc, ncomsucc, 0, -1, &maxextensions,
2038 	                     naddconss, &extended) );
2039 	            }
2040 	
2041 	            /* if an extension was found for the current clique then free the old SOS1 constraint */
2042 	            if ( extended )
2043 	            {
2044 	               assert( ! SCIPconsIsModifiable(cons) );
2045 	               SCIP_CALL( SCIPdelCons(scip, cons) );
2046 	               ++(*ndelconss);
2047 	               *result = SCIP_SUCCESS;
2048 	            }
2049 	            else /* if we keep the constraint */
2050 	            {
2051 	               int cliqueind;
2052 	
2053 	               cliqueind = nsos1vars + ncliques; /* index of clique in vertex-clique graph */
2054 	
2055 	               /* add directed edges to the vertex-clique graph */
2056 	               assert( cliquesize >= 0 && cliquesize <= nsos1vars );
2057 	               assert( ncliques < csize );
2058 	               SCIP_CALL( SCIPallocBlockMemoryArray(scip, &cliques[ncliques], cliquesize) );/*lint !e866*/
2059 	               for (j = 0; j < cliquesize; ++j)
2060 	               {
2061 	                  cliques[ncliques][j] = newclique[j];
2062 	                  SCIP_CALL( SCIPdigraphAddArcSafe(vertexcliquegraph, cliques[ncliques][j], cliqueind, NULL) );
2063 	               }
2064 	
2065 	               /* update number of maximal cliques */
2066 	               ++ncliques;
2067 	            }
2068 	         }
2069 	      }
2070 	   }
2071 	
2072 	   /* free buffer arrays */
2073 	   for (c = ncliques-1; c >= 0; --c)
2074 	      SCIPfreeBlockMemoryArray(scip, &cliques[c], cliquesizes[c]);
2075 	   SCIPfreeBlockMemoryArrayNull(scip, &cliques, csize);
2076 	   SCIPfreeBlockMemoryArrayNull(scip, &cliquesizes, csize);
2077 	
2078 	   SCIPfreeBufferArrayNull(scip, &comsucc);
2079 	   SCIPfreeBufferArrayNull(scip, &lengthconss);
2080 	   SCIPfreeBufferArrayNull(scip, &indconss);
2081 	   SCIPfreeBufferArrayNull(scip, &newclique);
2082 	   SCIPfreeBufferArrayNull(scip, &consweights);
2083 	   SCIPfreeBufferArrayNull(scip, &consvars);
2084 	   SCIPdigraphFree(&vertexcliquegraph);
2085 	
2086 	   return SCIP_OKAY;
2087 	}
2088 	
2089 	
2090 	/** performs implication graph analysis
2091 	 *
2092 	 *  Tentatively fixes a variable to nonzeero and extracts consequences from it:
2093 	 *  - adds (possibly new) complementarity constraints to the problem if variables are implied to be zero
2094 	 *  - returns that the subproblem is infeasible if the domain of a variable turns out to be empty
2095 	 */
2096 	static
2097 	SCIP_RETCODE performImplicationGraphAnalysis(
2098 	   SCIP*                 scip,               /**< SCIP pointer */
2099 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
2100 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
2101 	   SCIP_VAR**            totalvars,          /**< problem and SOS1 variables */
2102 	   SCIP_DIGRAPH*         implgraph,          /**< implication graph (@p j is successor of @p i if and only if \f$ x_i\not = 0 \Rightarrow x_j\not = 0\f$) */
2103 	   SCIP_HASHMAP*         implhash,           /**< hash map from variable to node in implication graph */
2104 	   SCIP_Bool**           adjacencymatrix,    /**< adjacencymatrix of the conflict graph (only lower half filled) */
2105 	   int                   givennode,          /**< node of the conflict graph */
2106 	   int                   nonznode,           /**< node of the conflict graph that is implied to be nonzero if given node is nonzero */
2107 	   SCIP_Real*            impllbs,            /**< current lower variable bounds if given node is nonzero (update possible) */
2108 	   SCIP_Real*            implubs,            /**< current upper variable bounds if given node is nonzero (update possible) */
2109 	   SCIP_Bool*            implnodes,          /**< indicates which variables are currently implied to be nonzero if given node is nonzero (update possible) */
2110 	   int*                  naddconss,          /**< pointer to store number of added SOS1 constraints */
2111 	   int*                  probingdepth,       /**< pointer to store current probing depth */
2112 	   SCIP_Bool*            infeasible          /**< pointer to store whether the subproblem gets infeasible if variable to 'nonznode' is nonzero */
2113 	   )
2114 	{
2115 	   SCIP_SUCCDATA** succdatas;
2116 	   int succnode;
2117 	   int* succ;
2118 	   int nsucc;
2119 	   int s;
2120 	
2121 	   assert( nonznode >= 0 && nonznode < SCIPdigraphGetNNodes(conflictgraph) );
2122 	
2123 	   /* check probing depth */
2124 	   if ( conshdlrdata->depthimplanalysis >= 0 && *probingdepth >= conshdlrdata->depthimplanalysis )
2125 	      return SCIP_OKAY;
2126 	   ++(*probingdepth);
2127 	
2128 	   /* get successors of 'nonznode' in the conflict graph */
2129 	   nsucc = SCIPdigraphGetNSuccessors(conflictgraph, nonznode);
2130 	   succ = SCIPdigraphGetSuccessors(conflictgraph, nonznode);
2131 	
2132 	   /* loop through neighbors of 'nonznode' in the conflict graph; these variables are implied to be zero */
2133 	   for (s = 0; s < nsucc; ++s)
2134 	   {
2135 	      succnode = succ[s];
2136 	
2137 	      /* if the current variable domain of the successor node does not contain the value zero then return that the problem is infeasible
2138 	       * else if 'succnode' is not already complementary to 'givennode' then add a new complementarity constraint */
2139 	      if ( givennode == succnode || SCIPisFeasPositive(scip, impllbs[succnode]) || SCIPisFeasNegative(scip, implubs[succnode]) )
2140 	      {
2141 		*infeasible = TRUE;
2142 		return SCIP_OKAY;
2143 	      }
2144 	      else if ( ! isConnectedSOS1(adjacencymatrix, NULL, givennode, succnode) )
2145 	      {
2146 		char namesos[SCIP_MAXSTRLEN];
2147 		SCIP_CONS* soscons = NULL;
2148 		SCIP_VAR* var1;
2149 		SCIP_VAR* var2;
2150 	
2151 		/* update implied bounds of succnode */
2152 		impllbs[succnode] = 0;
2153 		implubs[succnode] = 0;
2154 	
2155 		/* add arcs to the conflict graph */
2156 		SCIP_CALL( SCIPdigraphAddArcSafe(conflictgraph, givennode, succnode, NULL) );
2157 		SCIP_CALL( SCIPdigraphAddArcSafe(conflictgraph, succnode, givennode, NULL) );
2158 	
2159 		/* resort successors */
2160 		SCIPsortInt(SCIPdigraphGetSuccessors(conflictgraph, givennode), SCIPdigraphGetNSuccessors(conflictgraph, givennode));
2161 		SCIPsortInt(SCIPdigraphGetSuccessors(conflictgraph, succnode), SCIPdigraphGetNSuccessors(conflictgraph, succnode));
2162 	
2163 		/* update adjacencymatrix */
2164 		if ( givennode > succnode )
2165 		  adjacencymatrix[givennode][succnode] = 1;
2166 		else
2167 		  adjacencymatrix[succnode][givennode] = 1;
2168 	
2169 		var1 = SCIPnodeGetVarSOS1(conflictgraph, givennode);
2170 		var2 = SCIPnodeGetVarSOS1(conflictgraph, succnode);
2171 	
2172 		/* create SOS1 constraint */
2173 		assert( SCIPgetDepth(scip) == 0 );
2174 		(void) SCIPsnprintf(namesos, SCIP_MAXSTRLEN, "presolved_sos1_%s_%s", SCIPvarGetName(var1), SCIPvarGetName(var2) );
2175 		SCIP_CALL( SCIPcreateConsSOS1(scip, &soscons, namesos, 0, NULL, NULL, TRUE, TRUE, TRUE, FALSE, TRUE,
2176 					      FALSE, FALSE, FALSE, FALSE) );
2177 	
2178 		/* add variables to SOS1 constraint */
2179 		SCIP_CALL( addVarSOS1(scip, soscons, conshdlrdata, var1, 1.0) );
2180 		SCIP_CALL( addVarSOS1(scip, soscons, conshdlrdata, var2, 2.0) );
2181 	
2182 		/* add constraint */
2183 		SCIP_CALL( SCIPaddCons(scip, soscons) );
2184 	
2185 		/* release constraint */
2186 		SCIP_CALL( SCIPreleaseCons(scip, &soscons) );
2187 	
2188 		++(*naddconss);
2189 	      }
2190 	   }
2191 	
2192 	   /* by construction: nodes of SOS1 variables are equal for conflict graph and implication graph */
2193 	   assert( nonznode == SCIPhashmapGetImageInt(implhash, SCIPnodeGetVarSOS1(conflictgraph, nonznode)) );
2194 	   succdatas = (SCIP_SUCCDATA**) SCIPdigraphGetSuccessorsData(implgraph, nonznode);
2195 	   nsucc = SCIPdigraphGetNSuccessors(implgraph, nonznode);
2196 	   succ = SCIPdigraphGetSuccessors(implgraph, nonznode);
2197 	
2198 	   /* go further in implication graph */
2199 	   for (s = 0; s < nsucc; ++s)
2200 	   {
2201 	     SCIP_SUCCDATA* data;
2202 	     int oldprobingdepth;
2203 	
2204 	     succnode = succ[s];
2205 	     data = succdatas[s];
2206 	     oldprobingdepth = *probingdepth;
2207 	
2208 	     /* if current lower bound is smaller than implied lower bound */
2209 	     if ( SCIPisFeasLT(scip, impllbs[succnode], data->lbimpl) )
2210 	     {
2211 		impllbs[succnode] = data->lbimpl;
2212 	
2213 		/* if node is SOS1 and implied to be nonzero for the first time, then this recursively may imply further bound changes */
2214 		if ( varGetNodeSOS1(conshdlrdata, totalvars[succnode]) >= 0 && ! implnodes[succnode] && SCIPisFeasPositive(scip, data->lbimpl) )
2215 		{
2216 		   /* by construction: nodes of SOS1 variables are equal for conflict graph and implication graph */
2217 		   assert( succnode == SCIPhashmapGetImageInt(implhash, SCIPnodeGetVarSOS1(conflictgraph, succnode)) );
2218 		   implnodes[succnode] = TRUE; /* in order to avoid cycling */
2219 		   SCIP_CALL( performImplicationGraphAnalysis(scip, conshdlrdata, conflictgraph, totalvars, implgraph, implhash, adjacencymatrix, givennode, succnode, impllbs, implubs, implnodes, naddconss, probingdepth, infeasible) );
2220 		   *probingdepth = oldprobingdepth;
2221 	
2222 		   /* return if the subproblem is known to be infeasible */
2223 		   if ( *infeasible )
2224 		      return SCIP_OKAY;
2225 		}
2226 	     }
2227 	
2228 	     /* if current upper bound is larger than implied upper bound */
2229 	     if ( SCIPisFeasGT(scip, implubs[succnode], data->ubimpl) )
2230 	     {
2231 		implubs[succnode] = data->ubimpl;
2232 	
2233 		/* if node is SOS1 and implied to be nonzero for the first time, then this recursively may imply further bound changes */
2234 		if ( varGetNodeSOS1(conshdlrdata, totalvars[succnode]) >= 0 && ! implnodes[succnode] && SCIPisFeasNegative(scip, data->ubimpl) )
2235 		{
2236 		   /* by construction: nodes of SOS1 variables are equal for conflict graph and implication graph */
2237 		   assert( succnode == SCIPhashmapGetImageInt(implhash, SCIPnodeGetVarSOS1(conflictgraph, succnode)) );
2238 		   implnodes[succnode] = TRUE; /* in order to avoid cycling */
2239 		   SCIP_CALL( performImplicationGraphAnalysis(scip, conshdlrdata, conflictgraph, totalvars, implgraph, implhash, adjacencymatrix, givennode, succnode, impllbs, implubs, implnodes, naddconss, probingdepth, infeasible) );
2240 		   *probingdepth = oldprobingdepth;
2241 	
2242 		   /* return if the subproblem is known to be infeasible */
2243 		   if ( *infeasible )
2244 		      return SCIP_OKAY;
2245 		}
2246 	     }
2247 	   }
2248 	
2249 	   return SCIP_OKAY;
2250 	}
2251 	
2252 	
2253 	/** returns whether node is implied to be zero; this information is taken from the input array 'implnodes' */
2254 	static
2255 	SCIP_Bool isImpliedZero(
2256 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
2257 	   SCIP_Bool*            implnodes,          /**< implnodes[i] = TRUE if the SOS1 variable corresponding to node i in the implication graph is implied to be nonzero */
2258 	   int                   node                /**< node of the conflict graph (or -1) */
2259 	   )
2260 	{
2261 	   int* succ;
2262 	   int nsucc;
2263 	   int s;
2264 	
2265 	   if ( node < 0 )
2266 	      return FALSE;
2267 	
2268 	   nsucc = SCIPdigraphGetNSuccessors(conflictgraph, node);
2269 	   succ = SCIPdigraphGetSuccessors(conflictgraph, node);
2270 	
2271 	   /* check whether any successor is implied to be nonzero */
2272 	   for (s = 0; s < nsucc; ++s)
2273 	   {
2274 	      if ( implnodes[succ[s]] )
2275 	         return TRUE;
2276 	   }
2277 	
2278 	   return FALSE;
2279 	}
2280 	
2281 	
2282 	/** updates arc data of implication graph */
2283 	static
2284 	SCIP_RETCODE updateArcData(
2285 	   SCIP*                 scip,               /**< SCIP pointer */
2286 	   SCIP_DIGRAPH*         implgraph,          /**< implication graph */
2287 	   SCIP_HASHMAP*         implhash,           /**< hash map from variable to node in implication graph */
2288 	   SCIP_VAR**            totalvars,          /**< problem and SOS1 variables */
2289 	   SCIP_VAR*             varv,               /**< variable that is assumed to be nonzero */
2290 	   SCIP_VAR*             varw,               /**< implication variable */
2291 	   SCIP_Real             lb,                 /**< old lower bound of \f$x_w\f$ */
2292 	   SCIP_Real             ub,                 /**< old upper bound of \f$x_w\f$ */
2293 	   SCIP_Real             newbound,           /**< new bound of \f$x_w\f$ */
2294 	   SCIP_Bool             lower,              /**< whether to consider lower bound implication (otherwise upper bound) */
2295 	   int*                  nchgbds,            /**< pointer to store number of changed bounds */
2296 	   SCIP_Bool*            update,             /**< pointer to store whether implication graph has been updated */
2297 	   SCIP_Bool*            infeasible          /**< pointer to store whether an infeasibility has been detected */
2298 	   )
2299 	{
2300 	   SCIP_SUCCDATA** succdatas;
2301 	   SCIP_SUCCDATA* data = NULL;
2302 	   int nsucc;
2303 	   int* succ;
2304 	   int indv;
2305 	   int indw;
2306 	   int s;
2307 	
2308 	   assert( scip != NULL );
2309 	   assert( implgraph != NULL );
2310 	   assert( implhash != NULL );
2311 	   assert( totalvars != NULL );
2312 	   assert( varv != NULL );
2313 	   assert( varw != NULL );
2314 	
2315 	   /* if x_v != 0 turns out to be infeasible then fix x_v = 0 */
2316 	   if ( ( lower && SCIPisFeasLT(scip, ub, newbound) ) || ( ! lower && SCIPisFeasGT(scip, lb, newbound) ) )
2317 	   {
2318 	      SCIP_Bool infeasible1;
2319 	      SCIP_Bool infeasible2;
2320 	      SCIP_Bool tightened1;
2321 	      SCIP_Bool tightened2;
2322 	
2323 	      SCIP_CALL( SCIPtightenVarLb(scip, varv, 0.0, FALSE, &infeasible1, &tightened1) );
2324 	      SCIP_CALL( SCIPtightenVarUb(scip, varv, 0.0, FALSE, &infeasible2, &tightened2) );
2325 	
2326 	      if ( infeasible1 || infeasible2 )
2327 	      {
2328 	         SCIPdebugMsg(scip, "detected infeasibility while trying to fix variable <%s> to zero\n", SCIPvarGetName(varv));
2329 	         *infeasible = TRUE;
2330 	      }
2331 	
2332 	      if ( tightened1 || tightened2 )
2333 	      {
2334 	         SCIPdebugMsg(scip, "fixed variable %s from lb = %f and ub = %f to 0.0 \n", SCIPvarGetName(varv), lb, ub);
2335 	         ++(*nchgbds);
2336 	      }
2337 	   }
2338 	
2339 	   /* get successor information */
2340 	   indv = SCIPhashmapGetImageInt(implhash, varv); /* get index of x_v in implication graph */
2341 	   assert( SCIPhashmapGetImageInt(implhash, totalvars[indv]) == indv );
2342 	   succdatas = (SCIP_SUCCDATA**) SCIPdigraphGetSuccessorsData(implgraph, indv);
2343 	   nsucc = SCIPdigraphGetNSuccessors(implgraph, indv);
2344 	   succ = SCIPdigraphGetSuccessors(implgraph, indv);
2345 	
2346 	   /* search for nodew in existing successors. If this is the case then check whether the lower implication bound may be updated ... */
2347 	   indw = SCIPhashmapGetImageInt(implhash, varw);
2348 	   assert( SCIPhashmapGetImageInt(implhash, totalvars[indw]) == indw );
2349 	   for (s = 0; s < nsucc; ++s)
2350 	   {
2351 	      if ( succ[s] == indw )
2352 	      {
2353 	         data = succdatas[s];
2354 	         assert( data != NULL );
2355 	         if ( lower && SCIPisFeasLT(scip, data->lbimpl, newbound) )
2356 	         {
2357 	            if ( SCIPvarIsIntegral(varw) )
2358 	               data->lbimpl = SCIPceil(scip, newbound);
2359 	            else
2360 	               data->lbimpl = newbound;
2361 	
2362 	            *update = TRUE;
2363 	            SCIPdebugMsg(scip, "updated to implication %s != 0 -> %s >= %f\n", SCIPvarGetName(varv), SCIPvarGetName(varw), newbound);
2364 	         }
2365 	         else if ( ! lower && SCIPisFeasGT(scip, data->ubimpl, newbound) )
2366 	         {
2367 	            if ( SCIPvarIsIntegral(varw) )
2368 	               data->ubimpl = SCIPfloor(scip, newbound);
2369 	            else
2370 	               data->ubimpl = newbound;
2371 	
2372 	            *update = TRUE;
2373 	            SCIPdebugMsg(scip, "updated to implication %s != 0 -> %s >= %f\n", SCIPvarGetName(varv), SCIPvarGetName(varw), newbound);
2374 	         }
2375 	         break;
2376 	      }
2377 	   }
2378 	
2379 	   /* ..., otherwise if there does not exist an arc between indv and indw already, then create one and add implication */
2380 	   if ( s == nsucc )
2381 	   {
2382 	      assert( data == NULL );
2383 	      SCIP_CALL( SCIPallocBlockMemory(scip, &data) );
2384 	      if ( lower )
2385 	      {
2386 	         data->lbimpl = newbound;
2387 	         data->ubimpl = ub;
2388 	         SCIPdebugMsg(scip, "add implication %s != 0 -> %s >= %f\n", SCIPvarGetName(varv), SCIPvarGetName(varw), newbound);
2389 	      }
2390 	      else
2391 	      {
2392 	         data->lbimpl = lb;
2393 	         data->ubimpl = newbound;
2394 	         SCIPdebugMsg(scip, "add implication %s != 0 -> %s <= %f\n", SCIPvarGetName(varv), SCIPvarGetName(varw), newbound);
2395 	      }
2396 	      SCIP_CALL( SCIPdigraphAddArc(implgraph, indv, indw, (void*)data) );
2397 	      *update = TRUE;
2398 	   }
2399 	
2400 	   return SCIP_OKAY;
2401 	}
2402 	
2403 	
2404 	/** updates implication graph
2405 	 *
2406 	 *  Assume the variable from the input is nonzero. If this implies that some other variable is also nonzero, then
2407 	 *  store this information in an implication graph
2408 	 */
2409 	static
2410 	SCIP_RETCODE updateImplicationGraphSOS1(
2411 	   SCIP*                 scip,               /**< SCIP pointer */
2412 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
2413 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
2414 	   SCIP_Bool**           adjacencymatrix,    /**< adjacency matrix of conflict graph (lower half) */
2415 	   SCIP_DIGRAPH*         implgraph,          /**< implication graph (@p j is successor of @p i if and only if \f$ x_i\not = 0 \Rightarrow x_j\not = 0\f$) */
2416 	   SCIP_HASHMAP*         implhash,           /**< hash map from variable to node in implication graph */
2417 	   SCIP_Bool*            implnodes,          /**< implnodes[i] = TRUE if the SOS1 variable corresponding to node i in the implication graph is implied to be nonzero */
2418 	   SCIP_VAR**            totalvars,          /**< problem and SOS1 variables */
2419 	   int**                 cliquecovers,       /**< clique covers of linear constraint */
2420 	   int*                  cliquecoversizes,   /**< size of clique covers */
2421 	   int*                  varincover,         /**< array with varincover[i] = cover of SOS1 index @p i */
2422 	   SCIP_VAR**            vars,               /**< variables to be checked */
2423 	   SCIP_Real*            coefs,              /**< coefficients of variables in linear constraint */
2424 	   int                   nvars,              /**< number of variables to be checked */
2425 	   SCIP_Real*            bounds,             /**< bounds of variables */
2426 	   SCIP_VAR*             var,                /**< variable that is assumed to be nonzero */
2427 	   SCIP_Real             bound,              /**< bound of variable */
2428 	   SCIP_Real             boundnonzero,       /**< bound of variable if it is known to be nonzero if infinity values are not summarized */
2429 	   int                   ninftynonzero,      /**< number of times infinity/-infinity has to be summarized to boundnonzero */
2430 	   SCIP_Bool             lower,              /**< TRUE if lower bounds are consideres; FALSE for upper bounds */
2431 	   int*                  nchgbds,            /**< pointer to store number of changed bounds */
2432 	   SCIP_Bool*            update,             /**< pointer to store whether implication graph has been updated */
2433 	   SCIP_Bool*            infeasible          /**< pointer to store whether an infeasibility has been detected */
2434 	   )
2435 	{
2436 	   int nodev;
2437 	   int w;
2438 	
2439 	   assert( update != NULL );
2440 	
2441 	   /* update implication graph if possible */
2442 	   *update = FALSE;
2443 	   *infeasible = FALSE;
2444 	   nodev = varGetNodeSOS1(conshdlrdata, var); /* possibly -1 if var is not involved in an SOS1 constraint */
2445 	
2446 	   /* if nodev is an index of an SOS1 variable and at least one lower bound of a variable that is not x_v is infinity */
2447 	   if ( nodev < 0 || SCIPisInfinity(scip, REALABS(bound)) || ninftynonzero > 1 )
2448 	      return SCIP_OKAY;
2449 	
2450 	   /* for every variable x_w: compute upper bound of a_w * x_w if x_v is known to be nonzero */
2451 	   for (w = 0; w < nvars; ++w)
2452 	   {
2453 	      int newninftynonzero;
2454 	      SCIP_Bool implinfty = FALSE;
2455 	      int nodew;
2456 	
2457 	      /* get node of x_w in conflict graph: nodew = -1 if it is no SOS1 variable */
2458 	      nodew = varGetNodeSOS1(conshdlrdata, vars[w]);
2459 	
2460 	      newninftynonzero = ninftynonzero;
2461 	
2462 	      /* variable should not be fixed to be already zero (note x_v is fixed to be nonzero by assumption) */
2463 	      if ( nodew < 0 || ( nodev != nodew && ! isConnectedSOS1(adjacencymatrix, NULL, nodev, nodew) && ! isImpliedZero(conflictgraph, implnodes, nodew) ) )
2464 	      {
2465 	         SCIP_Real implbound;
2466 	         SCIP_Bool implcoverw;
2467 	         int nodecliq;
2468 	         int indcliq;
2469 	         int ind;
2470 	         int j;
2471 	
2472 	         /* boundnonzero is the bound of x_v if x_v is nonzero we use this information to get a bound of x_w if x_v is
2473 	          * nonzero; therefore, we have to perform some recomputations */
2474 	         implbound = boundnonzero - bound;
2475 	         ind = varincover[w];
2476 	         assert( cliquecoversizes[ind] > 0 );
2477 	
2478 	         implcoverw = FALSE;
2479 	         for (j = 0; j < cliquecoversizes[ind]; ++j)
2480 	         {
2481 	            indcliq = cliquecovers[ind][j];
2482 	            assert( 0 <= indcliq && indcliq < nvars );
2483 	
2484 	            nodecliq = varGetNodeSOS1(conshdlrdata, vars[indcliq]); /* possibly -1 if variable is not involved in an SOS1 constraint */
2485 	
2486 	            /* if nodecliq is not a member of an SOS1 constraint or the variable corresponding to nodecliq is not implied to be zero if x_v != 0  */
2487 	            if ( nodecliq < 0 || (! isConnectedSOS1(adjacencymatrix, NULL, nodev, nodecliq) && ! isImpliedZero(conflictgraph, implnodes, nodecliq) ) )
2488 	            {
2489 	               if ( indcliq == w )
2490 	               {
2491 	                  if ( !SCIPisInfinity(scip, REALABS(bounds[w])) && !SCIPisInfinity(scip, REALABS(implbound + bounds[w])) )
2492 	                     implbound += bounds[w];
2493 	                  else
2494 	                     --newninftynonzero;
2495 	                  implcoverw = TRUE;
2496 	               }
2497 	               else if ( implcoverw )
2498 	               {
2499 	                  if ( SCIPisInfinity(scip, REALABS(bounds[indcliq])) || SCIPisInfinity(scip, REALABS(implbound - bounds[indcliq])) )
2500 	                     implinfty = TRUE;
2501 	                  else
2502 	                     implbound -= bounds[indcliq];
2503 	                  break;
2504 	               }
2505 	               else
2506 	               {
2507 	                  if ( SCIPisInfinity(scip, REALABS(bounds[indcliq])) )
2508 	                     implinfty = TRUE;
2509 	                  break;
2510 	               }
2511 	            }
2512 	         }
2513 	
2514 	         /* check whether x_v != 0 implies a bound change of x_w */
2515 	         if ( ! implinfty && newninftynonzero == 0 )
2516 	         {
2517 	            SCIP_Real newbound;
2518 	            SCIP_Real coef;
2519 	            SCIP_Real lb;
2520 	            SCIP_Real ub;
2521 	
2522 	            lb = SCIPvarGetLbLocal(vars[w]);
2523 	            ub = SCIPvarGetUbLocal(vars[w]);
2524 	            coef = coefs[w];
2525 	
2526 	            if ( SCIPisFeasZero(scip, coef) )
2527 	               continue;
2528 	
2529 	            newbound = implbound / coef;
2530 	
2531 	            if ( SCIPisInfinity(scip, newbound) )
2532 	               continue;
2533 	
2534 	            /* check if an implication can be added/updated or assumption x_v != 0 is infeasible */
2535 	            if ( lower )
2536 	            {
2537 	               if ( SCIPisFeasPositive(scip, coef) && SCIPisFeasLT(scip, lb, newbound) )
2538 	               {
2539 	                  SCIP_CALL( updateArcData(scip, implgraph, implhash, totalvars, var, vars[w], lb, ub, newbound, TRUE, nchgbds, update, infeasible) );
2540 	               }
2541 	               else if ( SCIPisFeasNegative(scip, coef) && SCIPisFeasGT(scip, ub, newbound) )
2542 	               {
2543 	                  SCIP_CALL( updateArcData(scip, implgraph, implhash, totalvars, var, vars[w], lb, ub, newbound, FALSE, nchgbds, update, infeasible) );
2544 	               }
2545 	            }
2546 	            else
2547 	            {
2548 	               if ( SCIPisFeasPositive(scip, coef) && SCIPisFeasGT(scip, ub, newbound) )
2549 	               {
2550 	                  SCIP_CALL( updateArcData(scip, implgraph, implhash, totalvars, var, vars[w], lb, ub, newbound, FALSE, nchgbds, update, infeasible) );
2551 	               }
2552 	               else if ( SCIPisFeasNegative(scip, coef) && SCIPisFeasLT(scip, lb, newbound) )
2553 	               {
2554 	                  SCIP_CALL( updateArcData(scip, implgraph, implhash, totalvars, var, vars[w], lb, ub, newbound, TRUE, nchgbds, update, infeasible) );
2555 	               }
2556 	            }
2557 	         }
2558 	      }
2559 	   }
2560 	
2561 	   return SCIP_OKAY;
2562 	}
2563 	
2564 	
2565 	/** search new disjoint clique that covers given node
2566 	 *
2567 	 *  For a given vertex @p v search for a clique of the conflict graph induced by the variables of a linear constraint that
2568 	 *  - covers @p v and
2569 	 *  - has an an empty intersection with already computed clique cover.
2570 	 */
2571 	static
2572 	SCIP_RETCODE computeVarsCoverSOS1(
2573 	   SCIP*                 scip,               /**< SCIP pointer */
2574 	   SCIP_DIGRAPH*         conflictgraphroot,  /**< conflict graph of the root node (nodes: 1, ..., @p nsos1vars) */
2575 	   SCIP_DIGRAPH*         conflictgraphlin,   /**< conflict graph of linear constraint (nodes: 1, ..., @p nlinvars) */
2576 	   SCIP_VAR**            linvars,            /**< variables in linear constraint */
2577 	   SCIP_Bool*            coveredvars,        /**< states which variables of the linear constraint are currently covered by a clique */
2578 	   int*                  clique,             /**< array to store new clique in cover */
2579 	   int*                  cliquesize,         /**< pointer to store the size of @p clique */
2580 	   int                   v,                  /**< position of variable in linear constraint that should be covered */
2581 	   SCIP_Bool             considersolvals     /**< TRUE if largest auxiliary bigM values of variables should be prefered */
2582 	   )
2583 	{
2584 	   int nsucc;
2585 	   int s;
2586 	
2587 	   assert( conflictgraphlin != NULL );
2588 	   assert( linvars != NULL );
2589 	   assert( coveredvars != NULL );
2590 	   assert( clique != NULL );
2591 	   assert( cliquesize != NULL );
2592 	
2593 	   assert( ! coveredvars[v] );  /* we should produce a new clique */
2594 	
2595 	   /* add index 'v' to the clique cover */
2596 	   clique[0] = v;
2597 	   *cliquesize = 1;
2598 	
2599 	   nsucc = SCIPdigraphGetNSuccessors(conflictgraphlin, v);
2600 	   if ( nsucc > 0 )
2601 	   {
2602 	      int* extensions;
2603 	      int nextensions = 0;
2604 	      int nextensionsnew;
2605 	      int succnode;
2606 	      int* succ;
2607 	
2608 	      /* allocate buffer array */
2609 	      SCIP_CALL( SCIPallocBufferArray(scip, &extensions, nsucc) );
2610 	
2611 	      succ = SCIPdigraphGetSuccessors(conflictgraphlin, v);
2612 	
2613 	      /* compute possible extensions for the clique cover */
2614 	      for (s = 0; s < nsucc; ++s)
2615 	      {
2616 	         succnode = succ[s];
2617 	         if ( ! coveredvars[succnode] )
2618 	            extensions[nextensions++] = succ[s];
2619 	      }
2620 	
2621 	      /* while there exist possible extensions for the clique cover */
2622 	      while ( nextensions > 0 )
2623 	      {
2624 	         int bestindex = -1;
2625 	
2626 	         if ( considersolvals )
2627 	         {
2628 	            SCIP_Real bestbigMval;
2629 	            SCIP_Real bigMval;
2630 	
2631 	            bestbigMval = -SCIPinfinity(scip);
2632 	
2633 	            /* search for the extension with the largest absolute value of its LP relaxation solution value */
2634 	            for (s = 0; s < nextensions; ++s)
2635 	            {
2636 	               bigMval = nodeGetSolvalBinaryBigMSOS1(scip, conflictgraphroot, NULL, extensions[s]);
2637 	               if ( SCIPisFeasLT(scip, bestbigMval, bigMval) )
2638 	               {
2639 	                  bestbigMval = bigMval;
2640 	                  bestindex = extensions[s];
2641 	               }
2642 	            }
2643 	         }
2644 	         else
2645 	            bestindex = extensions[0];
2646 	
2647 	         assert( bestindex != -1 );
2648 	
2649 	         /* add bestindex to the clique cover */
2650 	         clique[(*cliquesize)++] = bestindex;
2651 	
2652 	         /* compute new 'extensions' array */
2653 	         nextensionsnew = 0;
2654 	         for (s = 0; s < nextensions; ++s)
2655 	         {
2656 	            if ( s != bestindex && isConnectedSOS1(NULL, conflictgraphlin, bestindex, extensions[s]) )
2657 	               extensions[nextensionsnew++] = extensions[s];
2658 	         }
2659 	         nextensions = nextensionsnew;
2660 	      }
2661 	
2662 	      /* free buffer array */
2663 	      SCIPfreeBufferArray(scip, &extensions);
2664 	   }
2665 	
2666 	   /* mark covered indices */
2667 	   for (s = 0; s < *cliquesize; ++s)
2668 	   {
2669 	      int ind;
2670 	
2671 	      ind = clique[s];
2672 	      assert( 0 <= ind );
2673 	      assert( ! coveredvars[ind] );
2674 	      coveredvars[ind] = TRUE;
2675 	   }
2676 	
2677 	   return SCIP_OKAY;
2678 	}
2679 	
2680 	
2681 	/** try to tighten upper and lower bounds for variables */
2682 	static
2683 	SCIP_RETCODE tightenVarsBoundsSOS1(
2684 	   SCIP*                 scip,               /**< SCIP pointer */
2685 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
2686 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
2687 	   SCIP_DIGRAPH*         implgraph,          /**< implication graph (@p j is successor of @p i if and only if \f$ x_i\not = 0 \f$ implies a new lower/upper bound for \f$ x_j\f$) */
2688 	   SCIP_HASHMAP*         implhash,           /**< hash map from variable to node in implication graph */
2689 	   SCIP_Bool**           adjacencymatrix,    /**< adjacencymatrix of conflict graph */
2690 	   SCIP_VAR**            totalvars,          /**< problem and SOS1 vars */
2691 	   int                   ntotalvars,         /**< number of problem and SOS1 variables*/
2692 	   int                   nsos1vars,          /**< number of SOS1 variables */
2693 	   int*                  nchgbds,            /**< pointer to store number of changed bounds */
2694 	   SCIP_Bool*            implupdate,         /**< pointer to store whether the implication graph has been updated in this function call */
2695 	   SCIP_Bool*            cutoff              /**< pointer to store if current nodes LP is infeasible  */
2696 	   )
2697 	{
2698 	   SCIP_CONSHDLR* conshdlrlinear;
2699 	   SCIP_CONS** linearconss;
2700 	   int nlinearconss;
2701 	
2702 	   SCIP_Bool* implnodes = NULL;     /* implnodes[i] = TRUE if the SOS1 variable corresponding to node i in the implication graph is implied to be nonzero */
2703 	   SCIP_Bool* coveredvars = NULL;   /* coveredvars[i] = TRUE if variable with index i is covered by the clique cover */
2704 	   int* varindincons = NULL;        /* varindincons[i] = position of SOS1 index i in linear constraint (-1 if x_i is not involved in linear constraint) */
2705 	
2706 	   SCIP_VAR** trafolinvars = NULL;  /* variables of transformed linear constraints without (multi)aggregated variables */
2707 	   int ntrafolinvars = 0;
2708 	   SCIP_Real* trafolinvals = NULL;
2709 	   SCIP_Real* trafoubs = NULL;
2710 	   SCIP_Real* trafolbs = NULL;
2711 	   SCIP_Real traforhs;
2712 	   SCIP_Real trafolhs;
2713 	
2714 	   SCIP_VAR** sos1linvars = NULL;  /* variables that are not contained in linear constraint, but are in conflict with a variable from the linear constraint */
2715 	   int nsos1linvars;
2716 	   int c;
2717 	
2718 	   assert( scip != NULL );
2719 	   assert( conflictgraph != NULL );
2720 	   assert( adjacencymatrix != NULL );
2721 	   assert( nchgbds != NULL );
2722 	   assert( cutoff != NULL );
2723 	
2724 	   *cutoff = FALSE;
2725 	   *implupdate = FALSE;
2726 	
2727 	   /* get constraint handler data of linear constraints */
2728 	   conshdlrlinear = SCIPfindConshdlr(scip, "linear");
2729 	   if ( conshdlrlinear == NULL )
2730 	      return SCIP_OKAY;
2731 	
2732 	   /* get linear constraints and number of linear constraints */
2733 	   nlinearconss = SCIPconshdlrGetNConss(conshdlrlinear);
2734 	   linearconss = SCIPconshdlrGetConss(conshdlrlinear);
2735 	
2736 	   /* allocate buffer arrays */
2737 	   SCIP_CALL( SCIPallocBufferArray(scip, &sos1linvars, nsos1vars) );
2738 	   SCIP_CALL( SCIPallocBufferArray(scip, &implnodes, nsos1vars) );
2739 	   SCIP_CALL( SCIPallocBufferArray(scip, &varindincons, nsos1vars) );
2740 	   SCIP_CALL( SCIPallocBufferArray(scip, &coveredvars, ntotalvars) );
2741 	   SCIP_CALL( SCIPallocBufferArray(scip, &trafoubs, ntotalvars) );
2742 	   SCIP_CALL( SCIPallocBufferArray(scip, &trafolbs, ntotalvars) );
2743 	
2744 	   /* for every linear constraint and every SOS1 variable */
2745 	   for (c = 0; c < nlinearconss + nsos1vars && ! (*cutoff); ++c)
2746 	   {
2747 	      SCIP_DIGRAPH* conflictgraphlin;
2748 	      int** cliquecovers = NULL;           /* clique covers of indices of variables in linear constraint */
2749 	      int* cliquecoversizes = NULL;        /* size of each cover */
2750 	      SCIP_VAR* sosvar = NULL;
2751 	      SCIP_Real* cliquecovervals = NULL;
2752 	      SCIP_Real constant;
2753 	      int* varincover = NULL;              /* varincover[i] = cover of SOS1 index i */
2754 	      int ncliquecovers;
2755 	      int requiredsize;
2756 	
2757 	      int v;
2758 	      int i;
2759 	      int j;
2760 	
2761 	      /* get transformed linear constraints (without aggregated variables) */
2762 	      if ( c < nlinearconss )
2763 	      {
2764 	         SCIP_VAR** origlinvars;
2765 	         SCIP_Real* origlinvals;
2766 	
2767 	         /* get data of linear constraint */
2768 	         ntrafolinvars = SCIPgetNVarsLinear(scip, linearconss[c]);
2769 	         if ( ntrafolinvars < 1 )
2770 	            continue;
2771 	
2772 	         origlinvars = SCIPgetVarsLinear(scip, linearconss[c]);
2773 	         origlinvals = SCIPgetValsLinear(scip, linearconss[c]);
2774 	         assert( origlinvars != NULL );
2775 	         assert( origlinvals != NULL );
2776 	
2777 	         /* copy variables and coefficients of linear constraint */
2778 	         SCIP_CALL( SCIPduplicateBufferArray(scip, &trafolinvars, origlinvars, ntrafolinvars) );
2779 	         SCIP_CALL( SCIPduplicateBufferArray(scip, &trafolinvals, origlinvals, ntrafolinvars) );
2780 	
2781 	         trafolhs = SCIPgetLhsLinear(scip, linearconss[c]);
2782 	         traforhs = SCIPgetRhsLinear(scip, linearconss[c]);
2783 	      }
2784 	      else
2785 	      {
2786 	         sosvar = SCIPnodeGetVarSOS1(conflictgraph, c - nlinearconss);
2787 	
2788 	         if ( SCIPvarGetStatus(sosvar) != SCIP_VARSTATUS_AGGREGATED
2789 	            && SCIPvarGetStatus(sosvar) != SCIP_VARSTATUS_MULTAGGR
2790 	            && SCIPvarGetStatus(sosvar) != SCIP_VARSTATUS_NEGATED )
2791 	            continue;
2792 	
2793 	         /* store variable so it will be transformed to active variables below */
2794 	         ntrafolinvars = 1;
2795 	         SCIP_CALL( SCIPallocBufferArray(scip, &trafolinvars, ntrafolinvars + 1) );
2796 	         SCIP_CALL( SCIPallocBufferArray(scip, &trafolinvals, ntrafolinvars + 1) );
2797 	
2798 	         trafolinvars[0] = sosvar;
2799 	         trafolinvals[0] = 1.0;
2800 	
2801 	         trafolhs = 0.0;
2802 	         traforhs = 0.0;
2803 	      }
2804 	      assert( ntrafolinvars >= 1 );
2805 	
2806 	      /* transform linear constraint */
2807 	      constant = 0.0;
2808 	      SCIP_CALL( SCIPgetProbvarLinearSum(scip, trafolinvars, trafolinvals, &ntrafolinvars, ntrafolinvars, &constant, &requiredsize, TRUE) );
2809 	      if( requiredsize > ntrafolinvars )
2810 	      {
2811 	         SCIP_CALL( SCIPreallocBufferArray(scip, &trafolinvars, requiredsize + 1) );
2812 	         SCIP_CALL( SCIPreallocBufferArray(scip, &trafolinvals, requiredsize + 1) );
2813 	
2814 	         SCIP_CALL( SCIPgetProbvarLinearSum(scip, trafolinvars, trafolinvals, &ntrafolinvars, requiredsize, &constant, &requiredsize, TRUE) );
2815 	         assert( requiredsize <= ntrafolinvars );
2816 	      }
2817 	      if( !SCIPisInfinity(scip, -trafolhs) )
2818 	         trafolhs -= constant;
2819 	      if( !SCIPisInfinity(scip,  traforhs) )
2820 	         traforhs -= constant;
2821 	
2822 	      if ( ntrafolinvars == 0 )
2823 	      {
2824 	         SCIPfreeBufferArray(scip, &trafolinvals);
2825 	         SCIPfreeBufferArray(scip, &trafolinvars);
2826 	         continue;
2827 	      }
2828 	
2829 	      /* possibly add sos1 variable to create aggregation/multiaggregation/negation equality */
2830 	      if ( sosvar != NULL )
2831 	      {
2832 	         trafolinvals[ntrafolinvars] = -1.0;
2833 	         trafolinvars[ntrafolinvars] = sosvar;
2834 	         ++ntrafolinvars;
2835 	      }
2836 	
2837 	      /* compute lower and upper bounds of each term a_i * x_i of transformed constraint */
2838 	      for (v = 0; v < ntrafolinvars; ++v)
2839 	      {
2840 	         SCIP_Real lb;
2841 	         SCIP_Real ub;
2842 	
2843 	         lb = SCIPvarGetLbLocal(trafolinvars[v]);
2844 	         ub = SCIPvarGetUbLocal(trafolinvars[v]);
2845 	
2846 	         if ( trafolinvals[v] < 0.0 )
2847 	            SCIPswapReals(&lb, &ub);
2848 	
2849 	         assert( ! SCIPisInfinity(scip, REALABS(trafolinvals[v])) );
2850 	
2851 	         if ( SCIPisInfinity(scip, REALABS(lb)) || SCIPisInfinity(scip, REALABS(lb * trafolinvals[v])) )
2852 	            trafolbs[v] = -SCIPinfinity(scip);
2853 	         else
2854 	            trafolbs[v] = lb * trafolinvals[v];
2855 	
2856 	         if ( SCIPisInfinity(scip, REALABS(ub)) || SCIPisInfinity(scip, REALABS(ub * trafolinvals[v])) )
2857 	            trafoubs[v] = SCIPinfinity(scip);
2858 	         else
2859 	            trafoubs[v] = ub * trafolinvals[v];
2860 	      }
2861 	
2862 	      /* initialization: mark all the SOS1 variables as 'not a member of the linear constraint' */
2863 	      for (v = 0; v < nsos1vars; ++v)
2864 	         varindincons[v] = -1;
2865 	
2866 	      /* save position of SOS1 variables in linear constraint */
2867 	      for (v = 0; v < ntrafolinvars; ++v)
2868 	      {
2869 	         int node;
2870 	
2871 	         node = varGetNodeSOS1(conshdlrdata, trafolinvars[v]);
2872 	
2873 	         if ( node >= 0 )
2874 	            varindincons[node] = v;
2875 	      }
2876 	
2877 	      /* create conflict graph of linear constraint */
2878 	      SCIP_CALL( SCIPcreateDigraph(scip, &conflictgraphlin, ntrafolinvars) );
2879 	      SCIP_CALL( genConflictgraphLinearCons(conshdlrdata, conflictgraphlin, conflictgraph, trafolinvars, ntrafolinvars, varindincons) );
2880 	
2881 	      /* mark all the variables as 'not covered by some clique cover' */
2882 	      for (i = 0; i < ntrafolinvars; ++i)
2883 	         coveredvars[i] = FALSE;
2884 	
2885 	      /* allocate buffer array */
2886 	      SCIP_CALL( SCIPallocBufferArray(scip, &cliquecovervals, ntrafolinvars) );
2887 	      SCIP_CALL( SCIPallocBufferArray(scip, &cliquecoversizes, ntrafolinvars) );
2888 	      SCIP_CALL( SCIPallocBufferArray(scip, &cliquecovers, ntrafolinvars) );
2889 	
2890 	      /* compute distinct cliques that cover all the variables of the linear constraint */
2891 	      ncliquecovers = 0;
2892 	      for (v = 0; v < ntrafolinvars; ++v)
2893 	      {
2894 	         /* if variable is not already covered by an already known clique cover */
2895 	         if ( ! coveredvars[v] )
2896 	         {
2897 	            SCIP_CALL( SCIPallocBufferArray(scip, &(cliquecovers[ncliquecovers]), ntrafolinvars) ); /*lint !e866*/
2898 	            SCIP_CALL( computeVarsCoverSOS1(scip, conflictgraph, conflictgraphlin, trafolinvars, coveredvars, cliquecovers[ncliquecovers], &(cliquecoversizes[ncliquecovers]), v, FALSE) );
2899 	            ++ncliquecovers;
2900 	         }
2901 	      }
2902 	
2903 	      /* free conflictgraph */
2904 	      SCIPdigraphFree(&conflictgraphlin);
2905 	
2906 	      /* compute variables that are not contained in transformed linear constraint, but are in conflict with a variable from the transformed linear constraint */
2907 	      nsos1linvars = 0;
2908 	      for (v = 0; v < ntrafolinvars; ++v)
2909 	      {
2910 	         int nodev;
2911 	
2912 	         nodev = varGetNodeSOS1(conshdlrdata, trafolinvars[v]);
2913 	
2914 	         /* if variable is an SOS1 variable */
2915 	         if ( nodev >= 0 )
2916 	         {
2917 	            int succnode;
2918 	            int nsucc;
2919 	            int* succ;
2920 	            int s;
2921 	
2922 	            succ = SCIPdigraphGetSuccessors(conflictgraph, nodev);
2923 	            nsucc = SCIPdigraphGetNSuccessors(conflictgraph, nodev);
2924 	
2925 	            for (s = 0; s < nsucc; ++s)
2926 	            {
2927 	               succnode = succ[s];
2928 	
2929 	               /* if variable is not a member of linear constraint and not already listed in the array sos1linvars */
2930 	               if ( varindincons[succnode] == -1 )
2931 	               {
2932 	                  sos1linvars[nsos1linvars] = SCIPnodeGetVarSOS1(conflictgraph, succnode);
2933 	                  varindincons[succnode] = -2; /* mark variable as listed in array sos1linvars */
2934 	                  ++nsos1linvars;
2935 	               }
2936 	            }
2937 	         }
2938 	      }
2939 	
2940 	      /* try to tighten lower bounds */
2941 	
2942 	      /* sort each cliquecover array in ascending order of the lower bounds of a_i * x_i; fill vector varincover */
2943 	      SCIP_CALL( SCIPallocBufferArray(scip, &varincover, ntrafolinvars) );
2944 	      for (i = 0; i < ncliquecovers; ++i)
2945 	      {
2946 	         for (j = 0; j < cliquecoversizes[i]; ++j)
2947 	         {
2948 	            int ind = cliquecovers[i][j];
2949 	
2950 	            varincover[ind] = i;
2951 	            cliquecovervals[j] = trafoubs[ind];
2952 	         }
2953 	         SCIPsortDownRealInt(cliquecovervals, cliquecovers[i], cliquecoversizes[i]);
2954 	      }
2955 	
2956 	      /* for every variable in transformed constraint: try lower bound tightening */
2957 	      for (v = 0; v < ntrafolinvars + nsos1linvars; ++v)
2958 	      {
2959 	         SCIP_Real newboundnonzero; /* new bound of a_v * x_v if we assume that x_v != 0 */
2960 	         SCIP_Real newboundnores;   /* new bound of a_v * x_v if we assume that x_v = 0 is possible */
2961 	         SCIP_Real newbound;        /* resulting new bound of x_v */
2962 	         SCIP_VAR* var;
2963 	         SCIP_Real trafoubv;
2964 	         SCIP_Real linval;
2965 	         SCIP_Real ub;
2966 	         SCIP_Real lb;
2967 	         SCIP_Bool tightened;
2968 	         SCIP_Bool infeasible;
2969 	         SCIP_Bool inftynores = FALSE;
2970 	         SCIP_Bool update;
2971 	         int ninftynonzero = 0;
2972 	         int nodev;
2973 	         int w;
2974 	
2975 	         if ( v < ntrafolinvars )
2976 	         {
2977 	            var = trafolinvars[v];
2978 	            trafoubv = trafoubs[v];
2979 	         }
2980 	         else
2981 	         {
2982 	            assert( v >= ntrafolinvars );
2983 	            var = sos1linvars[v-ntrafolinvars];/*lint !e679*/
2984 	            trafoubv = 0.0;
2985 	         }
2986 	
2987 	         ub = SCIPvarGetUbLocal(var);
2988 	         lb = SCIPvarGetLbLocal(var);
2989 	
2990 	         if ( SCIPisInfinity(scip, -trafolhs) || SCIPisZero(scip, ub - lb) )
2991 	            continue;
2992 	
2993 	         newboundnonzero = trafolhs;
2994 	         newboundnores = trafolhs;
2995 	         nodev = varGetNodeSOS1(conshdlrdata, var); /* possibly -1 if var is not involved in an SOS1 constraint */
2996 	         assert( nodev < nsos1vars );
2997 	
2998 	         /* determine incidence vector of implication variables */
2999 	         for (w = 0; w < nsos1vars; ++w)
3000 	            implnodes[w] = FALSE;
3001 	         SCIP_CALL( getSOS1Implications(scip, conshdlrdata, totalvars, implgraph, implhash, implnodes, SCIPhashmapGetImageInt(implhash, var)) );
3002 	
3003 	         /* compute new bound */
3004 	         for (i = 0; i < ncliquecovers; ++i)
3005 	         {
3006 	            int indcliq;
3007 	            int nodecliq;
3008 	
3009 	            assert( cliquecoversizes[i] > 0 );
3010 	
3011 	            indcliq = cliquecovers[i][0];
3012 	            assert( 0 <= indcliq && indcliq < ntrafolinvars );
3013 	
3014 	            /* determine maximum without index v (note that the array 'cliquecovers' is sorted by the values of trafoub in non-increasing order) */
3015 	            if ( v != indcliq )
3016 	            {
3017 	               if ( SCIPisInfinity(scip, trafoubs[indcliq]) || SCIPisInfinity(scip, REALABS(newboundnores - trafoubs[indcliq])) )
3018 	                  inftynores = TRUE;
3019 	               else
3020 	                  newboundnores -= trafoubs[indcliq];
3021 	            }
3022 	            else if ( cliquecoversizes[i] > 1 )
3023 	            {
3024 	               assert( 0 <= cliquecovers[i][1] && cliquecovers[i][1] < ntrafolinvars );
3025 	               if ( SCIPisInfinity(scip, trafoubs[cliquecovers[i][1]]) || SCIPisInfinity(scip, REALABS(newboundnores - trafoubs[cliquecovers[i][1]])) )
3026 	                  inftynores = TRUE;
3027 	               else
3028 	                  newboundnores -= trafoubs[cliquecovers[i][1]];/*lint --e{679}*/
3029 	            }
3030 	
3031 	            /* determine maximum without index v and if x_v is nonzero (note that the array 'cliquecovers' is sorted by the values of trafoub in non-increasing order) */
3032 	            for (j = 0; j < cliquecoversizes[i]; ++j)
3033 	            {
3034 	               indcliq = cliquecovers[i][j];
3035 	               assert( 0 <= indcliq && indcliq < ntrafolinvars );
3036 	
3037 	               nodecliq = varGetNodeSOS1(conshdlrdata, trafolinvars[indcliq]); /* possibly -1 if variable is not involved in an SOS1 constraint */
3038 	               assert( nodecliq < nsos1vars );
3039 	
3040 	               if ( v != indcliq )
3041 	               {
3042 	                  /* if nodev or nodecliq are not a member of an SOS1 constraint or the variable corresponding to nodecliq is not implied to be zero if x_v != 0  */
3043 	                  if ( nodev < 0 || nodecliq < 0 || (! isConnectedSOS1(adjacencymatrix, NULL, nodev, nodecliq) && ! isImpliedZero(conflictgraph, implnodes, nodecliq) ) )
3044 	                  {
3045 	                     if ( SCIPisInfinity(scip, trafoubs[indcliq]) || SCIPisInfinity(scip, REALABS(newboundnonzero - trafoubs[indcliq])) )
3046 	                        ++ninftynonzero;
3047 	                     else
3048 	                        newboundnonzero -= trafoubs[indcliq];
3049 	                     break; /* break since we are only interested in the maximum upper bound among the variables in the clique cover;
3050 	                             * the variables in the clique cover form an SOS1 constraint, thus only one of them can be nonzero */
3051 	                  }
3052 	               }
3053 	            }
3054 	         }
3055 	         assert( ninftynonzero == 0 || inftynores );
3056 	
3057 	         /* if computed upper bound is not infinity and variable is contained in linear constraint */
3058 	         if ( ninftynonzero == 0 && v < ntrafolinvars )
3059 	         {
3060 	            linval = trafolinvals[v];
3061 	
3062 	            if ( SCIPisFeasZero(scip, linval) )
3063 	               continue;
3064 	
3065 	            /* compute new bound */
3066 	            if ( SCIPisFeasPositive(scip, newboundnores) && ! inftynores )
3067 	               newbound = newboundnonzero;
3068 	            else
3069 	               newbound = MIN(0, newboundnonzero);
3070 	            newbound /= linval;
3071 	
3072 	            if ( SCIPisInfinity(scip, newbound) )
3073 	               continue;
3074 	
3075 	            /* check if new bound is tighter than the old one or problem is infeasible */
3076 	            if ( SCIPisFeasPositive(scip, linval) && SCIPisFeasLT(scip, lb, newbound) )
3077 	            {
3078 	               if ( SCIPisFeasLT(scip, ub, newbound) )
3079 	               {
3080 	                  *cutoff = TRUE;
3081 	                  break;
3082 	               }
3083 	
3084 	               if ( SCIPvarIsIntegral(var) )
3085 	                  newbound = SCIPceil(scip, newbound);
3086 	
3087 	               SCIP_CALL( SCIPtightenVarLb(scip, var, newbound, FALSE, &infeasible, &tightened) );
3088 	               assert( ! infeasible );
3089 	
3090 	               if ( tightened )
3091 	               {
3092 	                  SCIPdebugMsg(scip, "changed lower bound of variable %s from %f to %f \n", SCIPvarGetName(var), lb, newbound);
3093 	                  ++(*nchgbds);
3094 	               }
3095 	            }
3096 	            else if ( SCIPisFeasNegative(scip, linval) && SCIPisFeasGT(scip, ub, newbound) )
3097 	            {
3098 	               /* if assumption a_i * x_i != 0 was not correct */
3099 	               if ( SCIPisFeasGT(scip, SCIPvarGetLbLocal(var), newbound) )
3100 	               {
3101 	                  *cutoff = TRUE;
3102 	                  break;
3103 	               }
3104 	
3105 	               if ( SCIPvarIsIntegral(var) )
3106 	                  newbound = SCIPfloor(scip, newbound);
3107 	
3108 	               SCIP_CALL( SCIPtightenVarUb(scip, var, newbound, FALSE, &infeasible, &tightened) );
3109 	               assert( ! infeasible );
3110 	
3111 	               if ( tightened )
3112 	               {
3113 	                  SCIPdebugMsg(scip, "changed upper bound of variable %s from %f to %f \n", SCIPvarGetName(var), ub, newbound);
3114 	                  ++(*nchgbds);
3115 	               }
3116 	            }
3117 	         }
3118 	
3119 	         /* update implication graph if possible */
3120 	         SCIP_CALL( updateImplicationGraphSOS1(scip, conshdlrdata, conflictgraph, adjacencymatrix, implgraph, implhash, implnodes, totalvars, cliquecovers, cliquecoversizes, varincover,
3121 	               trafolinvars, trafolinvals, ntrafolinvars, trafoubs, var, trafoubv, newboundnonzero, ninftynonzero, TRUE, nchgbds, &update, &infeasible) );
3122 	         if ( infeasible )
3123 	            *cutoff = TRUE;
3124 	         else if ( update )
3125 	            *implupdate = TRUE;
3126 	      }
3127 	
3128 	      if ( *cutoff == TRUE )
3129 	      {
3130 	         /* free memory */
3131 	         SCIPfreeBufferArrayNull(scip, &varincover);
3132 	         for (j = ncliquecovers-1; j >= 0; --j)
3133 	            SCIPfreeBufferArrayNull(scip, &cliquecovers[j]);
3134 	         SCIPfreeBufferArrayNull(scip, &cliquecovers);
3135 	         SCIPfreeBufferArrayNull(scip, &cliquecoversizes);
3136 	         SCIPfreeBufferArrayNull(scip, &cliquecovervals);
3137 	         SCIPfreeBufferArrayNull(scip, &trafolinvals);
3138 	         SCIPfreeBufferArrayNull(scip, &trafolinvars);
3139 	         break;
3140 	      }
3141 	
3142 	      /* try to tighten upper bounds */
3143 	
3144 	      /* sort each cliquecover array in ascending order of the lower bounds of a_i * x_i; fill vector varincover */
3145 	      for (i = 0; i < ncliquecovers; ++i)
3146 	      {
3147 	         for (j = 0; j < cliquecoversizes[i]; ++j)
3148 	         {
3149 	            int ind = cliquecovers[i][j];
3150 	
3151 	            varincover[ind] = i;
3152 	            cliquecovervals[j] = trafolbs[ind];
3153 	         }
3154 	         SCIPsortRealInt(cliquecovervals, cliquecovers[i], cliquecoversizes[i]);
3155 	      }
3156 	
3157 	      /* for every variable that is in transformed constraint or every variable that is in conflict with some variable from trans. cons.:
3158 	         try upper bound tightening */
3159 	      for (v = 0; v < ntrafolinvars + nsos1linvars; ++v)
3160 	      {
3161 	         SCIP_Real newboundnonzero; /* new bound of a_v*x_v if we assume that x_v != 0 */
3162 	         SCIP_Real newboundnores;   /* new bound of a_v*x_v if there are no restrictions */
3163 	         SCIP_Real newbound;        /* resulting new bound of x_v */
3164 	         SCIP_VAR* var;
3165 	         SCIP_Real linval;
3166 	         SCIP_Real trafolbv;
3167 	         SCIP_Real lb;
3168 	         SCIP_Real ub;
3169 	         SCIP_Bool tightened;
3170 	         SCIP_Bool infeasible;
3171 	         SCIP_Bool inftynores = FALSE;
3172 	         SCIP_Bool update;
3173 	         int ninftynonzero = 0;
3174 	         int nodev;
3175 	         int w;
3176 	
3177 	         if ( v < ntrafolinvars )
3178 	         {
3179 	            var = trafolinvars[v];
3180 	            trafolbv = trafolbs[v];
3181 	         }
3182 	         else
3183 	         {
3184 	            assert( v-ntrafolinvars >= 0 );
3185 	            var = sos1linvars[v-ntrafolinvars];/*lint !e679*/
3186 	            trafolbv = 0.0; /* since variable is not a member of linear constraint */
3187 	         }
3188 	         lb = SCIPvarGetLbLocal(var);
3189 	         ub = SCIPvarGetUbLocal(var);
3190 	         if ( SCIPisInfinity(scip, traforhs) || SCIPisEQ(scip, lb, ub) )
3191 	            continue;
3192 	
3193 	         newboundnonzero = traforhs;
3194 	         newboundnores = traforhs;
3195 	         nodev = varGetNodeSOS1(conshdlrdata, var); /* possibly -1 if var is not involved in an SOS1 constraint */
3196 	         assert( nodev < nsos1vars );
3197 	
3198 	         /* determine incidence vector of implication variables (i.e., which SOS1 variables are nonzero if x_v is nonzero) */
3199 	         for (w = 0; w < nsos1vars; ++w)
3200 	            implnodes[w] = FALSE;
3201 	         SCIP_CALL( getSOS1Implications(scip, conshdlrdata, totalvars, implgraph, implhash, implnodes, SCIPhashmapGetImageInt(implhash, var)) );
3202 	
3203 	         /* compute new bound */
3204 	         for (i = 0; i < ncliquecovers; ++i)
3205 	         {
3206 	            int indcliq;
3207 	            int nodecliq;
3208 	
3209 	            assert( cliquecoversizes[i] > 0 );
3210 	
3211 	            indcliq = cliquecovers[i][0];
3212 	            assert( 0 <= indcliq && indcliq < ntrafolinvars );
3213 	
3214 	            /* determine minimum without index v (note that the array 'cliquecovers' is sorted by the values of trafolb in increasing order) */
3215 	            if ( v != indcliq )
3216 	            {
3217 	               /* if bound would be infinity */
3218 	               if ( SCIPisInfinity(scip, -trafolbs[indcliq]) || SCIPisInfinity(scip, REALABS(newboundnores - trafolbs[indcliq])) )
3219 	                  inftynores = TRUE;
3220 	               else
3221 	                  newboundnores -= trafolbs[indcliq];
3222 	            }
3223 	            else if ( cliquecoversizes[i] > 1 )
3224 	            {
3225 	               assert( 0 <= cliquecovers[i][1] && cliquecovers[i][1] < ntrafolinvars );
3226 	               if ( SCIPisInfinity(scip, -trafolbs[cliquecovers[i][1]]) || SCIPisInfinity(scip, REALABS(newboundnores - trafolbs[cliquecovers[i][1]])) )
3227 	                  inftynores = TRUE;
3228 	               else
3229 	                  newboundnores -= trafolbs[cliquecovers[i][1]]; /*lint --e{679}*/
3230 	            }
3231 	
3232 	            /* determine minimum without index v and if x_v is nonzero (note that the array 'cliquecovers' is sorted by the values of trafolb in increasing order) */
3233 	            for (j = 0; j < cliquecoversizes[i]; ++j)
3234 	            {
3235 	               indcliq = cliquecovers[i][j];
3236 	               assert( 0 <= indcliq && indcliq < ntrafolinvars );
3237 	
3238 	               nodecliq = varGetNodeSOS1(conshdlrdata, trafolinvars[indcliq]); /* possibly -1 if variable is not involved in an SOS1 constraint */
3239 	               assert( nodecliq < nsos1vars );
3240 	
3241 	               if ( v != indcliq )
3242 	               {
3243 	                  /* if nodev or nodecliq are not a member of an SOS1 constraint or the variable corresponding to nodecliq is not implied to be zero if x_v != 0  */
3244 	                  if ( nodev < 0 || nodecliq < 0 || (! isConnectedSOS1(adjacencymatrix, NULL, nodev, nodecliq) && ! isImpliedZero(conflictgraph, implnodes, nodecliq) ) )
3245 	                  {
3246 	                     /* if bound would be infinity */
3247 	                     if ( SCIPisInfinity(scip, -trafolbs[indcliq]) || SCIPisInfinity(scip, REALABS(newboundnonzero - trafolbs[indcliq])) )
3248 	                        ++ninftynonzero;
3249 	                     else
3250 	                        newboundnonzero -= trafolbs[indcliq];
3251 	                     break; /* break since we are only interested in the minimum lower bound among the variables in the clique cover;
3252 	                             * the variables in the clique cover form an SOS1 constraint, thus only one of them can be nonzero */
3253 	                  }
3254 	               }
3255 	            }
3256 	         }
3257 	         assert( ninftynonzero == 0 || inftynores );
3258 	
3259 	         /* if computed bound is not infinity and variable is contained in linear constraint */
3260 	         if ( ninftynonzero == 0 && v < ntrafolinvars )
3261 	         {
3262 	            linval = trafolinvals[v];
3263 	
3264 	            if ( SCIPisFeasZero(scip, linval) )
3265 	               continue;
3266 	
3267 	            /* compute new bound */
3268 	            if ( SCIPisFeasNegative(scip, newboundnores) && ! inftynores )
3269 	               newbound = newboundnonzero;
3270 	            else
3271 	               newbound = MAX(0, newboundnonzero);
3272 	            newbound /= linval;
3273 	
3274 	            if ( SCIPisInfinity(scip, newbound) )
3275 	               continue;
3276 	
3277 	            /* check if new bound is tighter than the old one or problem is infeasible */
3278 	            if ( SCIPisFeasPositive(scip, linval) && SCIPisFeasGT(scip, ub, newbound) )
3279 	            {
3280 	               /* if new upper bound is smaller than the lower bound, we are infeasible */
3281 	               if ( SCIPisFeasGT(scip, lb, newbound) )
3282 	               {
3283 	                  *cutoff = TRUE;
3284 	                  break;
3285 	               }
3286 	
3287 	               if ( SCIPvarIsIntegral(var) )
3288 	                  newbound = SCIPfloor(scip, newbound);
3289 	
3290 	               SCIP_CALL( SCIPtightenVarUb(scip, var, newbound, FALSE, &infeasible, &tightened) );
3291 	               assert( ! infeasible );
3292 	
3293 	               if ( tightened )
3294 	               {
3295 	                  SCIPdebugMsg(scip, "changed upper bound of variable %s from %f to %f \n", SCIPvarGetName(var), ub, newbound);
3296 	                  ++(*nchgbds);
3297 	               }
3298 	            }
3299 	            else if ( SCIPisFeasNegative(scip, linval) && SCIPisFeasLT(scip, lb, newbound) )
3300 	            {
3301 	               /* if assumption a_i * x_i != 0 was not correct */
3302 	               if ( SCIPisFeasLT(scip, ub, newbound) )
3303 	               {
3304 	                  *cutoff = TRUE;
3305 	                  break;
3306 	               }
3307 	
3308 	               if ( SCIPvarIsIntegral(var) )
3309 	                  newbound = SCIPceil(scip, newbound);
3310 	
3311 	               SCIP_CALL( SCIPtightenVarLb(scip, var, newbound, FALSE, &infeasible, &tightened) );
3312 	               assert( ! infeasible );
3313 	
3314 	               if ( tightened )
3315 	               {
3316 	                  SCIPdebugMsg(scip, "changed lower bound of variable %s from %f to %f \n", SCIPvarGetName(var), lb, newbound);
3317 	                  ++(*nchgbds);
3318 	               }
3319 	            }
3320 	         }
3321 	
3322 	         /* update implication graph if possible */
3323 	         SCIP_CALL( updateImplicationGraphSOS1(scip, conshdlrdata, conflictgraph, adjacencymatrix, implgraph, implhash, implnodes, totalvars, cliquecovers, cliquecoversizes, varincover,
3324 	               trafolinvars, trafolinvals, ntrafolinvars, trafolbs, var, trafolbv, newboundnonzero, ninftynonzero, FALSE, nchgbds, &update, &infeasible) );
3325 	         if ( infeasible )
3326 	            *cutoff = TRUE;
3327 	         else if ( update )
3328 	            *implupdate = TRUE;
3329 	      }
3330 	
3331 	      /* free memory */
3332 	      SCIPfreeBufferArrayNull(scip, &varincover);
3333 	      for (j = ncliquecovers-1; j >= 0; --j)
3334 	         SCIPfreeBufferArrayNull(scip, &cliquecovers[j]);
3335 	      SCIPfreeBufferArrayNull(scip, &cliquecovers);
3336 	      SCIPfreeBufferArrayNull(scip, &cliquecoversizes);
3337 	      SCIPfreeBufferArrayNull(scip, &cliquecovervals);
3338 	      SCIPfreeBufferArrayNull(scip, &trafolinvals);
3339 	      SCIPfreeBufferArrayNull(scip, &trafolinvars);
3340 	
3341 	      if ( *cutoff == TRUE )
3342 	         break;
3343 	   } /* end for every linear constraint */
3344 	
3345 	   /* free buffer arrays */
3346 	   SCIPfreeBufferArrayNull(scip, &trafolbs);
3347 	   SCIPfreeBufferArrayNull(scip, &trafoubs);
3348 	   SCIPfreeBufferArrayNull(scip, &coveredvars);
3349 	   SCIPfreeBufferArrayNull(scip, &varindincons);
3350 	   SCIPfreeBufferArrayNull(scip, &implnodes);
3351 	   SCIPfreeBufferArrayNull(scip, &sos1linvars);
3352 	
3353 	   return SCIP_OKAY;
3354 	}
3355 	
3356 	
3357 	/** perform one presolving round for variables
3358 	 *
3359 	 *  We perform the following presolving steps:
3360 	 *  - Tighten the bounds of the variables
3361 	 *  - Update conflict graph based on bound implications of the variables
3362 	 */
3363 	static
3364 	SCIP_RETCODE presolRoundVarsSOS1(
3365 	   SCIP*                 scip,               /**< SCIP pointer */
3366 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
3367 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
3368 	   SCIP_Bool**           adjacencymatrix,    /**< adjacencymatrix of conflict graph */
3369 	   int                   nsos1vars,          /**< number of SOS1 variables */
3370 	   int*                  nfixedvars,         /**< pointer to store number of fixed variables */
3371 	   int*                  nchgbds,            /**< pointer to store number of changed bounds */
3372 	   int*                  naddconss,          /**< pointer to store number of addded constraints */
3373 	   SCIP_RESULT*          result              /**< result */
3374 	   )
3375 	{
3376 	   SCIP_DIGRAPH* implgraph;
3377 	   SCIP_HASHMAP* implhash;
3378 	
3379 	   SCIP_Bool cutoff = FALSE;
3380 	   SCIP_Bool updateconfl;
3381 	
3382 	   SCIP_VAR** totalvars;
3383 	   SCIP_VAR** probvars;
3384 	   int ntotalvars = 0;
3385 	   int nprobvars;
3386 	   int i;
3387 	   int j;
3388 	
3389 	   /* determine totalvars (union of SOS1 and problem variables) */
3390 	   probvars = SCIPgetVars(scip);
3391 	   nprobvars = SCIPgetNVars(scip);
3392 	   SCIP_CALL( SCIPhashmapCreate(&implhash, SCIPblkmem(scip), nsos1vars + nprobvars) );
3393 	   SCIP_CALL( SCIPallocBufferArray(scip, &totalvars, nsos1vars + nprobvars) );
3394 	
3395 	   for (i = 0; i < nsos1vars; ++i)
3396 	   {
3397 	      SCIP_VAR* var;
3398 	      var = SCIPnodeGetVarSOS1(conflictgraph, i);
3399 	
3400 	      /* insert node number to hash map */
3401 	      assert( ! SCIPhashmapExists(implhash, var) );
3402 	      SCIP_CALL( SCIPhashmapInsertInt(implhash, var, ntotalvars) );
3403 	      assert( ntotalvars == SCIPhashmapGetImageInt(implhash, var) );
3404 	      totalvars[ntotalvars++] = var;
3405 	   }
3406 	
3407 	   for (i = 0; i < nprobvars; ++i)
3408 	   {
3409 	      SCIP_VAR* var;
3410 	      var = probvars[i];
3411 	
3412 	      /* insert node number to hash map if not existent */
3413 	      if ( ! SCIPhashmapExists(implhash, var) )
3414 	      {
3415 	         SCIP_CALL( SCIPhashmapInsertInt(implhash, var, ntotalvars) );
3416 	         assert( ntotalvars == SCIPhashmapGetImageInt(implhash, var) );
3417 	         totalvars[ntotalvars++] = var;
3418 	      }
3419 	   }
3420 	
3421 	   /* create implication graph */
3422 	   SCIP_CALL( SCIPcreateDigraph(scip, &implgraph, ntotalvars) );
3423 	
3424 	   /* try to tighten the lower and upper bounds of the variables */
3425 	   updateconfl = FALSE;
3426 	   for (j = 0; (j < conshdlrdata->maxtightenbds || conshdlrdata->maxtightenbds == -1 ) && ! cutoff; ++j)
3427 	   {
3428 	      SCIP_Bool implupdate;
3429 	      int nchgbdssave;
3430 	
3431 	      nchgbdssave = *nchgbds;
3432 	
3433 	      assert( ntotalvars > 0 );
3434 	      SCIP_CALL( tightenVarsBoundsSOS1(scip, conshdlrdata, conflictgraph, implgraph, implhash, adjacencymatrix, totalvars, ntotalvars, nsos1vars, nchgbds, &implupdate, &cutoff) );
3435 	      if ( *nchgbds > nchgbdssave )
3436 	      {
3437 	         *result = SCIP_SUCCESS;
3438 	         if ( implupdate )
3439 	            updateconfl = TRUE;
3440 	      }
3441 	      else if ( implupdate )
3442 	         updateconfl = TRUE;
3443 	      else
3444 	         break;
3445 	   }
3446 	
3447 	   /* perform implication graph analysis */
3448 	   if ( updateconfl && conshdlrdata->perfimplanalysis && ! cutoff )
3449 	   {
3450 	      SCIP_Real* implubs;
3451 	      SCIP_Real* impllbs;
3452 	      SCIP_Bool* implnodes;
3453 	      SCIP_Bool infeasible;
3454 	      SCIP_Bool fixed;
3455 	      int naddconsssave;
3456 	      int probingdepth;
3457 	
3458 	      /* allocate buffer arrays */
3459 	      SCIP_CALL( SCIPallocBufferArray(scip, &implnodes, nsos1vars) );
3460 	      SCIP_CALL( SCIPallocBufferArray(scip, &impllbs, ntotalvars) );
3461 	      SCIP_CALL( SCIPallocBufferArray(scip, &implubs, ntotalvars) );
3462 	
3463 	      naddconsssave = *naddconss;
3464 	      for (i = 0; i < nsos1vars; ++i)
3465 	      {
3466 		 /* initialize data for implication graph analysis */
3467 		 infeasible = FALSE;
3468 		 probingdepth = 0;
3469 	         for (j = 0; j < nsos1vars; ++j)
3470 	            implnodes[j] = FALSE;
3471 		 for (j = 0; j < ntotalvars; ++j)
3472 		 {
3473 		    impllbs[j] = SCIPvarGetLbLocal(totalvars[j]);
3474 		    implubs[j] = SCIPvarGetUbLocal(totalvars[j]);
3475 		 }
3476 	
3477 		 /* try to update the conflict graph based on the information of the implication graph */
3478 		 SCIP_CALL( performImplicationGraphAnalysis(scip, conshdlrdata, conflictgraph, totalvars, implgraph, implhash, adjacencymatrix, i, i, impllbs, implubs, implnodes, naddconss, &probingdepth, &infeasible) );
3479 	
3480 		 /* if the subproblem turned out to be infeasible then fix variable to zero */
3481 		 if ( infeasible )
3482 		 {
3483 		    SCIP_CALL( SCIPfixVar(scip, totalvars[i], 0.0, &infeasible, &fixed) );
3484 	
3485 		    if ( fixed )
3486 		    {
3487 		       SCIPdebugMsg(scip, "fixed variable %s with lower bound %f and upper bound %f to zero\n",
3488 					SCIPvarGetName(totalvars[i]), SCIPvarGetLbLocal(totalvars[i]), SCIPvarGetUbLocal(totalvars[i]));
3489 		       ++(*nfixedvars);
3490 		    }
3491 	
3492 		    if ( infeasible )
3493 		       cutoff = TRUE;
3494 		 }
3495 	      }
3496 	
3497 	      if ( *naddconss > naddconsssave )
3498 	         *result = SCIP_SUCCESS;
3499 	
3500 	      /* free buffer arrays */
3501 	      SCIPfreeBufferArrayNull(scip, &implubs);
3502 	      SCIPfreeBufferArrayNull(scip, &impllbs);
3503 	      SCIPfreeBufferArrayNull(scip, &implnodes);
3504 	   }
3505 	
3506 	   /* if an infeasibility has been detected */
3507 	   if ( cutoff )
3508 	   {
3509 	      SCIPdebugMsg(scip, "cutoff \n");
3510 	      *result = SCIP_CUTOFF;
3511 	   }
3512 	
3513 	   /* free memory */;
3514 	   for (j = ntotalvars-1; j >= 0; --j)
3515 	   {
3516 	      SCIP_SUCCDATA** succdatas;
3517 	      int nsucc;
3518 	      int s;
3519 	
3520 	      succdatas = (SCIP_SUCCDATA**) SCIPdigraphGetSuccessorsData(implgraph, j);
3521 	      nsucc = SCIPdigraphGetNSuccessors(implgraph, j);
3522 	
3523 	      for (s = nsucc-1; s >= 0; --s)
3524 	         SCIPfreeBlockMemory(scip, &succdatas[s]);/*lint !e866*/
3525 	   }
3526 	   SCIPdigraphFree(&implgraph);
3527 	   SCIPfreeBufferArrayNull(scip, &totalvars);
3528 	   SCIPhashmapFree(&implhash);
3529 	
3530 	   return SCIP_OKAY;
3531 	}
3532 	
3533 	
3534 	/* ----------------------------- propagation -------------------------------------*/
3535 	
3536 	/** propagate variables of SOS1 constraint */
3537 	static
3538 	SCIP_RETCODE propConsSOS1(
3539 	   SCIP*                 scip,               /**< SCIP pointer */
3540 	   SCIP_CONS*            cons,               /**< constraint */
3541 	   SCIP_CONSDATA*        consdata,           /**< constraint data */
3542 	   SCIP_Bool*            cutoff,             /**< whether a cutoff happened */
3543 	   int*                  ngen                /**< number of domain changes */
3544 	   )
3545 	{
3546 	   assert( scip != NULL );
3547 	   assert( cons != NULL );
3548 	   assert( consdata != NULL );
3549 	   assert( cutoff != NULL );
3550 	   assert( ngen != NULL );
3551 	
3552 	   *cutoff = FALSE;
3553 	
3554 	   /* if more than one variable is fixed to be nonzero */
3555 	   if ( consdata->nfixednonzeros > 1 )
3556 	   {
3557 	      SCIPdebugMsg(scip, "the node is infeasible, more than 1 variable is fixed to be nonzero.\n");
3558 	      SCIP_CALL( SCIPresetConsAge(scip, cons) );
3559 	      *cutoff = TRUE;
3560 	      return SCIP_OKAY;
3561 	   }
3562 	
3563 	   /* if exactly one variable is fixed to be nonzero */
3564 	   if ( consdata->nfixednonzeros == 1 )
3565 	   {
3566 	      SCIP_VAR** vars;
3567 	      SCIP_Bool infeasible;
3568 	      SCIP_Bool tightened;
3569 	      SCIP_Bool success;
3570 	      SCIP_Bool allVarFixed;
3571 	      int firstFixedNonzero;
3572 	      int nvars;
3573 	      int j;
3574 	
3575 	      firstFixedNonzero = -1;
3576 	      nvars = consdata->nvars;
3577 	      vars = consdata->vars;
3578 	      assert( vars != NULL );
3579 	
3580 	      /* search nonzero variable - is needed for propinfo */
3581 	      for (j = 0; j < nvars; ++j)
3582 	      {
3583 	         if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(vars[j])) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(vars[j])) )
3584 	         {
3585 	            firstFixedNonzero = j;
3586 	            break;
3587 	         }
3588 	      }
3589 	      assert( firstFixedNonzero >= 0 );
3590 	
3591 	      SCIPdebugMsg(scip, "variable <%s> is fixed nonzero, fixing other variables to 0.\n", SCIPvarGetName(vars[firstFixedNonzero]));
3592 	
3593 	      /* fix variables before firstFixedNonzero to 0 */
3594 	      allVarFixed = TRUE;
3595 	      for (j = 0; j < firstFixedNonzero; ++j)
3596 	      {
3597 	         /* fix variable */
3598 	         SCIP_CALL( inferVariableZero(scip, vars[j], cons, firstFixedNonzero, &infeasible, &tightened, &success) );
3599 	         assert( ! infeasible );
3600 	         allVarFixed = allVarFixed && success;
3601 	         if ( tightened )
3602 	            ++(*ngen);
3603 	      }
3604 	
3605 	      /* fix variables after firstFixedNonzero to 0 */
3606 	      for (j = firstFixedNonzero+1; j < nvars; ++j)
3607 	      {
3608 	         /* fix variable */
3609 	         SCIP_CALL( inferVariableZero(scip, vars[j], cons, firstFixedNonzero, &infeasible, &tightened, &success) );
3610 	         assert( ! infeasible ); /* there should be no variables after firstFixedNonzero that are fixed to be nonzero */
3611 	         allVarFixed = allVarFixed && success;
3612 	         if ( tightened )
3613 	            ++(*ngen);
3614 	      }
3615 	
3616 	      /* reset constraint age counter */
3617 	      if ( *ngen > 0 )
3618 	      {
3619 	         SCIP_CALL( SCIPresetConsAge(scip, cons) );
3620 	      }
3621 	
3622 	      /* delete constraint locally */
3623 	      if ( allVarFixed )
3624 	      {
3625 	         assert( !SCIPconsIsModifiable(cons) );
3626 	         SCIP_CALL( SCIPdelConsLocal(scip, cons) );
3627 	      }
3628 	   }
3629 	
3630 	   return SCIP_OKAY;
3631 	}
3632 	
3633 	
3634 	/** propagate a variable that is known to be nonzero */
3635 	static
3636 	SCIP_RETCODE propVariableNonzero(
3637 	   SCIP*                 scip,               /**< SCIP pointer */
3638 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
3639 	   SCIP_DIGRAPH*         implgraph,          /**< implication graph */
3640 	   SCIP_CONS*            cons,               /**< some arbitrary SOS1 constraint */
3641 	   int                   node,               /**< conflict graph node of variable that is known to be nonzero */
3642 	   SCIP_Bool             implprop,           /**< whether implication graph propagation shall be applied */
3643 	   SCIP_Bool*            cutoff,             /**< whether a cutoff happened */
3644 	   int*                  ngen                /**< number of domain changes */
3645 	   )
3646 	{
3647 	   int inferinfo;
3648 	   int* succ;
3649 	   int nsucc;
3650 	   int s;
3651 	
3652 	   assert( scip != NULL );
3653 	   assert( conflictgraph != NULL );
3654 	   assert( cutoff != NULL );
3655 	   assert( ngen != NULL );
3656 	   assert( node >= 0 );
3657 	
3658 	   *cutoff = FALSE;
3659 	   inferinfo = -node - 1;
3660 	
3661 	   /* by assumption zero is outside the domain of variable */
3662 	   assert( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(SCIPnodeGetVarSOS1(conflictgraph, node))) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(SCIPnodeGetVarSOS1(conflictgraph, node))) );
3663 	
3664 	   /* apply conflict graph propagation (fix all neighbors in the conflict graph to zero) */
3665 	   succ = SCIPdigraphGetSuccessors(conflictgraph, node);
3666 	   nsucc = SCIPdigraphGetNSuccessors(conflictgraph, node);
3667 	   for (s = 0; s < nsucc; ++s)
3668 	   {
3669 	      SCIP_VAR* succvar;
3670 	      SCIP_Real lb;
3671 	      SCIP_Real ub;
3672 	
3673 	      succvar = SCIPnodeGetVarSOS1(conflictgraph, succ[s]);
3674 	      lb = SCIPvarGetLbLocal(succvar);
3675 	      ub = SCIPvarGetUbLocal(succvar);
3676 	
3677 	      if ( ! SCIPisFeasZero(scip, lb) || ! SCIPisFeasZero(scip, ub) )
3678 	      {
3679 	         SCIP_Bool infeasible;
3680 	         SCIP_Bool tightened;
3681 	         SCIP_Bool success;
3682 	
3683 	         /* fix variable if it is not multi-aggregated */
3684 	         SCIP_CALL( inferVariableZero(scip, succvar, cons, inferinfo, &infeasible, &tightened, &success) );
3685 	
3686 	         if ( infeasible )
3687 	         {
3688 	            /* variable cannot be nonzero */
3689 	            *cutoff = TRUE;
3690 	            return SCIP_OKAY;
3691 	         }
3692 	         if ( tightened )
3693 	            ++(*ngen);
3694 	         assert( success || SCIPvarGetStatus(succvar) == SCIP_VARSTATUS_MULTAGGR );
3695 	      }
3696 	   }
3697 	
3698 	   /* apply implication graph propagation */
3699 	   if ( implprop && implgraph != NULL )
3700 	   {
3701 	      SCIP_SUCCDATA** succdatas;
3702 	
3703 	#ifndef NDEBUG
3704 	      SCIP_NODEDATA* nodedbgdata;
3705 	      nodedbgdata = (SCIP_NODEDATA*) SCIPdigraphGetNodeData(implgraph, node);
3706 	      assert( SCIPvarCompare(nodedbgdata->var, SCIPnodeGetVarSOS1(conflictgraph, node)) == 0 );
3707 	#endif
3708 	
3709 	      /* get successor datas */
3710 	      succdatas = (SCIP_SUCCDATA**) SCIPdigraphGetSuccessorsData(implgraph, node);
3711 	
3712 	      if ( succdatas != NULL )
3713 	      {
3714 	         succ = SCIPdigraphGetSuccessors(implgraph, node);
3715 	         nsucc = SCIPdigraphGetNSuccessors(implgraph, node);
3716 	         for (s = 0; s < nsucc; ++s)
3717 	         {
3718 	            SCIP_SUCCDATA* succdata;
3719 	            SCIP_NODEDATA* nodedata;
3720 	            SCIP_VAR* var;
3721 	
3722 	            nodedata = (SCIP_NODEDATA*) SCIPdigraphGetNodeData(implgraph, succ[s]);
3723 	            assert( nodedata != NULL );
3724 	            succdata = succdatas[s];
3725 	            assert( succdata != NULL );
3726 	            var = nodedata->var;
3727 	            assert( var != NULL );
3728 	
3729 	            /* tighten variable if it is not multi-aggregated */
3730 	            if ( SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
3731 	            {
3732 	               /* check for lower bound implication */
3733 	               if ( SCIPisFeasLT(scip, SCIPvarGetLbLocal(var), succdata->lbimpl) )
3734 	               {
3735 	                  SCIP_Bool infeasible;
3736 	                  SCIP_Bool tightened;
3737 	
3738 	                  SCIP_CALL( SCIPinferVarLbCons(scip, var, succdata->lbimpl, cons, inferinfo, FALSE, &infeasible, &tightened) );
3739 	                  if ( infeasible )
3740 	                  {
3741 	                     *cutoff = TRUE;
3742 	                     return SCIP_OKAY;
3743 	                  }
3744 	                  if ( tightened )
3745 	                     ++(*ngen);
3746 	               }
3747 	
3748 	               /* check for upper bound implication */
3749 	               if ( SCIPisFeasGT(scip, SCIPvarGetUbLocal(var), succdata->ubimpl) )
3750 	               {
3751 	                  SCIP_Bool infeasible;
3752 	                  SCIP_Bool tightened;
3753 	
3754 	                  SCIP_CALL( SCIPinferVarUbCons(scip, var, succdata->ubimpl, cons, inferinfo, FALSE, &infeasible, &tightened) );
3755 	                  if ( infeasible )
3756 	                  {
3757 	                     *cutoff = TRUE;
3758 	                     return SCIP_OKAY;
3759 	                  }
3760 	                  if ( tightened )
3761 	                     ++(*ngen);
3762 	               }
3763 	            }
3764 	         }
3765 	      }
3766 	   }
3767 	
3768 	   return SCIP_OKAY;
3769 	}
3770 	
3771 	
3772 	/** initialize implication graph
3773 	 *
3774 	 *  @p j is successor of @p i if and only if \f$ x_i\not = 0 \Rightarrow x_j\not = 0\f$
3775 	 *
3776 	 *  @note By construction the implication graph is globally valid.
3777 	 */
3778 	static
3779 	SCIP_RETCODE initImplGraphSOS1(
3780 	   SCIP*                 scip,               /**< SCIP pointer */
3781 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
3782 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
3783 	   int                   nsos1vars,          /**< number of SOS1 variables */
3784 	   int                   maxrounds,          /**< maximal number of propagation rounds for generating implications */
3785 	   int*                  nchgbds,            /**< pointer to store number of bound changes */
3786 	   SCIP_Bool*            cutoff,             /**< pointer to store  whether a cutoff occurred */
3787 	   SCIP_Bool*            success             /**< whether initialization was successful */
3788 	   )
3789 	{
3790 	   SCIP_HASHMAP* implhash = NULL;
3791 	   SCIP_Bool** adjacencymatrix = NULL;
3792 	   SCIP_Bool* implnodes = NULL;
3793 	   SCIP_VAR** implvars = NULL;
3794 	   SCIP_VAR** probvars;
3795 	   int nimplnodes;
3796 	   int nprobvars;
3797 	   int i;
3798 	   int j;
3799 	
3800 	   assert( scip != NULL );
3801 	   assert( conshdlrdata != NULL );
3802 	   assert( conflictgraph != NULL );
3803 	   assert( conshdlrdata->implgraph == NULL );
3804 	   assert( conshdlrdata->nimplnodes == 0 );
3805 	   assert( cutoff != NULL );
3806 	   assert( nchgbds != NULL );
3807 	
3808 	   *nchgbds = 0;
3809 	   *cutoff = FALSE;
3810 	
3811 	   /* we do not create the adjacency matrix of the conflict graph if the number of SOS1 variables is larger than a predefined value */
3812 	   if ( conshdlrdata->maxsosadjacency != -1 && nsos1vars > conshdlrdata->maxsosadjacency )
3813 	   {
3814 	      *success = FALSE;
3815 	      SCIPdebugMsg(scip, "Implication graph was not created since number of SOS1 variables (%d) is larger than %d.\n", nsos1vars, conshdlrdata->maxsosadjacency);
3816 	
3817 	      return SCIP_OKAY;
3818 	   }
3819 	   *success = TRUE;
3820 	
3821 	   /* only add globally valid implications to implication graph */
3822 	   assert ( SCIPgetDepth(scip) == 0 );
3823 	
3824 	   probvars = SCIPgetVars(scip);
3825 	   nprobvars = SCIPgetNVars(scip);
3826 	   nimplnodes = 0;
3827 	
3828 	   /* create implication graph */
3829 	   SCIP_CALL( SCIPcreateDigraph(scip, &conshdlrdata->implgraph, nsos1vars + nprobvars) );
3830 	
3831 	   /* create hashmap */
3832 	   SCIP_CALL( SCIPhashmapCreate(&implhash, SCIPblkmem(scip), nsos1vars + nprobvars) );
3833 	
3834 	   /* determine implvars (union of SOS1 and problem variables)
3835 	    * Note: For separation of implied bound cuts it is important that SOS1 variables are enumerated first
3836 	    */
3837 	   SCIP_CALL( SCIPallocBufferArray(scip, &implvars, nsos1vars + nprobvars) );
3838 	   for (i = 0; i < nsos1vars; ++i)
3839 	   {
3840 	      SCIP_VAR* var;
3841 	      var = SCIPnodeGetVarSOS1(conflictgraph, i);
3842 	
3843 	      /* insert node number to hash map */
3844 	      assert( ! SCIPhashmapExists(implhash, var) );
3845 	      SCIP_CALL( SCIPhashmapInsertInt(implhash, var, nimplnodes) );
3846 	      assert( nimplnodes == SCIPhashmapGetImageInt(implhash, var) );
3847 	      implvars[nimplnodes++] = var;
3848 	   }
3849 	
3850 	   for (i = 0; i < nprobvars; ++i)
3851 	   {
3852 	      SCIP_VAR* var;
3853 	      var = probvars[i];
3854 	
3855 	      /* insert node number to hash map if not existent */
3856 	      if ( ! SCIPhashmapExists(implhash, var) )
3857 	      {
3858 	         SCIP_CALL( SCIPhashmapInsertInt(implhash, var, nimplnodes) );
3859 	         assert( nimplnodes == SCIPhashmapGetImageInt(implhash, var) );
3860 	         implvars[nimplnodes++] = var;
3861 	      }
3862 	   }
3863 	   conshdlrdata->nimplnodes = nimplnodes;
3864 	
3865 	   /* add variables to nodes of implication graph */
3866 	   for (i = 0; i < nimplnodes; ++i)
3867 	   {
3868 	      SCIP_NODEDATA* nodedata = NULL;
3869 	
3870 	      /* create node data */
3871 	      SCIP_CALL( SCIPallocBlockMemory(scip, &nodedata) );
3872 	      nodedata->var = implvars[i];
3873 	
3874 	      /* set node data */
3875 	      SCIPdigraphSetNodeData(conshdlrdata->implgraph, (void*) nodedata, i);
3876 	   }
3877 	
3878 	   /* allocate buffer arrays */
3879 	   SCIP_CALL( SCIPallocBufferArray(scip, &implnodes, nsos1vars) );
3880 	   SCIP_CALL( SCIPallocBufferArray(scip, &adjacencymatrix, nsos1vars) );
3881 	
3882 	   for (i = 0; i < nsos1vars; ++i)
3883 	      SCIP_CALL( SCIPallocBufferArray(scip, &adjacencymatrix[i], i+1) ); /*lint !e866*/
3884 	
3885 	   /* create adjacency matrix */
3886 	   for (i = 0; i < nsos1vars; ++i)
3887 	   {
3888 	      for (j = 0; j < i+1; ++j)
3889 	         adjacencymatrix[i][j] = 0;
3890 	   }
3891 	
3892 	   for (i = 0; i < nsos1vars; ++i)
3893 	   {
3894 	      int* succ;
3895 	      int nsucc;
3896 	      succ = SCIPdigraphGetSuccessors(conflictgraph, i);
3897 	      nsucc = SCIPdigraphGetNSuccessors(conflictgraph, i);
3898 	
3899 	      for (j = 0; j < nsucc; ++j)
3900 	      {
3901 	         if ( i > succ[j] )
3902 	            adjacencymatrix[i][succ[j]] = 1;
3903 	      }
3904 	   }
3905 	
3906 	   assert( SCIPgetDepth(scip) == 0 );
3907 	
3908 	   /* compute SOS1 implications from linear constraints and tighten bounds of variables */
3909 	   for (j = 0; (j < maxrounds || maxrounds == -1 ); ++j)
3910 	   {
3911 	      SCIP_Bool implupdate;
3912 	      int nchgbdssave;
3913 	
3914 	      nchgbdssave = *nchgbds;
3915 	
3916 	      assert( nimplnodes > 0 );
3917 	      SCIP_CALL( tightenVarsBoundsSOS1(scip, conshdlrdata, conflictgraph, conshdlrdata->implgraph, implhash, adjacencymatrix, implvars, nimplnodes, nsos1vars, nchgbds, &implupdate, cutoff) );
3918 	      if ( *cutoff || ( ! implupdate && ! ( *nchgbds > nchgbdssave ) ) )
3919 	         break;
3920 	   }
3921 	
3922 	   /* free memory */
3923 	   for (i = nsos1vars-1; i >= 0; --i)
3924 	      SCIPfreeBufferArrayNull(scip, &adjacencymatrix[i]);
3925 	   SCIPfreeBufferArrayNull(scip, &adjacencymatrix);
3926 	   SCIPfreeBufferArrayNull(scip, &implnodes);
3927 	   SCIPfreeBufferArrayNull(scip, &implvars);
3928 	   SCIPhashmapFree(&implhash);
3929 	
3930 	#ifdef SCIP_DEBUG
3931 	   /* evaluate results */
3932 	   if ( cutoff )
3933 	   {
3934 	      SCIPdebugMsg(scip, "cutoff \n");
3935 	   }
3936 	   else if ( *nchgbds > 0 )
3937 	   {
3938 	      SCIPdebugMsg(scip, "found %d bound changes\n", *nchgbds);
3939 	   }
3940 	#endif
3941 	
3942 	   assert( conshdlrdata->implgraph != NULL );
3943 	
3944 	   return SCIP_OKAY;
3945 	}
3946 	
3947 	
3948 	/** deinitialize implication graph */
3949 	static
3950 	SCIP_RETCODE freeImplGraphSOS1(
3951 	   SCIP*                 scip,               /**< SCIP pointer */
3952 	   SCIP_CONSHDLRDATA*    conshdlrdata        /**< constraint handler data */
3953 	   )
3954 	{
3955 	   int j;
3956 	
3957 	   assert( scip != NULL );
3958 	   assert( conshdlrdata != NULL );
3959 	
3960 	   /* free whole memory of implication graph */
3961 	   if ( conshdlrdata->implgraph == NULL )
3962 	   {
3963 	      assert( conshdlrdata->nimplnodes == 0 );
3964 	      return SCIP_OKAY;
3965 	   }
3966 	
3967 	   /* free arc data */
3968 	   for (j = conshdlrdata->nimplnodes-1; j >= 0; --j)
3969 	   {
3970 	      SCIP_SUCCDATA** succdatas;
3971 	      int nsucc;
3972 	      int s;
3973 	
3974 	      succdatas = (SCIP_SUCCDATA**) SCIPdigraphGetSuccessorsData(conshdlrdata->implgraph, j);
3975 	      nsucc = SCIPdigraphGetNSuccessors(conshdlrdata->implgraph, j);
3976 	
3977 	      for (s = nsucc-1; s >= 0; --s)
3978 	      {
3979 	         assert( succdatas[s] != NULL );
3980 	         SCIPfreeBlockMemory(scip, &succdatas[s]);/*lint !e866*/
3981 	      }
3982 	   }
3983 	
3984 	   /* free node data */
3985 	   for (j = conshdlrdata->nimplnodes-1; j >= 0; --j)
3986 	   {
3987 	      SCIP_NODEDATA* nodedata;
3988 	      nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conshdlrdata->implgraph, j);
3989 	      assert( nodedata != NULL );
3990 	      SCIPfreeBlockMemory(scip, &nodedata);
3991 	      SCIPdigraphSetNodeData(conshdlrdata->implgraph, NULL, j);
3992 	   }
3993 	
3994 	   /* free implication graph */
3995 	   SCIPdigraphFree(&conshdlrdata->implgraph);
3996 	   conshdlrdata->nimplnodes = 0;
3997 	
3998 	   return SCIP_OKAY;
3999 	}
4000 	
4001 	
4002 	/* ----------------------------- branching -------------------------------------*/
4003 	
4004 	/** get the vertices whose neighbor set covers a subset of the neighbor set of a given other vertex.
4005 	 *
4006 	 *  This function can be used to compute sets of variables to branch on.
4007 	 */
4008 	static
4009 	SCIP_RETCODE getCoverVertices(
4010 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
4011 	   SCIP_Bool*            verticesarefixed,   /**< array that indicates which variables are currently fixed to zero */
4012 	   int                   vertex,             /**< vertex (-1 if not needed) */
4013 	   int*                  neightocover,       /**< neighbors of given vertex to be covered (or NULL if all neighbors shall be covered) */
4014 	   int                   nneightocover,      /**< number of entries of neightocover (or 0 if all neighbors shall be covered )*/
4015 	   int*                  coververtices,      /**< array to store the vertices whose neighbor set covers the neighbor set of the given vertex */
4016 	   int*                  ncoververtices      /**< pointer to store size of coververtices */
4017 	   )
4018 	{
4019 	   int* succ1;
4020 	   int nsucc1;
4021 	   int s;
4022 	
4023 	   assert( conflictgraph != NULL );
4024 	   assert( verticesarefixed != NULL );
4025 	   assert( coververtices != NULL );
4026 	   assert( ncoververtices != NULL );
4027 	
4028 	   *ncoververtices = 0;
4029 	
4030 	   /* if all the neighbors shall be covered */
4031 	   if ( neightocover == NULL )
4032 	   {
4033 	      assert( nneightocover == 0 );
4034 	      nsucc1 = SCIPdigraphGetNSuccessors(conflictgraph, vertex);
4035 	      succ1 = SCIPdigraphGetSuccessors(conflictgraph, vertex);
4036 	   }
4037 	   else
4038 	   {
4039 	      nsucc1 = nneightocover;
4040 	      succ1 = neightocover;
4041 	   }
4042 	
4043 	   /* determine all the successors of the first unfixed successor */
4044 	   for (s = 0; s < nsucc1; ++s)
4045 	   {
4046 	      int succvertex1 = succ1[s];
4047 	
4048 	      if ( ! verticesarefixed[succvertex1] )
4049 	      {
4050 	         int succvertex2;
4051 	         int* succ2;
4052 	         int nsucc2;
4053 	         int j;
4054 	
4055 	         nsucc2 = SCIPdigraphGetNSuccessors(conflictgraph, succvertex1);
4056 	         succ2 = SCIPdigraphGetSuccessors(conflictgraph, succvertex1);
4057 	
4058 	         /* for the first unfixed vertex */
4059 	         if ( *ncoververtices == 0 )
4060 	         {
4061 	            for (j = 0; j < nsucc2; ++j)
4062 	            {
4063 	               succvertex2 = succ2[j];
4064 	               if ( ! verticesarefixed[succvertex2] )
4065 	                  coververtices[(*ncoververtices)++] = succvertex2;
4066 	            }
4067 	         }
4068 	         else
4069 	         {
4070 	            int vv = 0;
4071 	            int k = 0;
4072 	            int v;
4073 	
4074 	            /* determine all the successors that are in the set "coververtices" */
4075 	            for (v = 0; v < *ncoververtices; ++v)
4076 	            {
4077 	               assert( vv <= v );
4078 	               for (j = k; j < nsucc2; ++j)
4079 	               {
4080 	                  succvertex2 = succ2[j];
4081 	                  if ( succvertex2 > coververtices[v] )
4082 	                  {
4083 	                     /* coververtices[v] does not appear in succ2 list, go to next vertex in coververtices */
4084 	                     k = j;
4085 	                     break;
4086 	                  }
4087 	                  else if ( succvertex2 == coververtices[v] )
4088 	                  {
4089 	                     /* vertices are equal, copy to free position vv */
4090 	                     coververtices[vv++] = succvertex2;
4091 	                     k = j + 1;
4092 	                     break;
4093 	                  }
4094 	               }
4095 	            }
4096 	            /* store new size of coververtices */
4097 	            *ncoververtices = vv;
4098 	         }
4099 	      }
4100 	   }
4101 	
4102 	#ifdef SCIP_DEBUG
4103 	   /* check sorting */
4104 	   for (s = 0; s < *ncoververtices; ++s)
4105 	   {
4106 	      assert( *ncoververtices <= 1 || coververtices[*ncoververtices - 1] > coververtices[*ncoververtices - 2] );
4107 	   }
4108 	#endif
4109 	
4110 	   return SCIP_OKAY;
4111 	}
4112 	
4113 	
4114 	/** get vertices of variables that will be fixed to zero for each node */
4115 	static
4116 	SCIP_RETCODE getBranchingVerticesSOS1(
4117 	   SCIP*                 scip,               /**< SCIP pointer */
4118 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
4119 	   SCIP_SOL*             sol,                /**< solution to be enforced (NULL for LP solution) */
4120 	   SCIP_Bool*            verticesarefixed,   /**< vector that indicates which variables are currently fixed to zero */
4121 	   SCIP_Bool             bipbranch,          /**< TRUE if bipartite branching method should be used */
4122 	   int                   branchvertex,       /**< branching vertex */
4123 	   int*                  fixingsnode1,       /**< vertices of variables that will be fixed to zero for the first node */
4124 	   int*                  nfixingsnode1,      /**< pointer to store number of fixed variables for the first node */
4125 	   int*                  fixingsnode2,       /**< vertices of variables that will be fixed to zero for the second node */
4126 	   int*                  nfixingsnode2       /**< pointer to store number of fixed variables for the second node */
4127 	   )
4128 	{
4129 	   SCIP_Bool takeallsucc; /* whether to set fixingsnode1 = neighbors of 'branchvertex' in the conflict graph */
4130 	   int* succ;
4131 	   int nsucc;
4132 	   int j;
4133 	
4134 	   assert( scip != NULL );
4135 	   assert( conflictgraph != NULL );
4136 	   assert( verticesarefixed != NULL );
4137 	   assert( ! verticesarefixed[branchvertex] );
4138 	   assert( fixingsnode1 != NULL );
4139 	   assert( fixingsnode2 != NULL );
4140 	   assert( nfixingsnode1 != NULL );
4141 	   assert( nfixingsnode2 != NULL );
4142 	
4143 	   *nfixingsnode1 = 0;
4144 	   *nfixingsnode2 = 0;
4145 	   takeallsucc = TRUE;
4146 	
4147 	   /* get successors and number of successors of branching vertex */
4148 	   nsucc = SCIPdigraphGetNSuccessors(conflictgraph, branchvertex);
4149 	   succ = SCIPdigraphGetSuccessors(conflictgraph, branchvertex);
4150 	
4151 	   /* if bipartite branching method is turned on */
4152 	   if ( bipbranch )
4153 	   {
4154 	      SCIP_Real solval;
4155 	      int cnt = 0;
4156 	
4157 	      /* get all the neighbors of the variable with index 'branchvertex' whose solution value is nonzero */
4158 	      for (j = 0; j < nsucc; ++j)
4159 	      {
4160 	         if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, SCIPnodeGetVarSOS1(conflictgraph, succ[j]))) )
4161 	         {
4162 	            assert( ! verticesarefixed[succ[j]] );
4163 	            fixingsnode1[(*nfixingsnode1)++] = succ[j];
4164 	         }
4165 	      }
4166 	
4167 	      /* if one of the sets fixingsnode1 or fixingsnode2 contains only one variable with a nonzero LP value we perform standard neighborhood branching */
4168 	      if ( *nfixingsnode1 > 0 )
4169 	      {
4170 	         /* get the vertices whose neighbor set cover the selected subset of the neighbors of the given branching vertex */
4171 	         SCIP_CALL( getCoverVertices(conflictgraph, verticesarefixed, branchvertex, fixingsnode1, *nfixingsnode1, fixingsnode2, nfixingsnode2) );
4172 	
4173 	         /* determine the intersection of the neighbors of branchvertex with the intersection of all the neighbors of fixingsnode2 */
4174 	         SCIP_CALL( getCoverVertices(conflictgraph, verticesarefixed, branchvertex, fixingsnode2, *nfixingsnode2, fixingsnode1, nfixingsnode1) );
4175 	
4176 	         for (j = 0; j < *nfixingsnode2; ++j)
4177 	         {
4178 	            solval = SCIPgetSolVal(scip, sol, SCIPnodeGetVarSOS1(conflictgraph, fixingsnode2[j]));
4179 	            if( ! SCIPisFeasZero(scip, solval) )
4180 	               ++cnt;
4181 	         }
4182 	
4183 	         /* we decide whether to use all successors if one partition of complete bipartite subgraph has only one node */
4184 	         if ( cnt >= 2 )
4185 	         {
4186 	            cnt = 0;
4187 	            for (j = 0; j < *nfixingsnode1; ++j)
4188 	            {
4189 	               solval = SCIPgetSolVal(scip, sol, SCIPnodeGetVarSOS1(conflictgraph, fixingsnode1[j]));
4190 	               if( ! SCIPisFeasZero(scip, solval) )
4191 	                  ++cnt;
4192 	            }
4193 	
4194 	            if ( cnt >= 2 )
4195 	               takeallsucc = FALSE;
4196 	         }
4197 	      }
4198 	   }
4199 	
4200 	   if ( takeallsucc )
4201 	   {
4202 	      /* get all the unfixed neighbors of the branching vertex */
4203 	      *nfixingsnode1 = 0;
4204 	      for (j = 0; j < nsucc; ++j)
4205 	      {
4206 	         if ( ! verticesarefixed[succ[j]] )
4207 	            fixingsnode1[(*nfixingsnode1)++] = succ[j];
4208 	      }
4209 	
4210 	      if ( bipbranch )
4211 	      {
4212 	         /* get the vertices whose neighbor set covers the neighbor set of a given branching vertex */
4213 	         SCIP_CALL( getCoverVertices(conflictgraph, verticesarefixed, branchvertex, fixingsnode1, *nfixingsnode1, fixingsnode2, nfixingsnode2) );
4214 	      }
4215 	      else
4216 	      {
4217 	         /* use neighborhood branching, i.e, for the second node only the branching vertex can be fixed */
4218 	         fixingsnode2[0] = branchvertex;
4219 	         *nfixingsnode2 = 1;
4220 	      }
4221 	   }
4222 	
4223 	   return SCIP_OKAY;
4224 	}
4225 	
4226 	
4227 	/** gets branching priorities for SOS1 variables and applies 'most infeasible selection' rule to determine a vertex for the next branching decision */
4228 	static
4229 	SCIP_RETCODE getBranchingPrioritiesSOS1(
4230 	   SCIP*                 scip,               /**< SCIP pointer */
4231 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
4232 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
4233 	   SCIP_SOL*             sol,                /**< solution to be enforced (NULL for LP solution) */
4234 	   int                   nsos1vars,          /**< number of SOS1 variables */
4235 	   SCIP_Bool*            verticesarefixed,   /**< vector that indicates which variables are currently fixed to zero */
4236 	   SCIP_Bool             bipbranch,          /**< TRUE if bipartite branching method should be used */
4237 	   int*                  fixingsnode1,       /**< vertices of variables that will be fixed to zero for the first node (size = nsos1vars) */
4238 	   int*                  fixingsnode2,       /**< vertices of variables that will be fixed to zero for the second node (size = nsos1vars) */
4239 	   SCIP_Real*            branchpriors,       /**< pointer to store branching priorities (size = nsos1vars) or NULL if not needed */
4240 	   int*                  vertexbestprior,    /**< pointer to store vertex with the best branching priority or NULL if not needed */
4241 	   SCIP_Bool*            relsolfeas          /**< pointer to store if LP relaxation solution is feasible */
4242 	   )
4243 	{
4244 	   SCIP_Real bestprior;
4245 	   int i;
4246 	
4247 	   assert( scip != NULL );
4248 	   assert( conshdlrdata != NULL );
4249 	   assert( conflictgraph != NULL );
4250 	   assert( verticesarefixed != NULL );
4251 	   assert( fixingsnode1 != NULL );
4252 	   assert( fixingsnode2 != NULL );
4253 	   assert( relsolfeas != NULL );
4254 	
4255 	   bestprior = -SCIPinfinity(scip);
4256 	
4257 	   /* make sure data is initialized */
4258 	   if ( vertexbestprior != NULL )
4259 	      *vertexbestprior = -1;
4260 	
4261 	   for (i = 0; i < nsos1vars; ++i)
4262 	   {
4263 	      SCIP_Real prior;
4264 	      SCIP_Real solval;
4265 	      int nfixingsnode1;
4266 	      int nfixingsnode2;
4267 	      int nsucc;
4268 	      int j;
4269 	
4270 	      nsucc = SCIPdigraphGetNSuccessors(conflictgraph, i);
4271 	
4272 	      if ( nsucc == 0 || SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, SCIPnodeGetVarSOS1(conflictgraph, i))) || verticesarefixed[i] )
4273 	         prior = -SCIPinfinity(scip);
4274 	      else
4275 	      {
4276 	         SCIP_Bool iszero1 = TRUE;
4277 	         SCIP_Bool iszero2 = TRUE;
4278 	         SCIP_Real sum1 = 0.0;
4279 	         SCIP_Real sum2 = 0.0;
4280 	
4281 	         /* get vertices of variables that will be fixed to zero for each strong branching execution */
4282 	         assert( ! verticesarefixed[i] );
4283 	         SCIP_CALL( getBranchingVerticesSOS1(scip, conflictgraph, sol, verticesarefixed, bipbranch, i, fixingsnode1, &nfixingsnode1, fixingsnode2, &nfixingsnode2) );
4284 	
4285 	         for (j = 0; j < nfixingsnode1; ++j)
4286 	         {
4287 	            solval = SCIPgetSolVal(scip, sol, SCIPnodeGetVarSOS1(conflictgraph, fixingsnode1[j]));
4288 	            if ( ! SCIPisFeasZero(scip, solval) )
4289 	            {
4290 	               sum1 += REALABS( solval );
4291 	               iszero1 = FALSE;
4292 	            }
4293 	         }
4294 	
4295 	         for (j = 0; j < nfixingsnode2; ++j)
4296 	         {
4297 	            solval = SCIPgetSolVal(scip, sol, SCIPnodeGetVarSOS1(conflictgraph, fixingsnode2[j]));
4298 	            if ( ! SCIPisFeasZero(scip, solval) )
4299 	            {
4300 	               sum2 += REALABS( solval );
4301 	               iszero2 = FALSE;
4302 	            }
4303 	         }
4304 	
4305 	         if ( iszero1 || iszero2 )
4306 	            prior = -SCIPinfinity(scip);
4307 	         else
4308 	            prior = sum1 * sum2;
4309 	      }
4310 	
4311 	      if ( branchpriors != NULL )
4312 	         branchpriors[i] = prior;
4313 	      if ( bestprior < prior )
4314 	      {
4315 	         bestprior = prior;
4316 	
4317 	         if ( vertexbestprior != NULL )
4318 	            *vertexbestprior = i;
4319 	      }
4320 	   }
4321 	
4322 	   if ( SCIPisInfinity(scip, -bestprior) )
4323 	      *relsolfeas = TRUE;
4324 	   else
4325 	      *relsolfeas = FALSE;
4326 	
4327 	   return SCIP_OKAY;
4328 	}
4329 	
4330 	
4331 	/** performs strong branching with given domain fixings */
4332 	static
4333 	SCIP_RETCODE performStrongbranchSOS1(
4334 	   SCIP*                 scip,               /**< SCIP pointer */
4335 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
4336 	   int*                  fixingsexec,        /**< vertices of variables to be fixed to zero for this strong branching execution */
4337 	   int                   nfixingsexec,       /**< number of vertices of variables to be fixed to zero for this strong branching execution */
4338 	   int*                  fixingsop,          /**< vertices of variables to be fixed to zero for the opposite strong branching execution */
4339 	   int                   nfixingsop,         /**< number of vertices of variables to be fixed to zero for the opposite strong branching execution */
4340 	   int                   inititer,           /**< maximal number of LP iterations to perform */
4341 	   SCIP_Bool             fixnonzero,         /**< shall opposite variable (if positive in sign) fixed to the feasibility tolerance
4342 	                                              *   (only possible if nfixingsop = 1) */
4343 	   int*                  domainfixings,      /**< vertices that can be used to reduce the domain (should have size equal to number of variables) */
4344 	   int*                  ndomainfixings,     /**< pointer to store number of vertices that can be used to reduce the domain, could be filled by earlier calls */
4345 	   SCIP_Bool*            infeasible,         /**< pointer to store whether branch is infeasible */
4346 	   SCIP_Real*            objval,             /**< pointer to store objective value of LP with fixed variables (SCIP_INVALID if reddomain = TRUE or lperror = TRUE) */
4347 	   SCIP_Bool*            lperror             /**< pointer to store whether an unresolved LP error or a strange solution status occurred */
4348 	   )
4349 	{
4350 	   SCIP_LPSOLSTAT solstat;
4351 	   int i;
4352 	
4353 	   assert( scip != NULL );
4354 	   assert( conflictgraph != NULL );
4355 	   assert( fixingsexec != NULL );
4356 	   assert( nfixingsop > 0 );
4357 	   assert( fixingsop != NULL );
4358 	   assert( nfixingsop > 0 );
4359 	   assert( inititer >= -1 );
4360 	   assert( domainfixings != NULL );
4361 	   assert( ndomainfixings != NULL );
4362 	   assert( *ndomainfixings >= 0 );
4363 	   assert( infeasible != NULL );
4364 	   assert( objval != NULL );
4365 	   assert( lperror != NULL );
4366 	
4367 	   *objval = SCIP_INVALID; /* for debugging */
4368 	   *lperror = FALSE;
4369 	   *infeasible = FALSE;
4370 	
4371 	   /* start probing */
4372 	   SCIP_CALL( SCIPstartProbing(scip) );
4373 	
4374 	   /* perform domain fixings */
4375 	   if ( fixnonzero && nfixingsop == 1 )
4376 	   {
4377 	      SCIP_VAR* var;
4378 	      SCIP_Real lb;
4379 	      SCIP_Real ub;
4380 	
4381 	      var = SCIPnodeGetVarSOS1(conflictgraph, fixingsop[0]);
4382 	      lb = SCIPvarGetLbLocal(var);
4383 	      ub = SCIPvarGetUbLocal(var);
4384 	
4385 	      if ( SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
4386 	      {
4387 	         if ( SCIPisZero(scip, lb) )
4388 	         {
4389 	            /* fix variable to some very small, but positive number or to 1.0 if variable is integral */
4390 	            if (SCIPvarIsIntegral(var) )
4391 	            {
4392 	               SCIP_CALL( SCIPchgVarLbProbing(scip, var, 1.0) );
4393 	            }
4394 	            else
4395 	            {
4396 	               SCIP_CALL( SCIPchgVarLbProbing(scip, var, 1.5 * SCIPfeastol(scip)) );
4397 	            }
4398 	         }
4399 	         else if ( SCIPisZero(scip, ub) )
4400 	         {
4401 	            /* fix variable to some negative number with small absolute value or to -1.0 if variable is integral */
4402 	            if (SCIPvarIsIntegral(var) )
4403 	            {
4404 	               SCIP_CALL( SCIPchgVarUbProbing(scip, var, -1.0) );
4405 	            }
4406 	            else
4407 	            {
4408 	               SCIP_CALL( SCIPchgVarUbProbing(scip, var, -1.5 * SCIPfeastol(scip)) );
4409 	            }
4410 	         }
4411 	      }
4412 	   }
4413 	
4414 	   /* injects variable fixings into current probing node */
4415 	   for (i = 0; i < nfixingsexec && ! *infeasible; ++i)
4416 	   {
4417 	      SCIP_VAR* var;
4418 	
4419 	      var = SCIPnodeGetVarSOS1(conflictgraph, fixingsexec[i]);
4420 	      if ( SCIPisFeasGT(scip, SCIPvarGetLbLocal(var), 0.0) || SCIPisFeasLT(scip, SCIPvarGetUbLocal(var), 0.0) )
4421 	         *infeasible = TRUE;
4422 	      else
4423 	      {
4424 	         SCIP_CALL( SCIPfixVarProbing(scip, var, 0.0) );
4425 	      }
4426 	   }
4427 	
4428 	   /* apply domain propagation */
4429 	   if ( ! *infeasible )
4430 	   {
4431 	      SCIP_CALL( SCIPpropagateProbing(scip, 0, infeasible, NULL) );
4432 	   }
4433 	
4434 	   if ( *infeasible )
4435 	      solstat = SCIP_LPSOLSTAT_INFEASIBLE;
4436 	   else
4437 	   {
4438 	      /* solve the probing LP */
4439 	      SCIP_CALL( SCIPsolveProbingLP(scip, inititer, lperror, NULL) );
4440 	      if ( *lperror )
4441 	      {
4442 	         SCIP_CALL( SCIPendProbing(scip) );
4443 	         return SCIP_OKAY;
4444 	      }
4445 	
4446 	      /* get solution status */
4447 	      solstat = SCIPgetLPSolstat(scip);
4448 	   }
4449 	
4450 	   /* if objective limit was reached, then the domain can be reduced */
4451 	   if ( solstat == SCIP_LPSOLSTAT_OBJLIMIT || solstat == SCIP_LPSOLSTAT_INFEASIBLE )
4452 	   {
4453 	      *infeasible = TRUE;
4454 	
4455 	      for (i = 0; i < nfixingsop; ++i)
4456 	         domainfixings[(*ndomainfixings)++] = fixingsop[i];
4457 	   }
4458 	   else if ( solstat == SCIP_LPSOLSTAT_OPTIMAL || solstat == SCIP_LPSOLSTAT_TIMELIMIT || solstat == SCIP_LPSOLSTAT_ITERLIMIT )
4459 	   {
4460 	      /* get objective value of probing LP */
4461 	      *objval = SCIPgetLPObjval(scip);
4462 	   }
4463 	   else
4464 	      *lperror = TRUE;
4465 	
4466 	   /* end probing */
4467 	   SCIP_CALL( SCIPendProbing(scip) );
4468 	
4469 	   return SCIP_OKAY;
4470 	}
4471 	
4472 	
4473 	/** apply strong branching to determine the vertex for the next branching decision */
4474 	static
4475 	SCIP_RETCODE getBranchingDecisionStrongbranchSOS1(
4476 	   SCIP*                 scip,               /**< SCIP pointer */
4477 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< SOS1 constraint handler data */
4478 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
4479 	   SCIP_SOL*             sol,                /**< solution to be enforced (NULL for LP solution) */
4480 	   int                   nsos1vars,          /**< number of SOS1 variables */
4481 	   SCIP_Real             lpobjval,           /**< current LP relaxation solution */
4482 	   SCIP_Bool             bipbranch,          /**< TRUE if bipartite branching method should be used */
4483 	   int                   nstrongrounds,      /**< number of strong branching rounds */
4484 	   SCIP_Bool*            verticesarefixed,   /**< vector that indicates which variables are currently fixed to zero */
4485 	   int*                  fixingsnode1,       /**< pointer to store vertices of variables that will be fixed to zero for the first node (size = nsos1vars) */
4486 	   int*                  fixingsnode2,       /**< pointer to store vertices of variables that will be fixed to zero for the second node (size = nsos1vars) */
4487 	   int*                  vertexbestprior,    /**< pointer to store vertex with the best strong branching priority */
4488 	   SCIP_Real*            bestobjval1,        /**< pointer to store LP objective for left child node of branching decision with best priority */
4489 	   SCIP_Real*            bestobjval2,        /**< pointer to store LP objective for right child node of branching decision with best priority */
4490 	   SCIP_RESULT*          result              /**< pointer to store result of strong branching */
4491 	   )
4492 	{
4493 	   SCIP_Real* branchpriors = NULL;
4494 	   int* indsos1vars = NULL;
4495 	   int* domainfixings = NULL;
4496 	   int ndomainfixings;
4497 	   int nfixingsnode1;
4498 	   int nfixingsnode2;
4499 	
4500 	   SCIP_Bool relsolfeas;
4501 	   SCIP_Real bestscore;
4502 	   int lastscorechange;
4503 	   int maxfailures;
4504 	
4505 	   SCIP_Longint nlpiterations;
4506 	   SCIP_Longint nlps;
4507 	   int inititer;
4508 	   int j;
4509 	   int i;
4510 	
4511 	   assert( scip != NULL );
4512 	   assert( conshdlrdata != NULL );
4513 	   assert( conflictgraph != NULL );
4514 	   assert( verticesarefixed != NULL );
4515 	   assert( fixingsnode1 != NULL );
4516 	   assert( fixingsnode2 != NULL );
4517 	   assert( vertexbestprior != NULL );
4518 	   assert( result != NULL );
4519 	
4520 	   /* allocate buffer arrays */
4521 	   SCIP_CALL( SCIPallocBufferArray(scip, &branchpriors, nsos1vars) );
4522 	
4523 	   /* get branching priorities */
4524 	   SCIP_CALL( getBranchingPrioritiesSOS1(scip, conshdlrdata, conflictgraph, sol, nsos1vars, verticesarefixed,
4525 	         bipbranch, fixingsnode1, fixingsnode2, branchpriors, NULL, &relsolfeas) );
4526 	
4527 	   /* if LP relaxation solution is feasible */
4528 	   if ( relsolfeas )
4529 	   {
4530 	      SCIPdebugMsg(scip, "all the SOS1 constraints are feasible.\n");
4531 	      *vertexbestprior = -1;
4532 	      *result = SCIP_FEASIBLE;
4533 	
4534 	      /* free memory */
4535 	      SCIPfreeBufferArrayNull(scip, &branchpriors);
4536 	
4537 	      return SCIP_OKAY;
4538 	   }
4539 	
4540 	   /* allocate buffer arrays */
4541 	   SCIP_CALL( SCIPallocBufferArray(scip, &indsos1vars, nsos1vars) );
4542 	   SCIP_CALL( SCIPallocBufferArray(scip, &domainfixings, nsos1vars) );
4543 	
4544 	   /* sort branching priorities (descending order) */
4545 	   for (j = 0; j < nsos1vars; ++j)
4546 	      indsos1vars[j] = j;
4547 	   SCIPsortDownRealInt(branchpriors, indsos1vars, nsos1vars);
4548 	
4549 	   /* determine the number of LP iterations to perform in each strong branch */
4550 	   nlpiterations =  SCIPgetNDualResolveLPIterations(scip);
4551 	   nlps = SCIPgetNDualResolveLPs(scip);
4552 	   if ( nlps == 0 )
4553 	   {
4554 	      nlpiterations = SCIPgetNNodeInitLPIterations(scip);
4555 	      nlps = SCIPgetNNodeInitLPs(scip);
4556 	      if ( nlps == 0 )
4557 	      {
4558 	         nlpiterations = 1000;
4559 	         nlps = 1;
4560 	      }
4561 	   }
4562 	   assert(nlps >= 1);
4563 	
4564 	   /* compute number of LP iterations performed per strong branching iteration */
4565 	   if ( conshdlrdata->nstrongiter == -2 )
4566 	   {
4567 	      inititer = (int)(2*nlpiterations / nlps);
4568 	      inititer = (int)((SCIP_Real)inititer * (1.0 + 20.0/SCIPgetNNodes(scip)));
4569 	      inititer = MAX(inititer, 10);
4570 	      inititer = MIN(inititer, 500);
4571 	   }
4572 	   else
4573 	      inititer = conshdlrdata->nstrongiter;
4574 	
4575 	   /* get current LP relaxation solution */
4576 	   lpobjval = SCIPgetLPObjval(scip);
4577 	
4578 	   /* determine branching variable by strong branching or reduce domain */
4579 	   ndomainfixings = 0;
4580 	   lastscorechange = -1;
4581 	   assert( nsos1vars > 0 );
4582 	   *vertexbestprior = indsos1vars[0]; /* for the case that nstrongrounds = 0 */
4583 	   bestscore = -SCIPinfinity(scip);
4584 	   *bestobjval1 = -SCIPinfinity(scip);
4585 	   *bestobjval2 = -SCIPinfinity(scip);
4586 	   maxfailures = nstrongrounds;
4587 	
4588 	   /* for each strong branching round */
4589 	   for (j = 0; j < nstrongrounds; ++j)
4590 	   {
4591 	      int testvertex;
4592 	
4593 	      /* get branching vertex for the current strong branching iteration */
4594 	      testvertex = indsos1vars[j];
4595 	
4596 	      /* if variable with index 'vertex' does not violate any complementarity in its neighborhood for the current LP relaxation solution */
4597 	      if ( SCIPisPositive(scip, branchpriors[j]) )
4598 	      {
4599 	         SCIP_Bool infeasible1;
4600 	         SCIP_Bool infeasible2;
4601 	         SCIP_Bool lperror;
4602 	         SCIP_Real objval1;
4603 	         SCIP_Real objval2;
4604 	         SCIP_Real score;
4605 	
4606 	         /* get vertices of variables that will be fixed to zero for each strong branching execution */
4607 	         assert( ! verticesarefixed[testvertex] );
4608 	         SCIP_CALL( getBranchingVerticesSOS1(scip, conflictgraph, sol, verticesarefixed, bipbranch, testvertex,
4609 	               fixingsnode1, &nfixingsnode1, fixingsnode2, &nfixingsnode2) );
4610 	
4611 	         /* get information for first strong branching execution */
4612 	         SCIP_CALL( performStrongbranchSOS1(scip, conflictgraph, fixingsnode1, nfixingsnode1, fixingsnode2, nfixingsnode2,
4613 	               inititer, conshdlrdata->fixnonzero, domainfixings, &ndomainfixings, &infeasible1, &objval1, &lperror) );
4614 	         if ( lperror )
4615 	            continue;
4616 	
4617 	         /* get information for second strong branching execution */
4618 	         SCIP_CALL( performStrongbranchSOS1(scip, conflictgraph, fixingsnode2, nfixingsnode2, fixingsnode1, nfixingsnode1,
4619 	               inititer, FALSE, domainfixings, &ndomainfixings, &infeasible2, &objval2, &lperror) );
4620 	         if ( lperror )
4621 	            continue;
4622 	
4623 	         /* if both subproblems are infeasible */
4624 	         if ( infeasible1 && infeasible2 )
4625 	         {
4626 	            SCIPdebugMsg(scip, "detected cutoff.\n");
4627 	
4628 	            /* update result */
4629 	            *result = SCIP_CUTOFF;
4630 	
4631 	            /* free memory */
4632 	            SCIPfreeBufferArrayNull(scip, &domainfixings);
4633 	            SCIPfreeBufferArrayNull(scip, &indsos1vars);
4634 	            SCIPfreeBufferArrayNull(scip, &branchpriors);
4635 	
4636 	            return SCIP_OKAY;
4637 	         }
4638 	         else if ( ! infeasible1 && ! infeasible2 ) /* both subproblems are feasible */
4639 	         {
4640 	            /* if domain has not been reduced in this for-loop */
4641 	            if ( ndomainfixings == 0 )
4642 	            {
4643 	               score = MAX( REALABS(objval1 - lpobjval), SCIPfeastol(scip) ) * MAX( REALABS(objval2 - lpobjval), SCIPfeastol(scip) );/*lint !e666*/
4644 	
4645 	               if ( SCIPisPositive(scip, score - bestscore) )
4646 	               {
4647 	                  bestscore = score;
4648 	                  *vertexbestprior = testvertex;
4649 	                  *bestobjval1 = objval1;
4650 	                  *bestobjval2 = objval2;
4651 	
4652 	                  lastscorechange = j;
4653 	               }
4654 	               else if ( j - lastscorechange > maxfailures )
4655 	                  break;
4656 	            }
4657 	         }
4658 	      }
4659 	   }
4660 	
4661 	   /* if variable fixings have been detected by probing, then reduce domain */
4662 	   if ( ndomainfixings > 0 )
4663 	   {
4664 	      SCIP_NODE* node = SCIPgetCurrentNode(scip);
4665 	      SCIP_Bool infeasible;
4666 	
4667 	      for (i = 0; i < ndomainfixings; ++i)
4668 	      {
4669 	         SCIP_CALL( fixVariableZeroNode(scip, SCIPnodeGetVarSOS1(conflictgraph, domainfixings[i]), node, &infeasible) );
4670 	         assert( ! infeasible );
4671 	      }
4672 	
4673 	      SCIPdebugMsg(scip, "found %d domain fixings.\n", ndomainfixings);
4674 	
4675 	      /* update result */
4676 	      *result = SCIP_REDUCEDDOM;
4677 	   }
4678 	
4679 	   /* free buffer arrays */
4680 	   SCIPfreeBufferArrayNull(scip, &domainfixings);
4681 	   SCIPfreeBufferArrayNull(scip, &indsos1vars);
4682 	   SCIPfreeBufferArrayNull(scip, &branchpriors);
4683 	
4684 	   return SCIP_OKAY;
4685 	}
4686 	
4687 	
4688 	/** for two given vertices @p v1 and @p v2 search for a clique in the conflict graph that contains these vertices. From
4689 	 *  this clique, we create a bound constraint.
4690 	 */
4691 	static
4692 	SCIP_RETCODE getBoundConsFromVertices(
4693 	   SCIP*                 scip,               /**< SCIP pointer */
4694 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
4695 	   SCIP_SOL*             sol,                /**< solution to be enforced (NULL for LP solution) */
4696 	   int                   v1,                 /**< first vertex that shall be contained in bound constraint */
4697 	   int                   v2,                 /**< second vertex that shall be contained in bound constraint */
4698 	   SCIP_VAR*             boundvar,           /**< bound variable of @p v1 and @p v2 (or NULL if not existent) */
4699 	   SCIP_Bool             extend,             /**< should @p v1 and @p v2 be greedily extended to a clique of larger size */
4700 	   SCIP_CONS*            cons,               /**< bound constraint */
4701 	   SCIP_Real*            feas                /**< feasibility value of bound constraint */
4702 	   )
4703 	{
4704 	   SCIP_NODEDATA* nodedata;
4705 	   SCIP_Bool addv2 = TRUE;
4706 	   SCIP_Real solval;
4707 	   SCIP_VAR* var;
4708 	   SCIP_Real coef = 0.0;
4709 	   int nsucc;
4710 	   int s;
4711 	
4712 	   int* extensions = NULL;
4713 	   int nextensions = 0;
4714 	   int nextensionsnew;
4715 	   int* succ;
4716 	
4717 	   assert( scip != NULL );
4718 	   assert( conflictgraph != NULL );
4719 	   assert( cons != NULL );
4720 	   assert( feas != NULL );
4721 	
4722 	   *feas = 0.0;
4723 	
4724 	   /* add index 'v1' to the clique */
4725 	   nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, v1);
4726 	   var = nodedata->var;
4727 	   assert( boundvar == NULL || SCIPvarCompare(boundvar, nodedata->ubboundvar) == 0 );
4728 	   solval = SCIPgetSolVal(scip, sol, var);
4729 	
4730 	   /* if 'v1' and 'v2' have the same bound variable then the bound cut can be strengthened */
4731 	   if ( boundvar == NULL )
4732 	   {
4733 	      if ( SCIPisFeasPositive(scip, solval) )
4734 	      {
4735 	         SCIP_Real ub;
4736 	         ub = SCIPvarGetUbLocal(var);
4737 	         assert( SCIPisFeasPositive(scip, ub));
4738 	
4739 	         if ( ! SCIPisInfinity(scip, ub) )
4740 	            coef = 1.0/ub;
4741 	      }
4742 	      else if ( SCIPisFeasNegative(scip, solval) )
4743 	      {
4744 	         SCIP_Real lb;
4745 	         lb = SCIPvarGetLbLocal(var);
4746 	         assert( SCIPisFeasNegative(scip, lb) );
4747 	         if ( ! SCIPisInfinity(scip, -lb) )
4748 	            coef = 1.0/lb;
4749 	      }
4750 	   }
4751 	   else if ( boundvar == nodedata->ubboundvar )
4752 	   {
4753 	      if ( SCIPisFeasPositive(scip, solval) )
4754 	      {
4755 	         SCIP_Real ub;
4756 	
4757 	         ub = nodedata->ubboundcoef;
4758 	         assert( SCIPisFeasPositive(scip, ub) );
4759 	         if ( ! SCIPisInfinity(scip, ub) )
4760 	            coef = 1.0/ub;
4761 	      }
4762 	      else if ( SCIPisFeasNegative(scip, solval) )
4763 	      {
4764 	         SCIP_Real lb;
4765 	
4766 	         lb = nodedata->lbboundcoef;
4767 	         assert( SCIPisFeasPositive(scip, lb) );
4768 	         if ( ! SCIPisInfinity(scip, lb) )
4769 	            coef = 1.0/lb;
4770 	      }
4771 	   }
4772 	
4773 	   if ( ! SCIPisZero(scip, coef) )
4774 	   {
4775 	      *feas += coef * solval;
4776 	      SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, coef) );
4777 	   }
4778 	
4779 	   /* if clique shall be greedily extended to a clique of larger size */
4780 	   if ( extend )
4781 	   {
4782 	      /* get successors */
4783 	      nsucc = SCIPdigraphGetNSuccessors(conflictgraph, v1);
4784 	      succ = SCIPdigraphGetSuccessors(conflictgraph, v1);
4785 	      assert( nsucc > 0 );
4786 	
4787 	      /* allocate buffer array */
4788 	      SCIP_CALL( SCIPallocBufferArray(scip, &extensions, nsucc) );
4789 	
4790 	      /* get possible extensions for the clique cover */
4791 	      for (s = 0; s < nsucc; ++s)
4792 	         extensions[s] = succ[s];
4793 	      nextensions = nsucc;
4794 	   }
4795 	   else
4796 	      nextensions = 1;
4797 	
4798 	   /* while there exist possible extensions for the clique cover */
4799 	   while ( nextensions > 0 )
4800 	   {
4801 	      SCIP_Real bestbigMval;
4802 	      SCIP_Real bigMval;
4803 	      int bestindex = -1;
4804 	      int ext;
4805 	
4806 	      bestbigMval = -SCIPinfinity(scip);
4807 	
4808 	      /* if v2 has not been added to clique already */
4809 	      if ( addv2 )
4810 	      {
4811 	         bestindex = v2;
4812 	         addv2 = FALSE;
4813 	      }
4814 	      else /* search for the extension with the largest absolute value of its LP relaxation solution value */
4815 	      {
4816 	         assert( extensions != NULL );
4817 	         for (s = 0; s < nextensions; ++s)
4818 	         {
4819 	            ext = extensions[s];
4820 	            bigMval = nodeGetSolvalBinaryBigMSOS1(scip, conflictgraph, sol, ext);
4821 	            if ( SCIPisFeasLT(scip, bestbigMval, bigMval) )
4822 	            {
4823 	               bestbigMval = bigMval;
4824 	               bestindex = ext;
4825 	            }
4826 	         }
4827 	      }
4828 	      assert( bestindex != -1 );
4829 	
4830 	      /* add bestindex variable to the constraint */
4831 	      nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, bestindex);
4832 	      var = nodedata->var;
4833 	      solval = SCIPgetSolVal(scip, sol, var);
4834 	      coef = 0.0;
4835 	      if ( boundvar == NULL )
4836 	      {
4837 	         if ( SCIPisFeasPositive(scip, solval) )
4838 	         {
4839 	            SCIP_Real ub;
4840 	            ub = SCIPvarGetUbLocal(var);
4841 	            assert( SCIPisFeasPositive(scip, ub));
4842 	
4843 	            if ( ! SCIPisInfinity(scip, ub) )
4844 	               coef = 1.0/ub;
4845 	         }
4846 	         else if ( SCIPisFeasNegative(scip, solval) )
4847 	         {
4848 	            SCIP_Real lb;
4849 	            lb = SCIPvarGetLbLocal(var);
4850 	            assert( SCIPisFeasNegative(scip, lb) );
4851 	            if ( ! SCIPisInfinity(scip, -lb) )
4852 	               coef = 1.0/lb;
4853 	         }
4854 	      }
4855 	      else if ( boundvar == nodedata->ubboundvar )
4856 	      {
4857 	         if ( SCIPisFeasPositive(scip, solval) )
4858 	         {
4859 	            SCIP_Real ub;
4860 	
4861 	            ub = nodedata->ubboundcoef;
4862 	            assert( SCIPisFeasPositive(scip, ub) );
4863 	            if ( ! SCIPisInfinity(scip, ub) )
4864 	               coef = 1.0/ub;
4865 	         }
4866 	         else if ( SCIPisFeasNegative(scip, solval) )
4867 	         {
4868 	            SCIP_Real lb;
4869 	
4870 	            lb = nodedata->lbboundcoef;
4871 	            assert( SCIPisFeasPositive(scip, lb) );
4872 	            if ( ! SCIPisInfinity(scip, -lb) )
4873 	               coef = 1.0/lb;
4874 	         }
4875 	      }
4876 	      if ( ! SCIPisZero(scip, coef) )
4877 	      {
4878 	         *feas += coef * solval;
4879 	         SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, coef) );
4880 	      }
4881 	
4882 	      if ( extend )
4883 	      {
4884 	         assert( extensions != NULL );
4885 	         /* compute new 'extensions' array */
4886 	         nextensionsnew = 0;
4887 	         for (s = 0; s < nextensions; ++s)
4888 	         {
4889 	            if ( s != bestindex && isConnectedSOS1(NULL, conflictgraph, bestindex, extensions[s]) )
4890 	               extensions[nextensionsnew++] = extensions[s];
4891 	         }
4892 	         nextensions = nextensionsnew;
4893 	      }
4894 	      else
4895 	         nextensions = 0;
4896 	   }
4897 	
4898 	   /* free buffer array */
4899 	   if ( extend )
4900 	      SCIPfreeBufferArray(scip, &extensions);
4901 	
4902 	   /* subtract rhs of constraint from feasibility value or add bound variable if existent */
4903 	   if ( boundvar == NULL )
4904 	      *feas -= 1.0;
4905 	   else
4906 	   {
4907 	      SCIP_CALL( SCIPaddCoefLinear(scip, cons, boundvar, -1.0) );
4908 	      *feas -= SCIPgetSolVal(scip, sol, boundvar);
4909 	   }
4910 	
4911 	   return SCIP_OKAY;
4912 	}
4913 	
4914 	
4915 	/** tries to add feasible complementarity constraints to a given child branching node.
4916 	 *
4917 	 *  @note In this function the conflict graph is updated to the conflict graph of the considered child branching node.
4918 	 */
4919 	static
4920 	SCIP_RETCODE addBranchingComplementaritiesSOS1(
4921 	   SCIP*                 scip,               /**< SCIP pointer */
4922 	   SCIP_NODE*            node,               /**< branching node */
4923 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
4924 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph of the current node */
4925 	   SCIP_DIGRAPH*         localconflicts,     /**< local conflicts (updates to local conflicts of child node) */
4926 	   SCIP_SOL*             sol,                /**< solution to be enforced (NULL for LP solution) */
4927 	   int                   nsos1vars,          /**< number of SOS1 variables */
4928 	   SCIP_Bool*            verticesarefixed,   /**< vector that indicates which variables are currently fixed to zerox */
4929 	   int*                  fixingsnode1,       /**< vertices of variables that will be fixed to zero for the branching node in the input of this function */
4930 	   int                   nfixingsnode1,      /**< number of entries of array nfixingsnode1 */
4931 	   int*                  fixingsnode2,       /**< vertices of variables that will be fixed to zero for the other branching node */
4932 	   int                   nfixingsnode2,      /**< number of entries of array nfixingsnode2 */
4933 	   int*                  naddedconss,        /**< pointer to store the number of added SOS1 constraints */
4934 	   SCIP_Bool             onlyviolsos1        /**< should only SOS1 constraints be added that are violated by the LP solution */
4935 	   )
4936 	{
4937 	   assert( scip != NULL );
4938 	   assert( node != NULL );
4939 	   assert( conshdlrdata != NULL );
4940 	   assert( conflictgraph != NULL );
4941 	   assert( verticesarefixed != NULL );
4942 	   assert( fixingsnode1 != NULL );
4943 	   assert( fixingsnode2 != NULL );
4944 	   assert( naddedconss != NULL );
4945 	
4946 	   *naddedconss = 0;
4947 	
4948 	   if ( nfixingsnode2 > 1 )
4949 	   {
4950 	      int* fixingsnode21; /* first partition of fixingsnode2 */
4951 	      int* fixingsnode22; /* second partition of fixingsnode2 */
4952 	      int nfixingsnode21;
4953 	      int nfixingsnode22;
4954 	
4955 	      int* coverarray; /* vertices, not in fixingsnode1 that cover all the vertices in array fixingsnode22 */
4956 	      int ncoverarray;
4957 	
4958 	      SCIP_Bool* mark;
4959 	      int* succarray;
4960 	      int nsuccarray;
4961 	      int* succ;
4962 	      int nsucc;
4963 	
4964 	      int i;
4965 	      int s;
4966 	
4967 	      /* allocate buffer arrays */
4968 	      SCIP_CALL( SCIPallocBufferArray(scip, &succarray, nsos1vars) );
4969 	      SCIP_CALL( SCIPallocBufferArray(scip, &mark, nsos1vars) );
4970 	      SCIP_CALL( SCIPallocBufferArray(scip, &fixingsnode21, nfixingsnode2) );
4971 	      SCIP_CALL( SCIPallocBufferArray(scip, &fixingsnode22, nfixingsnode2) );
4972 	
4973 	      /* mark all the unfixed vertices with FALSE */
4974 	      for (i = 0; i < nsos1vars; ++i)
4975 	         mark[i] = (verticesarefixed[i]);
4976 	
4977 	      /* mark all the vertices that are in the set fixingsnode1 */
4978 	      for (i = 0; i < nfixingsnode1; ++i)
4979 	      {
4980 	         assert( nfixingsnode1 <= 1 || (fixingsnode1[nfixingsnode1 - 1] > fixingsnode1[nfixingsnode1 - 2]) ); /* test: vertices are sorted */
4981 	         mark[fixingsnode1[i]] = TRUE;
4982 	      }
4983 	
4984 	      /* mark all the vertices that are in the set fixingsnode2 */
4985 	      for (i = 0; i < nfixingsnode2; ++i)
4986 	      {
4987 	         assert( nfixingsnode2 <= 1 || (fixingsnode2[nfixingsnode2 - 1] > fixingsnode2[nfixingsnode2 - 2]) ); /* test: vertices are sorted */
4988 	         mark[fixingsnode2[i]] = TRUE;
4989 	      }
4990 	
4991 	      /* compute the set of vertices that have a neighbor in the set fixingsnode2, but are not in the set fixingsnode1 or fixingsnode2 and are not already fixed */
4992 	      nsuccarray = 0;
4993 	      for (i = 0; i < nfixingsnode2; ++i)
4994 	      {
4995 	         nsucc = SCIPdigraphGetNSuccessors(conflictgraph, fixingsnode2[i]);
4996 	         succ = SCIPdigraphGetSuccessors(conflictgraph, fixingsnode2[i]);
4997 	
4998 	         for (s = 0; s < nsucc; ++s)
4999 	         {
5000 	            int succnode = succ[s];
5001 	
5002 	            if ( ! mark[succnode] )
5003 	            {
5004 	               mark[succnode] = TRUE;
5005 	               succarray[nsuccarray++] = succnode;
5006 	            }
5007 	         }
5008 	      }
5009 	
5010 	      /* allocate buffer array */
5011 	      SCIP_CALL( SCIPallocBufferArray(scip, &coverarray, nsos1vars) );
5012 	
5013 	      /* mark all the vertices with FALSE */
5014 	      for (i = 0; i < nsos1vars; ++i)
5015 	         mark[i] = FALSE;
5016 	
5017 	      /* mark all the vertices that are in the set fixingsnode2 */
5018 	      for (i = 0; i < nfixingsnode2; ++i)
5019 	         mark[fixingsnode2[i]] = TRUE;
5020 	
5021 	      /* for every node in succarray */
5022 	      for (i = 0; i < nsuccarray; ++i)
5023 	      {
5024 	         SCIP_Real solval1;
5025 	         SCIP_VAR* var1;
5026 	         int vertex1;
5027 	         int j;
5028 	
5029 	         vertex1 = succarray[i];
5030 	         var1 = SCIPnodeGetVarSOS1(conflictgraph, vertex1);
5031 	         solval1 = SCIPgetSolVal(scip, sol, var1);
5032 	
5033 	         /* we only add complementarity constraints if they are violated by the current LP solution */
5034 	         if ( ! onlyviolsos1 || ! SCIPisFeasZero(scip, solval1) )
5035 	         {
5036 	            /* compute first partition of fixingsnode2 that is the intersection of the neighbors of 'vertex1' with the set fixingsnode2 */
5037 	            nsucc = SCIPdigraphGetNSuccessors(conflictgraph, vertex1);
5038 	            succ = SCIPdigraphGetSuccessors(conflictgraph, vertex1);
5039 	            nfixingsnode21 = 0;
5040 	
5041 	            for (s = 0; s < nsucc; ++s)
5042 	            {
5043 	               if ( mark[succ[s]] )
5044 	               {
5045 	                  fixingsnode21[nfixingsnode21++] = succ[s];
5046 	                  assert( nfixingsnode21 == 1 || (fixingsnode21[nfixingsnode21 - 1] > fixingsnode21[nfixingsnode21 - 2]) ); /* test: successor vertices are sorted */
5047 	               }
5048 	            }
5049 	
5050 	            /* if variable can be fixed to zero */
5051 	            if ( nfixingsnode21 == nfixingsnode2 )
5052 	            {
5053 	               SCIP_Bool infeasible;
5054 	
5055 	               SCIP_CALL( fixVariableZeroNode(scip, var1, node, &infeasible) );
5056 	               assert( ! infeasible );
5057 	               continue;
5058 	            }
5059 	
5060 	            /* compute second partition of fixingsnode2 (that is fixingsnode2 \setminus fixingsnode21 ) */
5061 	            SCIPcomputeArraysSetminusInt(fixingsnode2, nfixingsnode2, fixingsnode21, nfixingsnode21, fixingsnode22, &nfixingsnode22);
5062 	            assert ( nfixingsnode22 + nfixingsnode21 == nfixingsnode2 );
5063 	
5064 	            /* compute cover set (that are all the vertices not in fixingsnode1 and fixingsnode21, whose neighborhood covers all the vertices of fixingsnode22) */
5065 	            SCIP_CALL( getCoverVertices(conflictgraph, verticesarefixed, -1, fixingsnode22, nfixingsnode22, coverarray, &ncoverarray) );
5066 	            SCIPcomputeArraysSetminusInt(coverarray, ncoverarray, fixingsnode1, nfixingsnode1, coverarray, &ncoverarray);
5067 	            SCIPcomputeArraysSetminusInt(coverarray, ncoverarray, fixingsnode21, nfixingsnode21, coverarray, &ncoverarray);
5068 	
5069 	            for (j = 0; j < ncoverarray; ++j)
5070 	            {
5071 	               int vertex2;
5072 	
5073 	               vertex2 = coverarray[j];
5074 	               assert( vertex2 != vertex1 );
5075 	
5076 	               /* prevent double enumeration */
5077 	               if ( vertex2 < vertex1 )
5078 	               {
5079 	                  SCIP_VAR* var2;
5080 	                  SCIP_Real solval2;
5081 	
5082 	                  var2 = SCIPnodeGetVarSOS1(conflictgraph, vertex2);
5083 	                  solval2 = SCIPgetSolVal(scip, sol, var2);
5084 	
5085 	                  if ( onlyviolsos1 && ( SCIPisFeasZero(scip, solval1) || SCIPisFeasZero(scip, solval2) ) )
5086 	                     continue;
5087 	
5088 	                  if ( ! isConnectedSOS1(NULL, conflictgraph, vertex1, vertex2) )
5089 	                  {
5090 	                     char name[SCIP_MAXSTRLEN];
5091 	                     SCIP_CONS* conssos1 = NULL;
5092 	                     SCIP_Bool takebound = FALSE;
5093 	                     SCIP_Real feas;
5094 	
5095 	                     SCIP_NODEDATA* nodedata;
5096 	                     SCIP_Real lbboundcoef1;
5097 	                     SCIP_Real lbboundcoef2;
5098 	                     SCIP_Real ubboundcoef1;
5099 	                     SCIP_Real ubboundcoef2;
5100 	                     SCIP_VAR* boundvar1;
5101 	                     SCIP_VAR* boundvar2;
5102 	
5103 	                     /* get bound variables if available */
5104 	                     nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, vertex1);
5105 	                     assert( nodedata != NULL );
5106 	                     boundvar1 = nodedata->ubboundvar;
5107 	                     lbboundcoef1 = nodedata->lbboundcoef;
5108 	                     ubboundcoef1 = nodedata->ubboundcoef;
5109 	                     nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, vertex2);
5110 	                     assert( nodedata != NULL );
5111 	                     boundvar2 = nodedata->ubboundvar;
5112 	                     lbboundcoef2 = nodedata->lbboundcoef;
5113 	                     ubboundcoef2 = nodedata->ubboundcoef;
5114 	
5115 	                     if ( boundvar1 != NULL && boundvar2 != NULL && SCIPvarCompare(boundvar1, boundvar2) == 0 )
5116 	                        takebound = TRUE;
5117 	
5118 	                     /* add new arc to local conflicts in order to generate tighter bound inequalities */
5119 	                     if ( conshdlrdata->addextendedbds )
5120 	                     {
5121 	                        if ( localconflicts == NULL )
5122 	                        {
5123 	                           SCIP_CALL( SCIPcreateDigraph(scip, &conshdlrdata->localconflicts, nsos1vars) );
5124 	                           localconflicts = conshdlrdata->localconflicts;
5125 	                        }
5126 	                        SCIP_CALL( SCIPdigraphAddArc(localconflicts, vertex1, vertex2, NULL) );
5127 	                        SCIP_CALL( SCIPdigraphAddArc(localconflicts, vertex2, vertex1, NULL) );
5128 	                        SCIP_CALL( SCIPdigraphAddArc(conflictgraph, vertex1, vertex2, NULL) );
5129 	                        SCIP_CALL( SCIPdigraphAddArc(conflictgraph, vertex2, vertex1, NULL) );
5130 	
5131 	                        /* can sort successors in place - do not use arcdata */
5132 	                        SCIPsortInt(SCIPdigraphGetSuccessors(localconflicts, vertex1), SCIPdigraphGetNSuccessors(localconflicts, vertex1));
5133 	                        SCIPsortInt(SCIPdigraphGetSuccessors(localconflicts, vertex2), SCIPdigraphGetNSuccessors(localconflicts, vertex2));
5134 	                        SCIPsortInt(SCIPdigraphGetSuccessors(conflictgraph, vertex1), SCIPdigraphGetNSuccessors(conflictgraph, vertex1));
5135 	                        SCIPsortInt(SCIPdigraphGetSuccessors(conflictgraph, vertex2), SCIPdigraphGetNSuccessors(conflictgraph, vertex2));
5136 	
5137 	                        /* mark conflictgraph as not local such that the new arcs are deleted after currents node processing */
5138 	                        conshdlrdata->isconflocal = TRUE;
5139 	                     }
5140 	
5141 	                     /* measure feasibility of complementarity between var1 and var2 */
5142 	                     if ( ! takebound )
5143 	                     {
5144 	                        feas = -1.0;
5145 	                        if ( SCIPisFeasPositive(scip, solval1) )
5146 	                        {
5147 	                           assert( SCIPisFeasPositive(scip, SCIPvarGetUbLocal(var1)));
5148 	                           if ( ! SCIPisInfinity(scip, SCIPvarGetUbLocal(var1)) )
5149 	                              feas += solval1/SCIPvarGetUbLocal(var1);
5150 	                        }
5151 	                        else if ( SCIPisFeasNegative(scip, solval1) )
5152 	                        {
5153 	                           assert( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var1)));
5154 	                           if ( ! SCIPisInfinity(scip, -SCIPvarGetLbLocal(var1)) )
5155 	                              feas += solval1/SCIPvarGetLbLocal(var1);
5156 	                        }
5157 	
5158 	                        if ( SCIPisFeasPositive(scip, solval2) )
5159 	                        {
5160 	                           assert( SCIPisFeasPositive(scip, SCIPvarGetUbLocal(var2)));
5161 	                           if ( ! SCIPisInfinity(scip, SCIPvarGetUbLocal(var2)) )
5162 	                              feas += solval2/SCIPvarGetUbLocal(var2);
5163 	                        }
5164 	                        else if ( SCIPisFeasNegative(scip, solval2) )
5165 	                        {
5166 	                           assert( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var2)));
5167 	                           if ( ! SCIPisInfinity(scip, -SCIPvarGetLbLocal(var2)) )
5168 	                              feas += solval2/SCIPvarGetLbLocal(var2);
5169 	                        }
5170 	                     }
5171 	                     else
5172 	                     {
5173 	                        feas = -SCIPgetSolVal(scip, sol, boundvar1);
5174 	                        if ( SCIPisFeasPositive(scip, solval1) )
5175 	                        {
5176 	                           assert( SCIPisFeasPositive(scip, ubboundcoef1));
5177 	                           if ( ! SCIPisInfinity(scip, ubboundcoef1) )
5178 	                              feas += solval1/ubboundcoef1;
5179 	                        }
5180 	                        else if ( SCIPisFeasNegative(scip, solval1) )
5181 	                        {
5182 	                           assert( SCIPisFeasPositive(scip, lbboundcoef1));
5183 	                           if ( ! SCIPisInfinity(scip, -lbboundcoef1) )
5184 	                              feas += solval1/lbboundcoef1;
5185 	                        }
5186 	
5187 	                        if ( SCIPisFeasPositive(scip, solval2) )
5188 	                        {
5189 	                           assert( SCIPisFeasPositive(scip, ubboundcoef2));
5190 	                           if ( ! SCIPisInfinity(scip, ubboundcoef2) )
5191 	                              feas += solval2/ubboundcoef2;
5192 	                        }
5193 	                        else if ( SCIPisFeasNegative(scip, solval2) )
5194 	                        {
5195 	                           assert( SCIPisFeasPositive(scip, lbboundcoef2));
5196 	                           if ( ! SCIPisInfinity(scip, -lbboundcoef2) )
5197 	                              feas += solval2/lbboundcoef2;
5198 	                        }
5199 	                        assert( ! SCIPisFeasNegative(scip, solval2) );
5200 	                     }
5201 	
5202 	                     if ( SCIPisGT(scip, feas, conshdlrdata->addcompsfeas) )
5203 	                     {
5204 	                        /* create SOS1 constraint */
5205 	                        (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "sos1_branchnode_%" SCIP_LONGINT_FORMAT "_no_%i", SCIPnodeGetNumber(node), *naddedconss);
5206 	                        SCIP_CALL( SCIPcreateConsSOS1(scip, &conssos1, name, 0, NULL, NULL, TRUE, TRUE, TRUE, FALSE, TRUE,
5207 	                              TRUE, FALSE, FALSE, FALSE) );
5208 	
5209 	                        /* add variables to SOS1 constraint */
5210 	                        SCIP_CALL( addVarSOS1(scip, conssos1, conshdlrdata, var1, 1.0) );
5211 	                        SCIP_CALL( addVarSOS1(scip, conssos1, conshdlrdata, var2, 2.0) );
5212 	
5213 	                        /* add SOS1 constraint to the branching node */
5214 	                        SCIP_CALL( SCIPaddConsNode(scip, node, conssos1, NULL) );
5215 	                        ++(*naddedconss);
5216 	
5217 	                        /* release constraint */
5218 	                        SCIP_CALL( SCIPreleaseCons(scip, &conssos1) );
5219 	                     }
5220 	
5221 	                     /* add bound inequality*/
5222 	                     if ( ! SCIPisFeasZero(scip, solval1) && ! SCIPisFeasZero(scip, solval2) )
5223 	                     {
5224 	                        /* possibly create linear constraint of the form x_i/u_i + x_j/u_j <= t if a bound variable t with x_i <= u_i * t and x_j <= u_j * t exists.
5225 	                         * Otherwise try to create a constraint of the form x_i/u_i + x_j/u_j <= 1. Try the same for the lower bounds. */
5226 	                        (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "boundcons_branchnode_%" SCIP_LONGINT_FORMAT "_no_%i", SCIPnodeGetNumber(node), *naddedconss);
5227 	                        if ( takebound )
5228 	                        {
5229 	                           /* create constraint with right hand side = 0.0 */
5230 	                           SCIP_CALL( SCIPcreateConsLinear(scip, &conssos1, name, 0, NULL, NULL, -SCIPinfinity(scip), 0.0, TRUE, FALSE, TRUE, FALSE, FALSE,
5231 	                                 TRUE, FALSE, FALSE, FALSE, FALSE) );
5232 	
5233 	                           /* add variables */
5234 	                           SCIP_CALL( getBoundConsFromVertices(scip, conflictgraph, sol, vertex1, vertex2, boundvar1, conshdlrdata->addextendedbds, conssos1, &feas) );
5235 	                        }
5236 	                        else
5237 	                        {
5238 	                           /* create constraint with right hand side = 1.0 */
5239 	                           SCIP_CALL( SCIPcreateConsLinear(scip, &conssos1, name, 0, NULL, NULL, -SCIPinfinity(scip), 1.0, TRUE, FALSE, TRUE, FALSE, FALSE,
5240 	                                 TRUE, FALSE, FALSE, FALSE, FALSE) );
5241 	
5242 	                           /* add variables */
5243 	                           SCIP_CALL( getBoundConsFromVertices(scip, conflictgraph, sol, vertex1, vertex2, NULL, conshdlrdata->addextendedbds, conssos1, &feas) );
5244 	                        }
5245 	
5246 	                        /* add linear constraint to the branching node if usefull */
5247 	                        if ( SCIPisGT(scip, feas, conshdlrdata->addbdsfeas ) )
5248 	                        {
5249 	                           SCIP_CALL( SCIPaddConsNode(scip, node, conssos1, NULL) );
5250 	                           ++(*naddedconss);
5251 	                        }
5252 	
5253 	                        /* release constraint */
5254 	                        SCIP_CALL( SCIPreleaseCons(scip, &conssos1) );
5255 	                     }
5256 	
5257 	                     /* break if number of added constraints exceeds a predefined value */
5258 	                     if ( conshdlrdata->maxaddcomps >= 0 && *naddedconss > conshdlrdata->maxaddcomps )
5259 	                        break;
5260 	                  }
5261 	               }
5262 	            }
5263 	         }
5264 	
5265 	         /* break if number of added constraints exceeds a predefined value */
5266 	         if ( conshdlrdata->maxaddcomps >= 0 && *naddedconss > conshdlrdata->maxaddcomps )
5267 	            break;
5268 	      }
5269 	
5270 	      /* free buffer array */
5271 	      SCIPfreeBufferArray(scip, &coverarray);
5272 	      SCIPfreeBufferArray(scip, &fixingsnode22);
5273 	      SCIPfreeBufferArray(scip, &fixingsnode21);
5274 	      SCIPfreeBufferArray(scip, &mark);
5275 	      SCIPfreeBufferArray(scip, &succarray);
5276 	   }
5277 	
5278 	   return SCIP_OKAY;
5279 	}
5280 	
5281 	
5282 	/** resets local conflict graph to the conflict graph of the root node */
5283 	static
5284 	SCIP_RETCODE resetConflictgraphSOS1(
5285 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph of root node */
5286 	   SCIP_DIGRAPH*         localconflicts,     /**< local conflicts that should be removed from conflict graph */
5287 	   int                   nsos1vars           /**< number of SOS1 variables */
5288 	   )
5289 	{
5290 	   int j;
5291 	
5292 	   for (j = 0; j < nsos1vars; ++j)
5293 	   {
5294 	      int nsuccloc;
5295 	
5296 	      nsuccloc = SCIPdigraphGetNSuccessors(localconflicts, j);
5297 	      if ( nsuccloc > 0 )
5298 	      {
5299 	         int* succloc;
5300 	         int* succ;
5301 	         int nsucc;
5302 	         int k = 0;
5303 	
5304 	         succloc = SCIPdigraphGetSuccessors(localconflicts, j);
5305 	         succ = SCIPdigraphGetSuccessors(conflictgraph, j);
5306 	         nsucc = SCIPdigraphGetNSuccessors(conflictgraph, j);
5307 	
5308 	         /* reset number of successors */
5309 	         SCIPcomputeArraysSetminusInt(succ, nsucc, succloc, nsuccloc, succ, &k);
5310 	         SCIP_CALL( SCIPdigraphSetNSuccessors(conflictgraph, j, k) );
5311 	         SCIP_CALL( SCIPdigraphSetNSuccessors(localconflicts, j, 0) );
5312 	      }
5313 	   }
5314 	
5315 	   return SCIP_OKAY;
5316 	}
5317 	
5318 	
5319 	/** Conflict graph enforcement method
5320 	 *
5321 	 *  The conflict graph can be enforced by different branching rules:
5322 	 *
5323 	 *  - Branch on the neighborhood of a single variable @p i, i.e., in one branch \f$x_i\f$ is fixed to zero and in the
5324 	 *    other its neighbors from the conflict graph.
5325 	 *
5326 	 *  - Branch on complete bipartite subgraphs of the conflict graph, i.e., in one branch fix the variables from the first
5327 	 *    bipartite partition and the variables from the second bipartite partition in the other.
5328 	 *
5329 	 *  - In addition to variable domain fixings, it is sometimes also possible to add new SOS1 constraints to the branching
5330 	 *    nodes. This results in a nonstatic conflict graph, which may change dynamically with every branching node.
5331 	 *
5332 	 *  We make use of different selection rules that define on which system of SOS1 variables to branch next:
5333 	 *
5334 	 *  - Most infeasible branching: Branch on the system of SOS1 variables with largest violation.
5335 	 *
5336 	 *  - Strong branching: Here, the LP-relaxation is partially solved for each branching decision among a candidate list.
5337 	 *    Then the decision with best progress is chosen.
5338 	 */
5339 	static
5340 	SCIP_RETCODE enforceConflictgraph(
5341 	   SCIP*                 scip,               /**< SCIP pointer */
5342 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
5343 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
5344 	   int                   nconss,             /**< number of constraints */
5345 	   SCIP_CONS**           conss,              /**< SOS1 constraints */
5346 	   SCIP_SOL*             sol,                /**< solution to be enforced (NULL for LP solution) */
5347 	   SCIP_RESULT*          result              /**< result */
5348 	   )
5349 	{
5350 	   SCIP_DIGRAPH* conflictgraph;
5351 	   int nsos1vars;
5352 	
5353 	   SCIP_Bool* verticesarefixed = NULL;
5354 	   int* fixingsnode1 = NULL;
5355 	   int* fixingsnode2 = NULL;
5356 	   int nfixingsnode1;
5357 	   int nfixingsnode2;
5358 	
5359 	   SCIP_Real bestobjval1 = -SCIPinfinity(scip);
5360 	   SCIP_Real bestobjval2 = -SCIPinfinity(scip);
5361 	   SCIP_Real lpobjval = -SCIPinfinity(scip);
5362 	
5363 	   SCIP_Bool infeasible;
5364 	   SCIP_Bool bipbranch = FALSE;
5365 	   int nstrongrounds;
5366 	
5367 	   int branchvertex;
5368 	   SCIP_NODE* node1;
5369 	   SCIP_NODE* node2;
5370 	   SCIP_Real nodeselest;
5371 	   SCIP_Real objest;
5372 	
5373 	   int i;
5374 	   int j;
5375 	   int c;
5376 	
5377 	   assert( scip != NULL );
5378 	   assert( conshdlrdata != NULL );
5379 	   assert( conshdlr != NULL );
5380 	   assert( conss != NULL );
5381 	   assert( result != NULL );
5382 	
5383 	   SCIPdebugMsg(scip, "Enforcing SOS1 conflict graph <%s>.\n", SCIPconshdlrGetName(conshdlr) );
5384 	   *result = SCIP_DIDNOTRUN;
5385 	
5386 	   /* get number of SOS1 variables */
5387 	   nsos1vars = conshdlrdata->nsos1vars;
5388 	
5389 	   /* exit for trivial cases */
5390 	   if ( nsos1vars == 0 || nconss == 0 )
5391 	   {
5392 	      *result = SCIP_FEASIBLE;
5393 	      return SCIP_OKAY;
5394 	   }
5395 	
5396 	   /* get conflict graph */
5397 	   conflictgraph = conshdlrdata->conflictgraph;
5398 	   assert( ! conshdlrdata->isconflocal ); /* conflictgraph should be the one of the root node */
5399 	
5400 	   /* check each constraint and update conflict graph if necessary */
5401 	   for (c = 0; c < nconss; ++c)
5402 	   {
5403 	      SCIP_CONSDATA* consdata;
5404 	      SCIP_CONS* cons;
5405 	      SCIP_Bool cutoff;
5406 	      int ngen = 0;
5407 	
5408 	      cons = conss[c];
5409 	      assert( cons != NULL );
5410 	      consdata = SCIPconsGetData(cons);
5411 	      assert( consdata != NULL );
5412 	
5413 	      /* do nothing if there are not enough variables - this is usually eliminated by preprocessing */
5414 	      if ( consdata->nvars < 2 )
5415 	         continue;
5416 	
5417 	      /* first perform propagation (it might happen that standard propagation is turned off) */
5418 	      SCIP_CALL( propConsSOS1(scip, cons, consdata, &cutoff, &ngen) );
5419 	      SCIPdebugMsg(scip, "propagating <%s> in enforcing (cutoff: %u, domain reductions: %d).\n", SCIPconsGetName(cons), cutoff, ngen);
5420 	      if ( cutoff )
5421 	      {
5422 	         *result = SCIP_CUTOFF;
5423 		 break;
5424 	      }
5425 	      if ( ngen > 0 )
5426 	      {
5427 	         *result = SCIP_REDUCEDDOM;
5428 		 break;
5429 	      }
5430 	      assert( ngen == 0 );
5431 	
5432 	      /* add local conflicts to conflict graph and save them in 'localconflicts' */
5433 	      if ( consdata->local )
5434 	      {
5435 	         SCIP_VAR** vars;
5436 	         int nvars;
5437 	         int indi;
5438 	         int indj;
5439 	
5440 	         if ( conshdlrdata->localconflicts == NULL )
5441 	         {
5442 	            SCIP_CALL( SCIPcreateDigraph(scip, &conshdlrdata->localconflicts, nsos1vars) );
5443 	         }
5444 	
5445 	         vars = consdata->vars;
5446 	         nvars = consdata->nvars;
5447 	         for (i = 0; i < nvars-1; ++i)
5448 	         {
5449 	            SCIP_VAR* var;
5450 	
5451 	            var = vars[i];
5452 	            indi = varGetNodeSOS1(conshdlrdata, var);
5453 	
5454 	            if( indi == -1 )
5455 	               return SCIP_INVALIDDATA;
5456 	
5457 	            if ( ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) || ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) )
5458 	            {
5459 	               for (j = i+1; j < nvars; ++j)
5460 	               {
5461 	                  var = vars[j];
5462 	                  indj = varGetNodeSOS1(conshdlrdata, var);
5463 	
5464 	                  if( indj == -1 )
5465 	                     return SCIP_INVALIDDATA;
5466 	
5467 	                  if ( ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) || ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) )
5468 	                  {
5469 	                     if ( ! isConnectedSOS1(NULL, conflictgraph, indi, indj) )
5470 	                     {
5471 	                        SCIP_CALL( SCIPdigraphAddArcSafe(conflictgraph, indi, indj, NULL) );
5472 	                        SCIP_CALL( SCIPdigraphAddArcSafe(conflictgraph, indj, indi, NULL) );
5473 	
5474 	                        SCIP_CALL( SCIPdigraphAddArcSafe(conshdlrdata->localconflicts, indi, indj, NULL) );
5475 	                        SCIP_CALL( SCIPdigraphAddArcSafe(conshdlrdata->localconflicts, indj, indi, NULL) );
5476 	
5477 	                        conshdlrdata->isconflocal = TRUE;
5478 	                     }
5479 	                  }
5480 	               }
5481 	            }
5482 	         }
5483 	      }
5484 	   }
5485 	
5486 	   /* sort successor list of conflict graph if necessary */
5487 	   if ( conshdlrdata->isconflocal )
5488 	   {
5489 	      for (j = 0; j < nsos1vars; ++j)
5490 	      {
5491 	         int nsuccloc;
5492 	
5493 	         nsuccloc = SCIPdigraphGetNSuccessors(conshdlrdata->localconflicts, j);
5494 	         if ( nsuccloc > 0 )
5495 	         {
5496 	            SCIPsortInt(SCIPdigraphGetSuccessors(conflictgraph, j), SCIPdigraphGetNSuccessors(conflictgraph, j));
5497 	            SCIPsortInt(SCIPdigraphGetSuccessors(conshdlrdata->localconflicts, j), nsuccloc);
5498 	         }
5499 	      }
5500 	   }
5501 	
5502 	   if ( *result == SCIP_CUTOFF || *result == SCIP_REDUCEDDOM )
5503 	   {
5504 	      /* remove local conflicts from conflict graph */
5505 	      if ( conshdlrdata->isconflocal )
5506 	      {
5507 		 SCIP_CALL( resetConflictgraphSOS1(conflictgraph, conshdlrdata->localconflicts, nsos1vars) );
5508 		 conshdlrdata->isconflocal = FALSE;
5509 	      }
5510 	      return SCIP_OKAY;
5511 	   }
5512 	
5513 	   /* detect fixed variables */
5514 	   SCIP_CALL( SCIPallocBufferArray(scip, &verticesarefixed, nsos1vars) );
5515 	   for (j = 0; j < nsos1vars; ++j)
5516 	   {
5517 	      SCIP_VAR* var;
5518 	      SCIP_Real ub;
5519 	      SCIP_Real lb;
5520 	
5521 	      var = SCIPnodeGetVarSOS1(conflictgraph, j);
5522 	      ub = SCIPvarGetUbLocal(var);
5523 	      lb = SCIPvarGetLbLocal(var);
5524 	      if ( SCIPisFeasZero(scip, ub) && SCIPisFeasZero(scip, lb) )
5525 	         verticesarefixed[j] = TRUE;
5526 	      else
5527 	         verticesarefixed[j] = FALSE;
5528 	   }
5529 	
5530 	   /* should bipartite branching be used? */
5531 	   if ( conshdlrdata->branchingrule == 'b' )
5532 	      bipbranch = TRUE;
5533 	
5534 	   /* determine number of strong branching iterations */
5535 	   if ( conshdlrdata->nstrongrounds >= 0 )
5536 	      nstrongrounds = MIN(conshdlrdata->nstrongrounds, nsos1vars);
5537 	   else
5538 	   {
5539 	      /* determine number depending on depth, based on heuristical considerations */
5540 	      if ( SCIPgetDepth(scip) <= 10 )
5541 	         nstrongrounds = MAX(10, (int)SCIPfloor(scip, pow(log((SCIP_Real)nsos1vars), 1.0)));/*lint !e666*/
5542 	      else if ( SCIPgetDepth(scip) <= 20 )
5543 	         nstrongrounds = MAX(5, (int)SCIPfloor(scip, pow(log((SCIP_Real)nsos1vars), 0.7)));/*lint !e666*/
5544 	      else
5545 	         nstrongrounds = 0;
5546 	      nstrongrounds = MIN(nsos1vars, nstrongrounds);
5547 	   }
5548 	
5549 	   /* allocate buffer arrays */
5550 	   SCIP_CALL( SCIPallocBufferArray(scip, &fixingsnode1, nsos1vars) );
5551 	   if ( bipbranch )
5552 	      SCIP_CALL( SCIPallocBufferArray(scip, &fixingsnode2, nsos1vars) );
5553 	   else
5554 	      SCIP_CALL( SCIPallocBufferArray(scip, &fixingsnode2, 1) );
5555 	
5556 	   /* if strongbranching is turned off: use most infeasible branching */
5557 	   if ( nstrongrounds == 0 )
5558 	   {
5559 	      SCIP_Bool relsolfeas;
5560 	
5561 	      /* get branching vertex using most infeasible branching */
5562 	      SCIP_CALL( getBranchingPrioritiesSOS1(scip, conshdlrdata, conflictgraph, sol, nsos1vars, verticesarefixed,
5563 	            bipbranch, fixingsnode1, fixingsnode2, NULL, &branchvertex, &relsolfeas) );
5564 	
5565 	      /* if LP relaxation solution is feasible */
5566 	      if ( relsolfeas )
5567 	      {
5568 	         SCIPdebugMsg(scip, "all the SOS1 constraints are feasible.\n");
5569 	
5570 	         /* update result */
5571 	         *result = SCIP_FEASIBLE;
5572 	
5573 	         /* remove local conflicts from conflict graph */
5574 	         if ( conshdlrdata->isconflocal )
5575 	         {
5576 	            SCIP_CALL( resetConflictgraphSOS1(conflictgraph, conshdlrdata->localconflicts, nsos1vars) );
5577 	            conshdlrdata->isconflocal = FALSE;
5578 	         }
5579 	
5580 	         /* free memory */
5581 	         SCIPfreeBufferArrayNull(scip, &fixingsnode2);
5582 	         SCIPfreeBufferArrayNull(scip, &fixingsnode1);
5583 	         SCIPfreeBufferArrayNull(scip, &verticesarefixed);
5584 	
5585 	         return SCIP_OKAY;
5586 	      }
5587 	   }
5588 	   else
5589 	   {
5590 	      /* get branching vertex using strong branching */
5591 	      SCIP_CALL( getBranchingDecisionStrongbranchSOS1(scip, conshdlrdata, conflictgraph, sol, nsos1vars, lpobjval,
5592 	            bipbranch, nstrongrounds, verticesarefixed, fixingsnode1, fixingsnode2, &branchvertex, &bestobjval1,
5593 	            &bestobjval2, result) );
5594 	
5595 	      if ( *result == SCIP_CUTOFF || *result == SCIP_FEASIBLE || *result == SCIP_REDUCEDDOM )
5596 	      {
5597 	         /* remove local conflicts from conflict graph */
5598 	         if ( conshdlrdata->isconflocal )
5599 	         {
5600 	            SCIP_CALL( resetConflictgraphSOS1(conflictgraph, conshdlrdata->localconflicts, nsos1vars) );
5601 	            conshdlrdata->isconflocal = FALSE;
5602 	         }
5603 	
5604 	         /* free memory */
5605 	         SCIPfreeBufferArrayNull(scip, &fixingsnode2);
5606 	         SCIPfreeBufferArrayNull(scip, &fixingsnode1);
5607 	         SCIPfreeBufferArrayNull(scip, &verticesarefixed);
5608 	
5609 	         return SCIP_OKAY;
5610 	      }
5611 	   }
5612 	
5613 	   /* if we should leave branching decision to branching rules */
5614 	   if ( ! conshdlrdata->branchsos )
5615 	   {
5616 	      /* remove local conflicts from conflict graph */
5617 	      if ( conshdlrdata->isconflocal )
5618 	      {
5619 		 SCIP_CALL( resetConflictgraphSOS1(conflictgraph, conshdlrdata->localconflicts, nsos1vars) );
5620 		 conshdlrdata->isconflocal = FALSE;
5621 	      }
5622 	
5623 	      /* free memory */
5624 	      SCIPfreeBufferArrayNull(scip, &fixingsnode2);
5625 	      SCIPfreeBufferArrayNull(scip, &fixingsnode1);
5626 	      SCIPfreeBufferArrayNull(scip, &verticesarefixed);
5627 	
5628 	      assert( branchvertex >= 0 && branchvertex < nsos1vars );
5629 	      if ( SCIPvarIsBinary(SCIPnodeGetVarSOS1(conflictgraph, branchvertex)) )
5630 	      {
5631 	         *result = SCIP_INFEASIBLE;
5632 	         return SCIP_OKAY;
5633 	      }
5634 	      else
5635 	      {
5636 	         SCIPerrorMessage("Incompatible parameter setting: branchsos can only be set to false if all SOS1 variables are binary.\n");
5637 	         return SCIP_PARAMETERWRONGVAL;
5638 	      }
5639 	   }
5640 	
5641 	   /* create branching nodes */
5642 	
5643 	   /* get vertices of variables that will be fixed to zero for each node */
5644 	   assert( branchvertex >= 0 && branchvertex < nsos1vars );
5645 	   assert( ! verticesarefixed[branchvertex] );
5646 	   SCIP_CALL( getBranchingVerticesSOS1(scip, conflictgraph, sol, verticesarefixed, bipbranch, branchvertex,
5647 	         fixingsnode1, &nfixingsnode1, fixingsnode2, &nfixingsnode2) );
5648 	
5649 	   /* calculate node selection and objective estimate for node 1 */
5650 	   nodeselest = 0.0;
5651 	   objest = SCIPgetLocalTransEstimate(scip);
5652 	   for (j = 0; j < nfixingsnode1; ++j)
5653 	   {
5654 	      SCIP_VAR* var;
5655 	
5656 	      var = SCIPnodeGetVarSOS1(conflictgraph, fixingsnode1[j]);
5657 	      objest += SCIPcalcChildEstimateIncrease(scip, var, SCIPgetSolVal(scip, sol, var), 0.0);
5658 	      nodeselest += SCIPcalcNodeselPriority(scip, var, SCIP_BRANCHDIR_DOWNWARDS, 0.0);
5659 	   }
5660 	   assert( objest >= SCIPgetLocalTransEstimate(scip) );
5661 	
5662 	   /* create node 1 */
5663 	   SCIP_CALL( SCIPcreateChild(scip, &node1, nodeselest, objest) );
5664 	
5665 	   /* fix variables for the first node */
5666 	   if ( conshdlrdata->fixnonzero && nfixingsnode2 == 1 )
5667 	   {
5668 	      SCIP_VAR* var;
5669 	      SCIP_Real lb;
5670 	      SCIP_Real ub;
5671 	
5672 	      var = SCIPnodeGetVarSOS1(conflictgraph, fixingsnode2[0]);
5673 	      lb = SCIPvarGetLbLocal(var);
5674 	      ub = SCIPvarGetUbLocal(var);
5675 	
5676 	      if ( SCIPvarGetStatus(var) != SCIP_VARSTATUS_MULTAGGR )
5677 	      {
5678 	         if ( SCIPisZero(scip, lb) )
5679 	         {
5680 	            /* fix variable to some very small, but positive number or to 1.0 if variable is integral */
5681 	            if (SCIPvarIsIntegral(var) )
5682 	            {
5683 	               SCIP_CALL( SCIPchgVarLbNode(scip, node1, var, 1.0) );
5684 	            }
5685 	            else
5686 	            {
5687 	               SCIP_CALL( SCIPchgVarLbNode(scip, node1, var, 1.5 * SCIPfeastol(scip)) );
5688 	            }
5689 	         }
5690 	         else if ( SCIPisZero(scip, ub) )
5691 	         {
5692 	            if (SCIPvarIsIntegral(var) )
5693 	            {
5694 	               /* fix variable to some negative number with small absolute value to -1.0 if variable is integral */
5695 	               SCIP_CALL( SCIPchgVarUbNode(scip, node1, var, -1.0) );
5696 	            }
5697 	            else
5698 	            {
5699 	               /* fix variable to some negative number with small absolute value to -1.0 if variable is integral */
5700 	               SCIP_CALL( SCIPchgVarUbNode(scip, node1, var, -1.5 * SCIPfeastol(scip)) );
5701 	            }
5702 	         }
5703 	      }
5704 	   }
5705 	
5706 	   for (j = 0; j < nfixingsnode1; ++j)
5707 	   {
5708 	      /* fix variable to zero */
5709 	      SCIP_CALL( fixVariableZeroNode(scip, SCIPnodeGetVarSOS1(conflictgraph, fixingsnode1[j]), node1, &infeasible) );
5710 	      assert( ! infeasible );
5711 	   }
5712 	
5713 	   /* calculate node selection and objective estimate for node 2 */
5714 	   nodeselest = 0.0;
5715 	   objest = SCIPgetLocalTransEstimate(scip);
5716 	   for (j = 0; j < nfixingsnode2; ++j)
5717 	   {
5718 	      SCIP_VAR* var;
5719 	
5720 	      var = SCIPnodeGetVarSOS1(conflictgraph, fixingsnode1[j]);
5721 	      objest += SCIPcalcChildEstimateIncrease(scip, var, SCIPgetSolVal(scip, sol, var), 0.0);
5722 	      nodeselest += SCIPcalcNodeselPriority(scip, var, SCIP_BRANCHDIR_DOWNWARDS, 0.0);
5723 	   }
5724 	   assert( objest >= SCIPgetLocalTransEstimate(scip) );
5725 	
5726 	   /* create node 2 */
5727 	   SCIP_CALL( SCIPcreateChild(scip, &node2, nodeselest, objest) );
5728 	
5729 	   /* fix variables to zero */
5730 	   for (j = 0; j < nfixingsnode2; ++j)
5731 	   {
5732 	      SCIP_CALL( fixVariableZeroNode(scip, SCIPnodeGetVarSOS1(conflictgraph, fixingsnode2[j]), node2, &infeasible) );
5733 	      assert( ! infeasible );
5734 	   }
5735 	
5736 	   /* add complementarity constraints to the branching nodes */
5737 	   if ( conshdlrdata->addcomps && ( conshdlrdata->addcompsdepth == -1 || conshdlrdata->addcompsdepth >= SCIPgetDepth(scip) ) )
5738 	   {
5739 	      int naddedconss;
5740 	
5741 	      assert( ! conshdlrdata->fixnonzero );
5742 	
5743 	      /* add complementarity constraints to the left branching node */
5744 	      SCIP_CALL( addBranchingComplementaritiesSOS1(scip, node1, conshdlrdata, conflictgraph, conshdlrdata->localconflicts, sol,
5745 	               nsos1vars, verticesarefixed, fixingsnode1, nfixingsnode1, fixingsnode2, nfixingsnode2, &naddedconss, TRUE) );
5746 	
5747 	      if ( naddedconss == 0 )
5748 	      {
5749 	         /* add complementarity constraints to the right branching node */
5750 	         SCIP_CALL( addBranchingComplementaritiesSOS1(scip, node2, conshdlrdata, conflictgraph, conshdlrdata->localconflicts, sol,
5751 	               nsos1vars, verticesarefixed, fixingsnode2, nfixingsnode2, fixingsnode1, nfixingsnode1, &naddedconss, TRUE) );
5752 	      }
5753 	   }
5754 	
5755 	   /* sets node's lower bound to the best known value */
5756 	   if ( nstrongrounds > 0 )
5757 	   {
5758 	      SCIP_CALL( SCIPupdateNodeLowerbound(scip, node1, MAX(lpobjval, bestobjval1) ) );
5759 	      SCIP_CALL( SCIPupdateNodeLowerbound(scip, node2, MAX(lpobjval, bestobjval2) ) );
5760 	   }
5761 	
5762 	   /* remove local conflicts from conflict graph */
5763 	   if ( conshdlrdata->isconflocal )
5764 	   {
5765 	      SCIP_CALL( resetConflictgraphSOS1(conflictgraph, conshdlrdata->localconflicts, nsos1vars) );
5766 	      conshdlrdata->isconflocal = FALSE;
5767 	   }
5768 	
5769 	   /* free buffer arrays */
5770 	   SCIPfreeBufferArrayNull(scip, &fixingsnode2);
5771 	   SCIPfreeBufferArrayNull(scip, &fixingsnode1);
5772 	   SCIPfreeBufferArrayNull(scip, &verticesarefixed );
5773 	   *result = SCIP_BRANCHED;
5774 	
5775 	   return SCIP_OKAY;
5776 	}
5777 	
5778 	
5779 	/** SOS1 branching enforcement method
5780 	 *
5781 	 *  We check whether the current solution is feasible, i.e., contains at most one nonzero
5782 	 *  variable. If not, we branch along the lines indicated by Beale and Tomlin:
5783 	 *
5784 	 *  We first compute \f$W = \sum_{j=1}^n |x_i|\f$ and \f$w = \sum_{j=1}^n j\, |x_i|\f$. Then we
5785 	 *  search for the index \f$k\f$ that satisfies
5786 	 *  \f[
5787 	 *        k \leq \frac{w}{W} < k+1.
5788 	 *  \f]
5789 	 *  The branches are then
5790 	 *  \f[
5791 	 *        x_1 = 0, \ldots, x_k = 0 \qquad \mbox{and}\qquad x_{k+1} = 0, \ldots, x_n = 0.
5792 	 *  \f]
5793 	 *
5794 	 *  If the constraint contains two variables, the branching of course simplifies.
5795 	 *
5796 	 *  Depending on the parameters (@c branchnonzeros, @c branchweight) there are three ways to choose
5797 	 *  the branching constraint.
5798 	 *
5799 	 *  <TABLE>
5800 	 *  <TR><TD>@c branchnonzeros</TD><TD>@c branchweight</TD><TD>constraint chosen</TD></TR>
5801 	 *  <TR><TD>@c true          </TD><TD> ?             </TD><TD>most number of nonzeros</TD></TR>
5802 	 *  <TR><TD>@c false         </TD><TD> @c true       </TD><TD>maximal weight corresponding to nonzero variable</TD></TR>
5803 	 *  <TR><TD>@c false         </TD><TD> @c true       </TD><TD>largest sum of variable values</TD></TR>
5804 	 *  </TABLE>
5805 	 *
5806 	 *  @c branchnonzeros = @c false, @c branchweight = @c true allows the user to specify an order for
5807 	 *  the branching importance of the constraints (setting the weights accordingly).
5808 	 *
5809 	 *  Constraint branching can also be turned off using parameter @c branchsos.
5810 	 */
5811 	static
5812 	SCIP_RETCODE enforceConssSOS1(
5813 	   SCIP*                 scip,               /**< SCIP pointer */
5814 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
5815 	   int                   nconss,             /**< number of constraints */
5816 	   SCIP_CONS**           conss,              /**< indicator constraints */
5817 	   SCIP_SOL*             sol,                /**< solution to be enforced (NULL for LP solution) */
5818 	   SCIP_RESULT*          result              /**< result */
5819 	   )
5820 	{
5821 	   SCIP_CONSHDLRDATA* conshdlrdata;
5822 	   SCIP_CONSDATA* consdata;
5823 	   SCIP_NODE* node1;
5824 	   SCIP_NODE* node2;
5825 	   SCIP_CONS* branchCons;
5826 	   SCIP_Real maxWeight;
5827 	   SCIP_VAR** vars;
5828 	   int nvars;
5829 	   int c;
5830 	
5831 	   assert( scip != NULL );
5832 	   assert( conshdlr != NULL );
5833 	   assert( conss != NULL );
5834 	   assert( result != NULL );
5835 	
5836 	   maxWeight = -SCIP_REAL_MAX;
5837 	   branchCons = NULL;
5838 	
5839 	   SCIPdebugMsg(scip, "Enforcing SOS1 constraints <%s>.\n", SCIPconshdlrGetName(conshdlr) );
5840 	   *result = SCIP_FEASIBLE;
5841 	
5842 	   /* get constraint handler data */
5843 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
5844 	   assert( conshdlrdata != NULL );
5845 	
5846 	   /* check each constraint */
5847 	   for (c = 0; c < nconss; ++c)
5848 	   {
5849 	      SCIP_CONS* cons;
5850 	      SCIP_Bool cutoff;
5851 	      SCIP_Real weight;
5852 	      int ngen;
5853 	      int cnt;
5854 	      int j;
5855 	
5856 	      cons = conss[c];
5857 	      assert( cons != NULL );
5858 	      consdata = SCIPconsGetData(cons);
5859 	      assert( consdata != NULL );
5860 	
5861 	      ngen = 0;
5862 	      cnt = 0;
5863 	      nvars = consdata->nvars;
5864 	      vars = consdata->vars;
5865 	
5866 	      /* do nothing if there are not enough variables - this is usually eliminated by preprocessing */
5867 	      if ( nvars < 2 )
5868 	         continue;
5869 	
5870 	      /* first perform propagation (it might happen that standard propagation is turned off) */
5871 	      SCIP_CALL( propConsSOS1(scip, cons, consdata, &cutoff, &ngen) );
5872 	      SCIPdebugMsg(scip, "propagating <%s> in enforcing (cutoff: %u, domain reductions: %d).\n", SCIPconsGetName(cons), cutoff, ngen);
5873 	      if ( cutoff )
5874 	      {
5875 	         *result = SCIP_CUTOFF;
5876 	         return SCIP_OKAY;
5877 	      }
5878 	      if ( ngen > 0 )
5879 	      {
5880 	         *result = SCIP_REDUCEDDOM;
5881 	         return SCIP_OKAY;
5882 	      }
5883 	      assert( ngen == 0 );
5884 	
5885 	      /* check constraint */
5886 	      weight = 0.0;
5887 	      for (j = 0; j < nvars; ++j)
5888 	      {
5889 	         SCIP_Real val = REALABS(SCIPgetSolVal(scip, sol, vars[j]));
5890 	
5891 	         if ( ! SCIPisFeasZero(scip, val) )
5892 	         {
5893 	            if ( conshdlrdata->branchnonzeros )
5894 	               weight += 1.0;
5895 	            else
5896 	            {
5897 	               if ( conshdlrdata->branchweight && consdata->weights != NULL )
5898 	               {
5899 	                  /* choose maximum nonzero-variable weight */
5900 	                  if ( consdata->weights[j] > weight )
5901 	                     weight = consdata->weights[j];
5902 	               }
5903 	               else
5904 	                  weight += val;
5905 	            }
5906 	            ++cnt;
5907 	         }
5908 	      }
5909 	      /* if constraint is violated */
5910 	      if ( cnt > 1 && weight > maxWeight )
5911 	      {
5912 	         maxWeight = weight;
5913 	         branchCons = cons;
5914 	      }
5915 	   }
5916 	
5917 	   /* if all constraints are feasible */
5918 	   if ( branchCons == NULL )
5919 	   {
5920 	      SCIPdebugMsg(scip, "All SOS1 constraints are feasible.\n");
5921 	      return SCIP_OKAY;
5922 	   }
5923 	
5924 	   /* if we should leave branching decision to branching rules */
5925 	   if ( ! conshdlrdata->branchsos )
5926 	   {
5927 	      int j;
5928 	
5929 	      consdata = SCIPconsGetData(branchCons);
5930 	      for (j = 0; j < consdata->nvars; ++j)
5931 	      {
5932 	         if ( ! SCIPvarIsBinary(consdata->vars[j]) )
5933 	            break;
5934 	      }
5935 	
5936 	      if ( j == consdata->nvars )
5937 	      {
5938 	         *result = SCIP_INFEASIBLE;
5939 	         return SCIP_OKAY;
5940 	      }
5941 	      else
5942 	      {
5943 	         SCIPerrorMessage("Incompatible parameter setting: branchsos can only be set to false if all SOS1 variables are binary.\n");
5944 	         return SCIP_PARAMETERWRONGVAL;
5945 	      }
5946 	   }
5947 	
5948 	   /* otherwise create branches */
5949 	   SCIPdebugMsg(scip, "Branching on constraint <%s> (weight: %f).\n", SCIPconsGetName(branchCons), maxWeight);
5950 	   consdata = SCIPconsGetData(branchCons);
5951 	   assert( consdata != NULL );
5952 	   nvars = consdata->nvars;
5953 	   vars = consdata->vars;
5954 	
5955 	   if ( nvars == 2 )
5956 	   {
5957 	      SCIP_Bool infeasible;
5958 	
5959 	      /* constraint is infeasible: */
5960 	      assert( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, vars[0])) && ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, vars[1])) );
5961 	
5962 	      /* create branches */
5963 	      SCIPdebugMsg(scip, "Creating two branches.\n");
5964 	
5965 	      SCIP_CALL( SCIPcreateChild(scip, &node1, SCIPcalcNodeselPriority(scip, vars[0], SCIP_BRANCHDIR_DOWNWARDS, 0.0), SCIPcalcChildEstimate(scip, vars[0], 0.0) ) );
5966 	      SCIP_CALL( fixVariableZeroNode(scip, vars[0], node1, &infeasible) );
5967 	      assert( ! infeasible );
5968 	
5969 	      SCIP_CALL( SCIPcreateChild(scip, &node2, SCIPcalcNodeselPriority(scip, vars[1], SCIP_BRANCHDIR_DOWNWARDS, 0.0), SCIPcalcChildEstimate(scip, vars[1], 0.0) ) );
5970 	      SCIP_CALL( fixVariableZeroNode(scip, vars[1], node2, &infeasible) );
5971 	      assert( ! infeasible );
5972 	   }
5973 	   else
5974 	   {
5975 	      SCIP_Bool infeasible;
5976 	      SCIP_Real weight1;
5977 	      SCIP_Real weight2;
5978 	      SCIP_Real nodeselest;
5979 	      SCIP_Real objest;
5980 	      SCIP_Real w;
5981 	      int j;
5982 	      int ind;
5983 	#ifndef NDEBUG
5984 	      int cnt = 0;
5985 	#endif
5986 	
5987 	      weight1 = 0.0;
5988 	      weight2 = 0.0;
5989 	
5990 	      /* compute weight */
5991 	      for (j = 0; j < nvars; ++j)
5992 	      {
5993 	         SCIP_Real val = REALABS(SCIPgetSolVal(scip, sol, vars[j]));
5994 	         weight1 += val * (SCIP_Real) j;
5995 	         weight2 += val;
5996 	
5997 	#ifndef NDEBUG
5998 	         if ( ! SCIPisFeasZero(scip, val) )
5999 	            ++cnt;
6000 	#endif
6001 	      }
6002 	
6003 	      assert( cnt >= 2 );
6004 	      assert( !SCIPisFeasZero(scip, weight2) );
6005 	      w = weight1/weight2;  /*lint !e795*/
6006 	
6007 	      ind = (int) SCIPfloor(scip, w);
6008 	      assert( 0 <= ind && ind < nvars-1 );
6009 	
6010 	      /* branch on variable ind: either all variables up to ind or all variables after ind are zero */
6011 	      SCIPdebugMsg(scip, "Branching on variable <%s>.\n", SCIPvarGetName(vars[ind]));
6012 	
6013 	      /* calculate node selection and objective estimate for node 1 */
6014 	      nodeselest = 0.0;
6015 	      objest = SCIPgetLocalTransEstimate(scip);
6016 	      for (j = 0; j <= ind; ++j)
6017 	      {
6018 	         objest += SCIPcalcChildEstimateIncrease(scip, vars[j], SCIPgetSolVal(scip, sol, vars[j]), 0.0);
6019 	         nodeselest += SCIPcalcNodeselPriority(scip, vars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
6020 	      }
6021 	      assert( objest >= SCIPgetLocalTransEstimate(scip) );
6022 	
6023 	      /* create node 1 */
6024 	      SCIP_CALL( SCIPcreateChild(scip, &node1, nodeselest, objest) );
6025 	      for (j = 0; j <= ind; ++j)
6026 	      {
6027 	         SCIP_CALL( fixVariableZeroNode(scip, vars[j], node1, &infeasible) );
6028 	         assert( ! infeasible );
6029 	      }
6030 	
6031 	      /* calculate node selection and objective estimate for node 1 */
6032 	      nodeselest = 0.0;
6033 	      objest = SCIPgetLocalTransEstimate(scip);
6034 	      for (j = ind+1; j < nvars; ++j)
6035 	      {
6036 	         objest += SCIPcalcChildEstimateIncrease(scip, vars[j], SCIPgetSolVal(scip, sol, vars[j]), 0.0);
6037 	         nodeselest += SCIPcalcNodeselPriority(scip, vars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
6038 	      }
6039 	      assert( objest >= SCIPgetLocalTransEstimate(scip) );
6040 	
6041 	      /* create node 2 */
6042 	      SCIP_CALL( SCIPcreateChild(scip, &node2, nodeselest, objest) );
6043 	      for (j = ind+1; j < nvars; ++j)
6044 	      {
6045 	         SCIP_CALL( fixVariableZeroNode(scip, vars[j], node2, &infeasible) );
6046 	         assert( ! infeasible );
6047 	      }
6048 	   }
6049 	   SCIP_CALL( SCIPresetConsAge(scip, branchCons) );
6050 	   *result = SCIP_BRANCHED;
6051 	
6052 	   return SCIP_OKAY;
6053 	}
6054 	
6055 	
6056 	/** constraint enforcing method of constraint handler */
6057 	static
6058 	SCIP_RETCODE enforceSOS1(
6059 	   SCIP*                 scip,               /**< SCIP pointer */
6060 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
6061 	   int                   nconss,             /**< number of constraints */
6062 	   SCIP_CONS**           conss,              /**< indicator constraints */
6063 	   SCIP_SOL*             sol,                /**< solution to be enforced (NULL for LP solution) */
6064 	   SCIP_RESULT*          result              /**< result */
6065 	   )
6066 	{
6067 	   SCIP_CONSHDLRDATA* conshdlrdata;
6068 	
6069 	   assert( scip != NULL );
6070 	   assert( conshdlr != NULL );
6071 	   assert( conss != NULL );
6072 	   assert( result != NULL );
6073 	
6074 	   /* get constraint handler data */
6075 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
6076 	   assert( conshdlrdata != NULL );
6077 	
6078 	   if ( conshdlrdata->addcomps && conshdlrdata->fixnonzero )
6079 	   {
6080 	      SCIPerrorMessage("Incompatible parameter setting: addcomps = TRUE and fixnonzero = TRUE.\n");
6081 	      return SCIP_PARAMETERWRONGVAL;
6082 	   }
6083 	
6084 	   if ( conshdlrdata->fixnonzero && ( conshdlrdata->branchingrule == 'b' || conshdlrdata->branchingrule == 's' ) )
6085 	   {
6086 	      SCIPerrorMessage("Incompatible parameter setting: nonzero fixing is not compatible with bipartite or sos1 branching.\n");
6087 	      return SCIP_PARAMETERWRONGVAL;
6088 	   }
6089 	
6090 	   if ( conshdlrdata->branchingrule == 's' && conshdlrdata->nstrongrounds != 0 )
6091 	   {
6092 	      SCIPerrorMessage("Strong branching is not available for SOS1 branching.\n");
6093 	      return SCIP_PARAMETERWRONGVAL;
6094 	   }
6095 	
6096 	   if ( conshdlrdata->branchingrule == 's' || conshdlrdata->switchsos1branch )
6097 	   {
6098 	      /* enforce SOS1 constraints */
6099 	      SCIP_CALL( enforceConssSOS1(scip, conshdlr, nconss, conss, sol, result) );
6100 	   }
6101 	   else
6102 	   {
6103 	      if ( conshdlrdata->branchingrule != 'n' && conshdlrdata->branchingrule != 'b' )
6104 	      {
6105 	         SCIPerrorMessage("branching rule %c unknown\n", conshdlrdata->branchingrule);
6106 	         return SCIP_PARAMETERWRONGVAL;
6107 	      }
6108 	
6109 	      /* enforce conflict graph */
6110 	      SCIP_CALL( enforceConflictgraph(scip, conshdlrdata, conshdlr, nconss, conss, sol, result) );
6111 	   }
6112 	
6113 	   return SCIP_OKAY;
6114 	}
6115 	
6116 	
6117 	/* ----------------------------- separation ------------------------------------*/
6118 	
6119 	/** initialitze tclique graph and create clique data */
6120 	static
6121 	SCIP_RETCODE initTCliquegraph(
6122 	   SCIP*                 scip,               /**< SCIP pointer */
6123 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
6124 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
6125 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
6126 	   int                   nsos1vars           /**< number of SOS1 variables */
6127 	   )
6128 	{
6129 	   TCLIQUE_DATA* tcliquedata;
6130 	   int j;
6131 	
6132 	   /* try to generate bound cuts */
6133 	   if ( ! tcliqueCreate(&conshdlrdata->tcliquegraph) )
6134 	      return SCIP_NOMEMORY;
6135 	
6136 	   /* add nodes */
6137 	   for (j = 0; j < nsos1vars; ++j)
6138 	   {
6139 	      if ( ! tcliqueAddNode(conshdlrdata->tcliquegraph, j, 0 ) )
6140 	         return SCIP_NOMEMORY;
6141 	   }
6142 	
6143 	   /* add edges */
6144 	   for (j = 0; j < nsos1vars; ++j)
6145 	   {
6146 	      int* succ;
6147 	      int nsucc;
6148 	      int succnode;
6149 	      int i;
6150 	
6151 	      nsucc = SCIPdigraphGetNSuccessors(conflictgraph, j);
6152 	      succ = SCIPdigraphGetSuccessors(conflictgraph, j);
6153 	
6154 	      for (i = 0; i < nsucc; ++i)
6155 	      {
6156 	         succnode = succ[i];
6157 	
6158 	         if ( succnode > j && SCIPvarIsActive(SCIPnodeGetVarSOS1(conflictgraph, succnode)) )
6159 	         {
6160 	            if ( ! tcliqueAddEdge(conshdlrdata->tcliquegraph, j, succnode) )
6161 	               return SCIP_NOMEMORY;
6162 	         }
6163 	      }
6164 	   }
6165 	
6166 	   if ( ! tcliqueFlush(conshdlrdata->tcliquegraph) )
6167 	      return SCIP_NOMEMORY;
6168 	
6169 	   /* allocate clique data */
6170 	   SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata->tcliquedata) );
6171 	   tcliquedata = conshdlrdata->tcliquedata;
6172 	
6173 	   /* initialize clique data */
6174 	   tcliquedata->scip = scip;
6175 	   tcliquedata->sol = NULL;
6176 	   tcliquedata->conshdlr = conshdlr;
6177 	   tcliquedata->conflictgraph = conflictgraph;
6178 	   tcliquedata->scaleval = 1000.0;
6179 	   tcliquedata->ncuts = 0;
6180 	   tcliquedata->nboundcuts = conshdlrdata->nboundcuts;
6181 	   tcliquedata->strthenboundcuts = conshdlrdata->strthenboundcuts;
6182 	   tcliquedata->maxboundcuts = conshdlrdata->maxboundcutsroot;
6183 	
6184 	   return SCIP_OKAY;
6185 	}
6186 	
6187 	
6188 	/** update weights of tclique graph */
6189 	static
6190 	SCIP_RETCODE updateWeightsTCliquegraph(
6191 	   SCIP*                 scip,               /**< SCIP pointer */
6192 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
6193 	   TCLIQUE_DATA*         tcliquedata,        /**< tclique data */
6194 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
6195 	   SCIP_SOL*             sol,                /**< LP solution to be separated (or NULL) */
6196 	   int                   nsos1vars           /**< number of SOS1 variables */
6197 	   )
6198 	{
6199 	   SCIP_Real scaleval;
6200 	   int j;
6201 	
6202 	   scaleval = tcliquedata->scaleval;
6203 	
6204 	   for (j = 0; j < nsos1vars; ++j)
6205 	   {
6206 	      SCIP_Real solval;
6207 	      SCIP_Real bound;
6208 	      SCIP_VAR* var;
6209 	
6210 	      var = SCIPnodeGetVarSOS1(conflictgraph, j);
6211 	      solval = SCIPgetSolVal(scip, sol, var);
6212 	
6213 	      if ( SCIPisFeasPositive(scip, solval) )
6214 	      {
6215 	         if ( conshdlrdata->strthenboundcuts )
6216 	            bound = REALABS( nodeGetSolvalVarboundUbSOS1(scip, conflictgraph, sol, j) );
6217 	         else
6218 	            bound = REALABS( SCIPvarGetUbLocal(var) );
6219 	      }
6220 	      else if ( SCIPisFeasNegative(scip, solval) )
6221 	      {
6222 	         if ( conshdlrdata->strthenboundcuts )
6223 	            bound = REALABS( nodeGetSolvalVarboundLbSOS1(scip, conflictgraph, sol, j) );
6224 	         else
6225 	            bound = REALABS( SCIPvarGetLbLocal(var) );
6226 	      }
6227 	      else
6228 	         bound = 0.0;
6229 	
6230 	      solval = REALABS( solval );
6231 	
6232 	      if ( ! SCIPisFeasZero(scip, bound) && ! SCIPisInfinity(scip, bound) )
6233 	      {
6234 	         SCIP_Real nodeweight;
6235 	         nodeweight = REALABS( solval/bound ) * scaleval;/*lint !e414*/
6236 	         tcliqueChangeWeight(conshdlrdata->tcliquegraph, j, (int)nodeweight);
6237 	      }
6238 	      else
6239 	      {
6240 	         tcliqueChangeWeight(conshdlrdata->tcliquegraph, j, 0);
6241 	      }
6242 	   }
6243 	
6244 	   return SCIP_OKAY;
6245 	}
6246 	
6247 	
6248 	/** adds bound cut(s) to separation storage */
6249 	static
6250 	SCIP_RETCODE addBoundCutSepa(
6251 	   SCIP*                 scip,               /**< SCIP pointer */
6252 	   TCLIQUE_DATA*         tcliquedata,        /**< clique data */
6253 	   SCIP_ROW*             rowlb,              /**< row for lower bounds (or NULL) */
6254 	   SCIP_ROW*             rowub,              /**< row for upper bounds (or NULL) */
6255 	   SCIP_Bool*            success,            /**< pointer to store if bound cut was added */
6256 	   SCIP_Bool*            cutoff              /**< pointer to store if a cutoff occurred */
6257 	   )
6258 	{
6259 	   assert( scip != NULL );
6260 	   assert( tcliquedata != NULL );
6261 	   assert( success != NULL);
6262 	   assert( cutoff != NULL );
6263 	
6264 	   *success = FALSE;
6265 	   *cutoff = FALSE;
6266 	
6267 	   /* add cut for lower bounds */
6268 	   if ( rowlb != NULL )
6269 	   {
6270 	      if ( ! SCIProwIsInLP(rowlb) && SCIPisCutEfficacious(scip, NULL, rowlb) )
6271 	      {
6272 	         SCIP_Bool infeasible;
6273 	
6274 	         SCIP_CALL( SCIPaddRow(scip, rowlb, FALSE, &infeasible) );
6275 	         if ( infeasible )
6276 	            *cutoff = TRUE;
6277 	         SCIPdebug( SCIP_CALL( SCIPprintRow(scip, rowlb, NULL) ) );
6278 	         ++tcliquedata->nboundcuts;
6279 	         ++tcliquedata->ncuts;
6280 	         *success = TRUE;
6281 	      }
6282 	   }
6283 	
6284 	   /* add cut for upper bounds */
6285 	   if ( rowub != NULL )
6286 	   {
6287 	      if ( ! SCIProwIsInLP(rowub) && SCIPisCutEfficacious(scip, NULL, rowub) )
6288 	      {
6289 	         SCIP_Bool infeasible;
6290 	
6291 	         SCIP_CALL( SCIPaddRow(scip, rowub, FALSE, &infeasible) );
6292 	         if ( infeasible )
6293 	            *cutoff = TRUE;
6294 	         SCIPdebug( SCIP_CALL( SCIPprintRow(scip, rowub, NULL) ) );
6295 	         ++tcliquedata->nboundcuts;
6296 	         ++tcliquedata->ncuts;
6297 	         *success = TRUE;
6298 	      }
6299 	   }
6300 	
6301 	   return SCIP_OKAY;
6302 	}
6303 	
6304 	
6305 	/** Generate bound constraint
6306 	 *
6307 	 *  We generate the row corresponding to the following simple valid inequalities:
6308 	 *  \f[
6309 	 *         \frac{x_1}{u_1} + \ldots + \frac{x_n}{u_n} \leq 1\qquad\mbox{and}\qquad
6310 	 *         \frac{x_1}{\ell_1} + \ldots + \frac{x_n}{\ell_1} \leq 1,
6311 	 *  \f]
6312 	 *  where \f$\ell_1, \ldots, \ell_n\f$ and \f$u_1, \ldots, u_n\f$ are the nonzero and finite lower and upper bounds of
6313 	 *  the variables \f$x_1, \ldots, x_n\f$. If an upper bound < 0 or a lower bound > 0, the constraint itself is
6314 	 *  redundant, so the cut is not applied (lower bounds > 0 and upper bounds < 0 are usually detected in presolving or
6315 	 *  propagation). Infinite bounds and zero are skipped. Thus \f$\ell_1, \ldots, \ell_n\f$ are all negative, which
6316 	 *  results in the \f$\leq\f$ inequality. In case of the presence of variable upper bounds, the bound inequality can
6317 	 *  be further strengthened.
6318 	 *
6319 	 *  Note that in fact, any mixture of nonzero finite lower and upper bounds would lead to a valid inequality as
6320 	 *  above. However, usually either the lower or upper bound is nonzero. Thus, the above inequalities are the most
6321 	 *  interesting.
6322 	 */
6323 	static
6324 	SCIP_RETCODE generateBoundInequalityFromSOS1Nodes(
6325 	   SCIP*                 scip,               /**< SCIP pointer */
6326 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
6327 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
6328 	   int*                  nodes,              /**< conflict graph nodes for bound constraint */
6329 	   int                   nnodes,             /**< number of conflict graph nodes for bound constraint */
6330 	   SCIP_Real             rhs,                /**< right hand side of bound constraint */
6331 	   SCIP_Bool             local,              /**< in any case produce a local cut (even if local bounds of variables are valid globally) */
6332 	   SCIP_Bool             global,             /**< in any case produce a global cut */
6333 	   SCIP_Bool             strengthen,         /**< whether trying to strengthen bound constraint */
6334 	   SCIP_Bool             removable,          /**< should the inequality be removed from the LP due to aging or cleanup? */
6335 	   const char*           nameext,            /**< part of name of bound constraints */
6336 	   SCIP_ROW**            rowlb,              /**< output: row for lower bounds (or NULL if not needed) */
6337 	   SCIP_ROW**            rowub               /**< output: row for upper bounds (or NULL if not needed) */
6338 	   )
6339 	{
6340 	   char name[SCIP_MAXSTRLEN];
6341 	   SCIP_VAR* lbboundvar = NULL;
6342 	   SCIP_VAR* ubboundvar = NULL;
6343 	   SCIP_Bool locallbs;
6344 	   SCIP_Bool localubs;
6345 	   SCIP_VAR** vars;
6346 	   SCIP_Real* vals;
6347 	
6348 	   assert( scip != NULL );
6349 	   assert( conshdlr != NULL );
6350 	   assert( conflictgraph != NULL );
6351 	   assert( ! local || ! global );
6352 	   assert( nodes != NULL );
6353 	
6354 	   /* allocate buffer array */
6355 	   SCIP_CALL( SCIPallocBufferArray(scip, &vars, nnodes+1) );
6356 	   SCIP_CALL( SCIPallocBufferArray(scip, &vals, nnodes+1) );
6357 	
6358 	   /* take care of upper bounds */
6359 	   if ( rowub != NULL )
6360 	   {
6361 	      SCIP_Bool useboundvar;
6362 	      int cnt = 0;
6363 	      int j;
6364 	
6365 	      /* Loop through all variables. We check whether all bound variables (if existent) are equal; if this is the
6366 	       * case then the bound constraint can be strengthened */
6367 	      localubs = local;
6368 	      useboundvar = strengthen;
6369 	      for (j = 0; j < nnodes; ++j)
6370 	      {
6371 	         SCIP_NODEDATA* nodedata;
6372 	         SCIP_VAR* var;
6373 	         SCIP_Real val;
6374 	
6375 	         nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, nodes[j]);
6376 	         assert( nodedata != NULL );
6377 	         var = nodedata->var;
6378 	         assert( var != NULL );
6379 	
6380 	         /* if variable is not involved in a variable bound constraint */
6381 	         if ( ! useboundvar || nodedata->ubboundvar == NULL )
6382 	         {
6383 	            useboundvar = FALSE;
6384 	            if ( localubs )
6385 	            {
6386 	               assert( ! global );
6387 	               val = SCIPvarGetUbLocal(var);
6388 	            }
6389 	            else
6390 	            {
6391 	               val = SCIPvarGetUbGlobal(var);
6392 	               if ( ! global && ! SCIPisFeasEQ(scip, val, SCIPvarGetUbLocal(var)) )
6393 	               {
6394 	                  localubs = TRUE;
6395 	                  val = SCIPvarGetUbLocal(var);
6396 	               }
6397 	            }
6398 	         }
6399 	         else
6400 	         {
6401 	            /* in this case the cut is always valid globally */
6402 	
6403 	            /* if we have a bound variable for the first time */
6404 	            if ( ubboundvar == NULL )
6405 	            {
6406 	               ubboundvar = nodedata->ubboundvar;
6407 	               val = nodedata->ubboundcoef;
6408 	            }
6409 	            /* else if the bound variable equals the stored bound variable */
6410 	            else if ( ubboundvar == nodedata->ubboundvar )
6411 	               val = nodedata->ubboundcoef;
6412 	            else /* else use bounds on the variables */
6413 	            {
6414 	               useboundvar = FALSE;
6415 	
6416 	               /* restart 'for'-loop */
6417 	               j = -1;  /*lint !e850*/
6418 	               cnt = 0;
6419 	               continue;
6420 	            }
6421 	         }
6422 	
6423 	         /* should not apply the cut if a variable is fixed to be negative -> constraint is redundant */
6424 	         if ( SCIPisNegative(scip, val) )
6425 	            break;
6426 	
6427 	         /* store variable if relevant for bound inequality */
6428 	         if ( ! SCIPisInfinity(scip, val) && ! SCIPisZero(scip, val) )
6429 	         {
6430 	            vars[cnt] = var;
6431 	
6432 	            /* if only two nodes then we scale the cut differently */
6433 	            if ( nnodes == 2 )
6434 	               vals[cnt++] = val;
6435 	            else
6436 	               vals[cnt++] = 1.0/val;
6437 	         }
6438 	      }
6439 	
6440 	      /* if cut is meaningful */
6441 	      if ( j == nnodes && cnt >= 2 )/*lint !e850*/
6442 	      {
6443 	         /* if only two nodes then we scale the cut differently */
6444 	         if ( nnodes == 2 )
6445 	         {
6446 	            SCIP_Real save;
6447 	
6448 	            save = vals[0];
6449 	            vals[0] = vals[1];
6450 	            vals[1] = save;
6451 	            rhs = rhs * vals[0] * vals[1];
6452 	            assert( (! useboundvar && cnt == 2 ) || (useboundvar && cnt == 3 ) );
6453 	         }
6454 	
6455 	         if ( useboundvar )
6456 	         {
6457 	            /* add bound variable to array */
6458 	            vars[cnt] = ubboundvar;
6459 	            vals[cnt++] = -rhs;
6460 	            assert(ubboundvar != NULL );
6461 	
6462 	            /* create upper bound inequality if at least two of the bounds are finite and nonzero */
6463 	            (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "sosub#%s", nameext);
6464 	            SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, rowub, conshdlr, name, -SCIPinfinity(scip), 0.0, localubs, FALSE, removable) );
6465 	            SCIP_CALL( SCIPaddVarsToRow(scip, *rowub, cnt, vars, vals) );
6466 	            SCIPdebug( SCIP_CALL( SCIPprintRow(scip, *rowub, NULL) ) );
6467 	         }
6468 	         else
6469 	         {
6470 	            /* create upper bound inequality if at least two of the bounds are finite and nonzero */
6471 	            (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "sosub#%s", nameext);
6472 	            SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, rowub, conshdlr, name, -SCIPinfinity(scip), rhs, localubs, FALSE, removable) );
6473 	            SCIP_CALL( SCIPaddVarsToRow(scip, *rowub, cnt, vars, vals) );
6474 	            SCIPdebug( SCIP_CALL( SCIPprintRow(scip, *rowub, NULL) ) );
6475 	         }
6476 	      }
6477 	   }
6478 	
6479 	   /* take care of lower bounds */
6480 	   if ( rowlb != NULL )
6481 	   {
6482 	      SCIP_Bool useboundvar;
6483 	      int cnt = 0;
6484 	      int j;
6485 	
6486 	      /* loop through all variables. We check whether all bound variables (if existent) are equal; if this is the
6487 	       * case then the bound constraint can be strengthened */
6488 	      locallbs = local;
6489 	      useboundvar = strengthen;
6490 	      for (j = 0; j < nnodes; ++j)
6491 	      {
6492 	         SCIP_NODEDATA* nodedata;
6493 	         SCIP_VAR* var;
6494 	         SCIP_Real val;
6495 	
6496 	         nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, nodes[j]);
6497 	         assert( nodedata != NULL );
6498 	         var = nodedata->var;
6499 	         assert( var != NULL );
6500 	
6501 	         /* if variable is not involved in a variable bound constraint */
6502 	         if ( ! useboundvar || nodedata->lbboundvar == NULL )
6503 	         {
6504 	            useboundvar = FALSE;
6505 	            if ( locallbs )
6506 	            {
6507 	               assert( ! global );
6508 	               val = SCIPvarGetLbLocal(var);
6509 	            }
6510 	            else
6511 	            {
6512 	               val = SCIPvarGetLbGlobal(var);
6513 	               if ( ! global && ! SCIPisFeasEQ(scip, val, SCIPvarGetLbLocal(var)) )
6514 	               {
6515 	                  locallbs = TRUE;
6516 	                  val = SCIPvarGetLbLocal(var);
6517 	               }
6518 	            }
6519 	         }
6520 	         else
6521 	         {
6522 	            /* in this case the cut is always valid globally */
6523 	
6524 	            /* if we have a bound variable for the first time */
6525 	            if ( lbboundvar == NULL )
6526 	            {
6527 	               lbboundvar = nodedata->lbboundvar;
6528 	               val = nodedata->lbboundcoef;
6529 	            }
6530 	            /* else if the bound variable equals the stored bound variable */
6531 	            else if ( SCIPvarCompare(lbboundvar, nodedata->lbboundvar) == 0 )
6532 	            {
6533 	               val = nodedata->lbboundcoef;
6534 	            }
6535 	            else /* else use bounds on the variables */
6536 	            {
6537 	               useboundvar = FALSE;
6538 	
6539 	               /* restart 'for'-loop */
6540 	               j = -1;  /*lint !e850*/
6541 	               cnt = 0;
6542 	               continue;
6543 	            }
6544 	         }
6545 	
6546 	         /* should not apply the cut if a variable is fixed to be positive -> constraint is redundant */
6547 	         if ( SCIPisPositive(scip, val) )
6548 	            break;
6549 	
6550 	         /* store variable if relevant for bound inequality */
6551 	         if ( ! SCIPisInfinity(scip, -val) && ! SCIPisZero(scip, val) )
6552 	         {
6553 	            vars[cnt] = var;
6554 	
6555 	            /* if only two nodes then we scale the cut differently */
6556 	            if ( nnodes == 2 )
6557 	               vals[cnt++] = val;
6558 	            else
6559 	               vals[cnt++] = 1.0/val;
6560 	         }
6561 	      }
6562 	
6563 	      /* if cut is meaningful */
6564 	      if ( j == nnodes && cnt >= 2 )/*lint !e850*/
6565 	      {
6566 	         /* if only two nodes then we scale the cut differently */
6567 	         if ( nnodes == 2 )
6568 	         {
6569 	            SCIP_Real save;
6570 	
6571 	            save = vals[0];
6572 	            vals[0] = vals[1];
6573 	            vals[1] = save;
6574 	            rhs = rhs * vals[0] * vals[1];
6575 	            assert( (! useboundvar && cnt == 2 ) || (useboundvar && cnt == 3 ) );
6576 	         }
6577 	
6578 	         if ( useboundvar )
6579 	         {
6580 	            /* add bound variable to array */
6581 	            vars[cnt] = lbboundvar;
6582 	            vals[cnt++] = -rhs;
6583 	            assert(lbboundvar != NULL );
6584 	
6585 	            /* create upper bound inequality if at least two of the bounds are finite and nonzero */
6586 	            (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "soslb#%s", nameext);
6587 	            SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, rowlb, conshdlr, name, -SCIPinfinity(scip), 0.0, locallbs, FALSE, TRUE) );
6588 	            SCIP_CALL( SCIPaddVarsToRow(scip, *rowlb, cnt, vars, vals) );
6589 	            SCIPdebug( SCIP_CALL( SCIPprintRow(scip, *rowlb, NULL) ) );
6590 	         }
6591 	         else
6592 	         {
6593 	            /* create upper bound inequality if at least two of the bounds are finite and nonzero */
6594 	            (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "soslb#%s", nameext);
6595 	            SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, rowlb, conshdlr, name, -SCIPinfinity(scip), rhs, locallbs, FALSE, TRUE) );
6596 	            SCIP_CALL( SCIPaddVarsToRow(scip, *rowlb, cnt, vars, vals) );
6597 	            SCIPdebug( SCIP_CALL( SCIPprintRow(scip, *rowlb, NULL) ) );
6598 	         }
6599 	      }
6600 	   }
6601 	
6602 	   /* free buffer array */
6603 	   SCIPfreeBufferArray(scip, &vals);
6604 	   SCIPfreeBufferArray(scip, &vars);
6605 	
6606 	   return SCIP_OKAY;
6607 	}
6608 	
6609 	
6610 	/** generates bound cuts using a clique found by algorithm for maximum weight clique
6611 	 *  and decides whether to stop generating cliques with the algorithm for maximum weight clique
6612 	 */
6613 	static
6614 	TCLIQUE_NEWSOL(tcliqueNewsolClique)
6615 	{
6616 	   TCLIQUE_WEIGHT minweightinc;
6617 	
6618 	   assert( acceptsol != NULL );
6619 	   assert( stopsolving != NULL );
6620 	   assert( tcliquedata != NULL );
6621 	
6622 	   /* we don't accept the solution as new incumbent, because we want to find many violated clique inequalities */
6623 	   *acceptsol = FALSE;
6624 	   *stopsolving = FALSE;
6625 	
6626 	   /* slightly increase the minimal weight for additional cliques */
6627 	   minweightinc = (cliqueweight - *minweight)/10;
6628 	   minweightinc = MAX(minweightinc, 1);
6629 	   *minweight += minweightinc;
6630 	
6631 	   /* adds cut if weight of the clique is greater than 1 */
6632 	   if( cliqueweight > tcliquedata->scaleval )
6633 	   {
6634 	      SCIP* scip;
6635 	      SCIP_SOL* sol;
6636 	      SCIP_Real unscaledweight;
6637 	      SCIP_Real solval;
6638 	      SCIP_Real bound;
6639 	      SCIP_VAR* var;
6640 	      int node;
6641 	      int i;
6642 	
6643 	      scip = tcliquedata->scip;
6644 	      sol = tcliquedata->sol;
6645 	      assert( scip != NULL );
6646 	
6647 	      /* calculate the weight of the clique in unscaled fractional variable space */
6648 	      unscaledweight = 0.0;
6649 	      for( i = 0; i < ncliquenodes; i++ )
6650 	      {
6651 	         node = cliquenodes[i];
6652 	         var = SCIPnodeGetVarSOS1(tcliquedata->conflictgraph, node);
6653 	         solval = SCIPgetSolVal(scip, sol, var);
6654 	
6655 	         if ( SCIPisFeasPositive(scip, solval) )
6656 	         {
6657 	            if ( tcliquedata->strthenboundcuts )
6658 	               bound = REALABS( nodeGetSolvalVarboundUbSOS1(scip, tcliquedata->conflictgraph, sol, node) );
6659 	            else
6660 	               bound = REALABS( SCIPvarGetUbLocal(var) );
6661 	         }
6662 	         else if ( SCIPisFeasNegative(scip, solval) )
6663 	         {
6664 	            if ( tcliquedata->strthenboundcuts )
6665 	               bound = REALABS( nodeGetSolvalVarboundLbSOS1(scip, tcliquedata->conflictgraph, sol, node) );
6666 	            else
6667 	               bound = REALABS( SCIPvarGetLbLocal(var) );
6668 	         }
6669 	         else
6670 	            bound = 0.0;
6671 	
6672 	         solval = REALABS( solval );
6673 	
6674 	         if ( ! SCIPisFeasZero(scip, bound) && ! SCIPisInfinity(scip, bound) )
6675 	            unscaledweight += REALABS( solval/bound );/*lint !e414*/
6676 	      }
6677 	
6678 	      if ( SCIPisEfficacious(scip, unscaledweight - 1.0) )
6679 	      {
6680 	         char nameext[SCIP_MAXSTRLEN];
6681 	         SCIP_ROW* rowlb = NULL;
6682 	         SCIP_ROW* rowub = NULL;
6683 	         SCIP_Bool success;
6684 	         SCIP_Bool cutoff;
6685 	
6686 	         /* generate bound inequalities for lower and upper bound case
6687 	          * NOTE: tests have shown that non-removable rows give the best results */
6688 	         (void) SCIPsnprintf(nameext, SCIP_MAXSTRLEN, "%d", tcliquedata->nboundcuts);
6689 	         if ( generateBoundInequalityFromSOS1Nodes(scip, tcliquedata->conshdlr, tcliquedata->conflictgraph,
6690 	               cliquenodes, ncliquenodes, 1.0, FALSE, FALSE, tcliquedata->strthenboundcuts, FALSE, nameext, &rowlb, &rowub) != SCIP_OKAY )
6691 	         {
6692 	            SCIPerrorMessage("Unexpected error in bound cut creation.\n");
6693 	            SCIPABORT();
6694 	            return;   /*lint !e527*/
6695 	         }
6696 	
6697 	         /* add bound cut(s) to separation storage if existent */
6698 	         if ( addBoundCutSepa(scip, tcliquedata, rowlb, rowub, &success, &cutoff) != SCIP_OKAY )
6699 	         {
6700 	            SCIPerrorMessage("Unexpected error in bound cut creation.\n");
6701 	            SCIPABORT();
6702 	            return;   /*lint !e527*/
6703 	         }
6704 	
6705 	         if ( rowlb != NULL )
6706 	         {
6707 	            if ( SCIPreleaseRow(scip, &rowlb) != SCIP_OKAY )
6708 	            {
6709 	               SCIPerrorMessage("Cannot release row,\n");
6710 	               SCIPABORT();
6711 	               return;   /*lint !e527*/
6712 	            }
6713 	         }
6714 	         if ( rowub != NULL )
6715 	         {
6716 	            if ( SCIPreleaseRow(scip, &rowub) != SCIP_OKAY )
6717 	            {
6718 	               SCIPerrorMessage("Cannot release row,\n");
6719 	               SCIPABORT();
6720 	               return;   /*lint !e527*/
6721 	            }
6722 	         }
6723 	
6724 	         /* if at least one cut has been added */
6725 	         if ( success )
6726 	         {
6727 	            SCIPdebugMsg(scip, " -> found bound cut corresponding to clique (act=%g)\n", unscaledweight);
6728 	
6729 	            /* if we found more than half the cuts we are allowed to generate, we accept the clique as new incumbent,
6730 	             * such that only more violated cuts are generated afterwards
6731 	             */
6732 	            if( tcliquedata->maxboundcuts >= 0 )
6733 	            {
6734 	               if ( tcliquedata->ncuts > tcliquedata->maxboundcuts/2 )
6735 	                  *acceptsol = TRUE;
6736 	               if ( tcliquedata->ncuts >= tcliquedata->maxboundcuts )
6737 	                  *stopsolving = TRUE;
6738 	            }
6739 	         }
6740 	         else
6741 	            *stopsolving = TRUE;
6742 	      } /*lint !e438*/
6743 	   }
6744 	}
6745 	
6746 	
6747 	/** separate bound inequalities from conflict graph */
6748 	static
6749 	SCIP_RETCODE sepaBoundInequalitiesFromGraph(
6750 	   SCIP*                 scip,               /**< SCIP pointer */
6751 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
6752 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
6753 	   SCIP_SOL*             sol,                /**< LP solution to be separated (or NULL) */
6754 	   int                   maxboundcuts,       /**< maximal number of bound cuts separated per separation round (-1: no limit) */
6755 	   int*                  ngen,               /**< pointer to store number of cuts generated */
6756 	   SCIP_Bool*            cutoff              /**< pointer whether a cutoff occurred */
6757 	   )
6758 	{
6759 	   SCIP_DIGRAPH* conflictgraph;
6760 	   TCLIQUE_DATA* tcliquedata;
6761 	   TCLIQUE_WEIGHT cliqueweight;
6762 	   TCLIQUE_STATUS tcliquestatus;
6763 	   int nsos1vars;
6764 	
6765 	   SCIP_Real scaleval = 1000.0;                  /* factor for scaling weights */
6766 	   int maxtreenodes = 10000;                     /* maximal number of nodes of b&b tree */
6767 	   int maxzeroextensions = 1000;                 /* maximal number of zero-valued variables extending the clique (-1: no limit) */
6768 	   int backtrackfreq = 1000;                     /* frequency for premature backtracking up to tree level 1 (0: no backtracking) */
6769 	   int ntreenodes;
6770 	   int* cliquenodes;
6771 	   int ncliquenodes;
6772 	
6773 	   assert( scip != NULL );
6774 	   assert( conshdlr != NULL );
6775 	   assert( conshdlrdata != NULL );
6776 	   assert( ngen != NULL );
6777 	
6778 	   /* get conflict graph */
6779 	   conflictgraph = SCIPgetConflictgraphSOS1(conshdlr);
6780 	   assert( conflictgraph != NULL );
6781 	
6782 	   /* get number of SOS1 variables */
6783 	   nsos1vars = SCIPgetNSOS1Vars(conshdlr);
6784 	
6785 	   /* initialize data of tclique graph*/
6786 	   tcliquedata = conshdlrdata->tcliquedata;
6787 	   tcliquedata->scaleval = scaleval;
6788 	   tcliquedata->maxboundcuts = maxboundcuts;
6789 	   tcliquedata->sol = sol;
6790 	   tcliquedata->ncuts = 0;
6791 	   tcliquedata->cutoff = FALSE;
6792 	
6793 	   /* update the weights of the tclique graph */
6794 	   SCIP_CALL( updateWeightsTCliquegraph(scip, conshdlrdata, tcliquedata, conflictgraph, sol, nsos1vars) );
6795 	
6796 	   /* allocate buffer array */
6797 	   SCIP_CALL( SCIPallocBufferArray(scip, &cliquenodes, nsos1vars) );
6798 	
6799 	   /* start algorithm to find maximum weight cliques and use them to generate bound cuts */
6800 	   tcliqueMaxClique(tcliqueGetNNodes, tcliqueGetWeights, tcliqueIsEdge, tcliqueSelectAdjnodes,
6801 	      conshdlrdata->tcliquegraph, tcliqueNewsolClique, tcliquedata,
6802 	      cliquenodes, &ncliquenodes, &cliqueweight, (int)scaleval-1, (int)scaleval+1,
6803 	      maxtreenodes, backtrackfreq, maxzeroextensions, -1, &ntreenodes, &tcliquestatus);
6804 	
6805 	   /* free buffer array */
6806 	   SCIPfreeBufferArray(scip, &cliquenodes);
6807 	
6808 	   /* get number of cuts of current separation round */
6809 	   *ngen = tcliquedata->ncuts;
6810 	
6811 	   /* store whether a cutoff occurred */
6812 	   *cutoff = tcliquedata->cutoff;
6813 	
6814 	   /* update number of bound cuts in separator data */
6815 	   conshdlrdata->nboundcuts = tcliquedata->nboundcuts;
6816 	
6817 	   return SCIP_OKAY;
6818 	}
6819 	
6820 	
6821 	/** Generate a bound constraint from the variables of an SOS1 constraint (see generateBoundInequalityFromSOS1Nodes() for more information) */
6822 	static
6823 	SCIP_RETCODE generateBoundInequalityFromSOS1Cons(
6824 	   SCIP*                 scip,               /**< SCIP pointer */
6825 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
6826 	   SCIP_CONS*            cons,               /**< SOS1 constraint */
6827 	   SCIP_Bool             local,              /**< in any case produce a local cut (even if local bounds of variables are valid globally) */
6828 	   SCIP_Bool             global,             /**< in any case produce a global cut */
6829 	   SCIP_Bool             strengthen,         /**< whether trying to strengthen bound constraint */
6830 	   SCIP_Bool             removable,          /**< should the inequality be removed from the LP due to aging or cleanup? */
6831 	   SCIP_ROW**            rowlb,              /**< output: row for lower bounds (or NULL if not needed) */
6832 	   SCIP_ROW**            rowub               /**< output: row for upper bounds (or NULL if not needed) */
6833 	   )
6834 	{
6835 	   SCIP_CONSHDLRDATA* conshdlrdata;
6836 	   SCIP_CONSDATA* consdata;
6837 	   int* nodes;
6838 	   int nvars;
6839 	   int cnt = 0;
6840 	   int j;
6841 	
6842 	   assert( scip != NULL );
6843 	   assert( conshdlr != NULL );
6844 	   assert( cons != NULL );
6845 	
6846 	   /* get constraint data */
6847 	   consdata = SCIPconsGetData(cons);
6848 	   assert( consdata != NULL );
6849 	   assert( consdata->vars != NULL );
6850 	   nvars = consdata->nvars;
6851 	
6852 	   /* get constraint handler data */
6853 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
6854 	   assert( conshdlrdata != NULL );
6855 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6856 	
6857 	   /* allocate buffer array */
6858 	   SCIP_CALL( SCIPallocBufferArray(scip, &nodes, nvars) );
6859 	
6860 	   /* get nodes in the conflict graph */
6861 	   for (j = 0; j < nvars; ++j)
6862 	   {
6863 	      if ( SCIPisFeasNegative(scip, SCIPvarGetLbLocal(consdata->vars[j])) || SCIPisFeasPositive(scip, SCIPvarGetUbLocal(consdata->vars[j])) )
6864 	      {
6865 	         assert( varGetNodeSOS1(conshdlrdata, consdata->vars[j]) >= 0 );
6866 	         nodes[cnt++] = varGetNodeSOS1(conshdlrdata, consdata->vars[j]);
6867 	      }
6868 	   }
6869 	
6870 	   /* generate bound constraint from conflict graph nodes */
6871 	   if ( cnt > 0 )
6872 	   {
6873 	      SCIP_CALL( generateBoundInequalityFromSOS1Nodes(scip, conshdlr, conshdlrdata->conflictgraph, nodes, cnt, 1.0, local, global,
6874 	            strengthen, removable, SCIPconsGetName(cons), rowlb, rowub) );
6875 	   }
6876 	
6877 	   /* free buffer array */
6878 	   SCIPfreeBufferArray(scip, &nodes);
6879 	
6880 	   return SCIP_OKAY;
6881 	}
6882 	
6883 	
6884 	/** initialize or separate bound inequalities from SOS1 constraints */
6885 	static
6886 	SCIP_RETCODE initsepaBoundInequalityFromSOS1Cons(
6887 	   SCIP*                 scip,               /**< SCIP pointer */
6888 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
6889 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
6890 	   SCIP_CONS**           conss,              /**< SOS1 constraints */
6891 	   int                   nconss,             /**< number of SOS1 constraints */
6892 	   SCIP_SOL*             sol,                /**< LP solution to be separated (or NULL) */
6893 	   SCIP_Bool             solvedinitlp,       /**< TRUE if initial LP relaxation at a node is solved */
6894 	   int                   maxboundcuts,       /**< maximal number of bound cuts separated per separation round (-1: no limit) */
6895 	   int*                  ngen,               /**< pointer to store number of cuts generated (or NULL) */
6896 	   SCIP_Bool*            cutoff              /**< pointer to store whether a cutoff occurred */
6897 	   )
6898 	{
6899 	   int cnt = 0;
6900 	   int c;
6901 	
6902 	   assert( scip != NULL );
6903 	   assert( conshdlrdata != NULL );
6904 	   assert( conss != NULL );
6905 	
6906 	   *cutoff = FALSE;
6907 	
6908 	   for (c = 0; c < nconss; ++c)
6909 	   {
6910 	      SCIP_CONSDATA* consdata;
6911 	      SCIP_ROW* rowub = NULL;
6912 	      SCIP_ROW* rowlb = NULL;
6913 	      SCIP_Bool release = FALSE;
6914 	
6915 	      assert( conss != NULL );
6916 	      assert( conss[c] != NULL );
6917 	      consdata = SCIPconsGetData(conss[c]);
6918 	      assert( consdata != NULL );
6919 	
6920 	      if ( solvedinitlp )
6921 	      {
6922 	         SCIPdebugMsg(scip, "Separating inequalities for SOS1 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
6923 	      }
6924 	      else
6925 	      {
6926 	         SCIPdebugMsg(scip, "Checking for initial rows for SOS1 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
6927 	      }
6928 	
6929 	      /* in case that the SOS1 constraint is local, we always generate new rows - the former rows might be invalid;
6930 	       * otherwise if the SOS1 constraint is global, we only generate rows if not yet done */
6931 	      if ( consdata->local )
6932 	      {
6933 	         SCIP_CALL( generateBoundInequalityFromSOS1Cons(scip, conshdlr, conss[c], TRUE, FALSE, TRUE, FALSE, &rowlb, &rowub) );
6934 	         release = TRUE;
6935 	      }
6936 	      else
6937 	      {
6938 	         if ( consdata->rowub == NULL || consdata->rowlb == NULL )
6939 	         {
6940 	            SCIP_CALL( generateBoundInequalityFromSOS1Cons(scip, conshdlr, conss[c], FALSE, TRUE, TRUE, FALSE,
6941 	                  (consdata->rowlb == NULL) ? &consdata->rowlb : NULL,
6942 	                  (consdata->rowub == NULL) ? &consdata->rowub : NULL) ); /*lint !e826*/
6943 	         }
6944 	         rowub = consdata->rowub;
6945 	         rowlb = consdata->rowlb;
6946 	      }
6947 	
6948 	      /* put corresponding rows into LP */
6949 	      if ( rowub != NULL && ! SCIProwIsInLP(rowub) && ( solvedinitlp || SCIPisCutEfficacious(scip, sol, rowub) ) )
6950 	      {
6951 	         SCIP_CALL( SCIPaddRow(scip, rowub, FALSE, cutoff) );
6952 	         SCIPdebug( SCIP_CALL( SCIPprintRow(scip, rowub, NULL) ) );
6953 	
6954 	         if ( solvedinitlp )
6955 	         {
6956 	            SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
6957 	         }
6958 	         ++cnt;
6959 	      }
6960 	
6961 	      if ( ! (*cutoff) && rowlb != NULL && ! SCIProwIsInLP(rowlb) && ( solvedinitlp || SCIPisCutEfficacious(scip, sol, rowlb) ) )
6962 	      {
6963 	         SCIP_CALL( SCIPaddRow(scip, rowlb, FALSE, cutoff) );
6964 	         SCIPdebug( SCIP_CALL( SCIPprintRow(scip, rowlb, NULL) ) );
6965 	
6966 	         if ( solvedinitlp )
6967 	         {
6968 	            SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
6969 	         }
6970 	         ++cnt;
6971 	      }
6972 	
6973 	      /* release rows if they are local */
6974 	      if ( release )
6975 	      {
6976 	         if ( rowlb != NULL )
6977 	         {
6978 	            SCIP_CALL( SCIPreleaseRow(scip, &rowlb) );
6979 	         }
6980 	         if ( rowub != NULL )
6981 	         {
6982 	            SCIP_CALL( SCIPreleaseRow(scip, &rowub) );
6983 	         }
6984 	      }
6985 	
6986 	      if ( *cutoff || ( maxboundcuts >= 0 && cnt >= maxboundcuts ) )
6987 	         break;
6988 	   }
6989 	
6990 	   /* store number of generated cuts */
6991 	   if ( ngen != NULL )
6992 	      *ngen = cnt;
6993 	
6994 	   return SCIP_OKAY;
6995 	}
6996 	
6997 	
6998 	/** separate implied bound cuts */
6999 	static
7000 	SCIP_RETCODE sepaImplBoundCutsSOS1(
7001 	   SCIP*                 scip,               /**< SCIP pointer */
7002 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
7003 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
7004 	   SCIP_SOL*             sol,                /**< LP solution to be separated (or NULL) */
7005 	   int                   maxcuts,            /**< maximal number of implied bound cuts separated per separation round (-1: no limit) */
7006 	   int*                  ngen,               /**< pointer to store number of cuts generated */
7007 	   SCIP_Bool*            cutoff              /**< pointer whether a cutoff occurred */
7008 	   )
7009 	{
7010 	   SCIP_DIGRAPH* implgraph;
7011 	   SCIP_Bool genbreak;
7012 	   int nimplnodes;
7013 	   int i;
7014 	
7015 	   assert( scip != NULL);
7016 	   assert( conshdlrdata != NULL);
7017 	   assert( conshdlr != NULL);
7018 	   assert( ngen != NULL);
7019 	   assert( cutoff != NULL);
7020 	
7021 	   *cutoff = FALSE;
7022 	   *ngen = 0;
7023 	
7024 	   /* return if conflict graph is not available */
7025 	   if ( conshdlrdata->conflictgraph == NULL )
7026 	      return SCIP_OKAY;
7027 	
7028 	   /* get implication graph  */
7029 	   implgraph = conshdlrdata->implgraph;
7030 	
7031 	   /* create implication graph if not done already */
7032 	   if ( implgraph == NULL )
7033 	   {
7034 	      int nchbds;
7035 	
7036 	      if ( SCIPgetDepth(scip) == 0 )
7037 	      {
7038 	         SCIP_Bool success;
7039 	         SCIP_CALL( initImplGraphSOS1(scip, conshdlrdata, conshdlrdata->conflictgraph, conshdlrdata->nsos1vars, conshdlrdata->maxtightenbds, &nchbds, cutoff, &success) );
7040 	         if ( *cutoff || ! success )
7041 	            return SCIP_OKAY;
7042 	         implgraph = conshdlrdata->implgraph;
7043 	      }
7044 	      else
7045 	      {
7046 	         return SCIP_OKAY;
7047 	      }
7048 	   }
7049 	   nimplnodes = conshdlrdata->nimplnodes;
7050 	   assert( implgraph != NULL );
7051 	   assert( nimplnodes > 0);
7052 	
7053 	   /* exit if implication graph has no arcs between its nodes */
7054 	   if ( SCIPdigraphGetNArcs(implgraph) < 1 )
7055 	      return SCIP_OKAY;
7056 	
7057 	   /* loop through all nodes of the implication graph */
7058 	   genbreak = FALSE;
7059 	   for (i = 0; i < nimplnodes && ! genbreak; ++i)
7060 	   {
7061 	      SCIP_SUCCDATA** succdatas;
7062 	      SCIP_NODEDATA* nodedata;
7063 	      SCIP_Real solval;
7064 	      SCIP_VAR* var;
7065 	      int* succ;
7066 	      int nsucc;
7067 	      int s;
7068 	
7069 	      succdatas = (SCIP_SUCCDATA**) SCIPdigraphGetSuccessorsData(implgraph, i);
7070 	      nodedata = (SCIP_NODEDATA*) SCIPdigraphGetNodeData(implgraph, i);
7071 	      assert( nodedata != NULL );
7072 	      var = nodedata->var;
7073 	      assert( var != NULL );
7074 	      solval = SCIPgetSolVal(scip, sol, var);
7075 	
7076 	      if ( succdatas != NULL && ! SCIPisFeasZero(scip, solval) )
7077 	      {
7078 	         succ = SCIPdigraphGetSuccessors(implgraph, i);
7079 	         nsucc = SCIPdigraphGetNSuccessors(implgraph, i);
7080 	
7081 	         for (s = 0; s < nsucc && ! genbreak; ++s)
7082 	         {
7083 	            SCIP_SUCCDATA* succdata;
7084 	            SCIP_VAR* succvar;
7085 	            SCIP_ROW* cut = NULL;
7086 	            SCIP_Bool bound1lower;
7087 	            SCIP_Bool bound2lower;
7088 	            SCIP_Real solvalsucc;
7089 	            SCIP_Real bound1;
7090 	            SCIP_Real bound2;
7091 	            SCIP_Real lhsrhs;
7092 	            SCIP_Real impl;
7093 	            int k;
7094 	
7095 	            nodedata = (SCIP_NODEDATA*) SCIPdigraphGetNodeData(implgraph, succ[s]);
7096 	            succdata = succdatas[s];
7097 	            assert( nodedata != NULL && succdata != NULL && nodedata->var != NULL );
7098 	            succvar = nodedata->var;
7099 	            solvalsucc = SCIPgetSolVal(scip, sol, succvar);
7100 	
7101 	            /* determine coefficients for bound inequality */
7102 	            assert( ! SCIPisFeasZero(scip, solval) );
7103 	            if ( SCIPisFeasNegative(scip, solval) )
7104 	            {
7105 	               bound1lower = TRUE;
7106 	               bound1 = SCIPvarGetLbGlobal(var);
7107 	            }
7108 	            else
7109 	            {
7110 	               bound1lower = FALSE;
7111 	               bound1 = SCIPvarGetUbGlobal(var);
7112 	            }
7113 	
7114 	            /* handle lower bound upper bound implications */
7115 	            for (k = 0; k < 2; ++k)
7116 	            {
7117 	               if ( k == 0 )
7118 	               {
7119 	                  SCIP_Real lbsucc;
7120 	                  lbsucc = SCIPvarGetLbGlobal(succvar);
7121 	                  if ( SCIPisFeasLT(scip, lbsucc, succdata->lbimpl) )
7122 	                  {
7123 	                     impl = succdata->lbimpl;
7124 	                     bound2 = lbsucc;
7125 	                  }
7126 	                  else
7127 	                     continue;
7128 	               }
7129 	               else
7130 	               {
7131 	                  SCIP_Real ubsucc;
7132 	                  ubsucc = SCIPvarGetUbGlobal(succvar);
7133 	                  if ( SCIPisFeasGT(scip, ubsucc, succdata->ubimpl) )
7134 	                  {
7135 	                     impl = succdata->ubimpl;
7136 	                     bound2 = ubsucc;
7137 	                  }
7138 	                  else
7139 	                     continue;
7140 	               }
7141 	
7142 	               if ( SCIPisInfinity(scip, REALABS(bound1)) || SCIPisInfinity(scip, REALABS(bound2)) )
7143 	                  continue;
7144 	               assert( ! SCIPisInfinity(scip, REALABS(impl)) );
7145 	
7146 	               if ( SCIPisFeasNegative(scip, bound2-impl) )
7147 	                  bound2lower = TRUE;
7148 	               else
7149 	                  bound2lower = FALSE;
7150 	
7151 	               /* determine left/right hand side of bound inequality */
7152 	               lhsrhs = bound1 * bound2;
7153 	
7154 	               /* create cut */
7155 	               if ( bound1lower == bound2lower )
7156 	               {
7157 	                  if ( SCIPisFeasGT(scip, solval * (bound2-impl) + solvalsucc * bound1, lhsrhs) )
7158 	                  {
7159 	                     SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &cut, conshdlr, "", -SCIPinfinity(scip), lhsrhs, FALSE, FALSE, TRUE) );
7160 	                  }
7161 	                  else
7162 	                     continue;
7163 	               }
7164 	               else
7165 	               {
7166 	                  if ( SCIPisFeasLT(scip, solval * (bound2-impl) + solvalsucc * bound1, lhsrhs) )
7167 	                  {
7168 	                     SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &cut, conshdlr, "", lhsrhs, SCIPinfinity(scip), FALSE, FALSE, TRUE) );
7169 	                  }
7170 	                  else
7171 	                     continue;
7172 	               }
7173 	
7174 	               /* add coefficients of variables */
7175 	               SCIP_CALL( SCIPcacheRowExtensions(scip, cut) );
7176 	               SCIP_CALL( SCIPaddVarToRow(scip, cut, var, bound2-impl) );
7177 	               SCIP_CALL( SCIPaddVarToRow(scip, cut, succvar, bound1) );
7178 	               SCIP_CALL( SCIPflushRowExtensions(scip, cut) );
7179 	
7180 	               /* add cut if useful */
7181 	               if ( ! SCIProwIsInLP(cut) && SCIPisCutEfficacious(scip, NULL, cut) )
7182 	               {
7183 	                  SCIP_Bool infeasible;
7184 	                  SCIP_CALL( SCIPaddRow(scip, cut, FALSE, &infeasible) );
7185 	                  if ( infeasible )
7186 	                  {
7187 	                     genbreak = TRUE;
7188 	                     *cutoff = TRUE;
7189 	                     break;
7190 	                  }
7191 	                  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, cut, NULL) ) );
7192 	#ifdef SCIP_DEBUG
7193 	                  if ( k == 0 )
7194 	                  {
7195 	                     SCIPdebugMsg(scip, "added cut for implication %s != 0 -> %s >= %f \n", SCIPvarGetName(var), SCIPvarGetName(succvar), succdata->lbimpl);
7196 	                  }
7197 	                  else
7198 	                  {
7199 	                     SCIPdebugMsg(scip, "added cut for implication %s != 0 -> %s <= %f \n", SCIPvarGetName(var), SCIPvarGetName(succvar), succdata->ubimpl);
7200 	                  }
7201 	#endif
7202 	
7203 	                  ++(*ngen);
7204 	               }
7205 	
7206 	               if ( maxcuts >= 0 && *ngen > maxcuts )
7207 	               {
7208 	                  genbreak = TRUE;
7209 	                  break;
7210 	               }
7211 	            }
7212 	
7213 	            if ( cut != NULL )
7214 	               SCIP_CALL( SCIPreleaseRow(scip, &cut) );
7215 	         }
7216 	      }
7217 	   }
7218 	
7219 	   return SCIP_OKAY;
7220 	}
7221 	
7222 	
7223 	/** separates SOS1 constraints for arbitrary solutions */
7224 	static
7225 	SCIP_RETCODE separateSOS1(
7226 	   SCIP*                 scip,               /**< SCIP pointer */
7227 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
7228 	   SCIP_SOL*             sol,                /**< solution to be separated (or NULL) */
7229 	   int                   nconss,             /**< number of constraints */
7230 	   SCIP_CONS**           conss,              /**< SOS1 constraints */
7231 	   SCIP_RESULT*          result              /**< result */
7232 	   )
7233 	{
7234 	   SCIP_CONSHDLRDATA* conshdlrdata;
7235 	   int depth;
7236 	
7237 	   assert( scip != NULL );
7238 	   assert( conshdlr != NULL );
7239 	   assert( conss != NULL );
7240 	   assert( result != NULL );
7241 	
7242 	   *result = SCIP_DIDNOTRUN;
7243 	
7244 	   if ( nconss == 0 )
7245 	      return SCIP_OKAY;
7246 	
7247 	   /* only separate cuts if we are not close to terminating */
7248 	   if( SCIPisStopped(scip) )
7249 	      return SCIP_OKAY;
7250 	
7251 	   *result = SCIP_DIDNOTFIND;
7252 	
7253 	   /* get constraint handler data */
7254 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
7255 	   assert( conshdlrdata != NULL );
7256 	
7257 	   /* get node depth */
7258 	   depth = SCIPgetDepth(scip);
7259 	
7260 	   /* separate bound (clique) inequalities */
7261 	   if ( conshdlrdata->boundcutsfreq >= 0 &&
7262 	      ( (conshdlrdata->boundcutsfreq == 0 && depth == 0) || (conshdlrdata->boundcutsfreq > 0 && depth % conshdlrdata->boundcutsfreq == 0)) )
7263 	   {
7264 	      int maxboundcuts;
7265 	      int ngen = 0;
7266 	
7267 	      /* determine maximal number of cuts*/
7268 	      if ( depth == 0 )
7269 	         maxboundcuts = conshdlrdata->maxboundcutsroot;
7270 	      else
7271 	         maxboundcuts = conshdlrdata->maxboundcuts;
7272 	
7273 	      if ( maxboundcuts >= 1 )
7274 	      {
7275 	         /* separate bound inequalities from SOS1 constraints */
7276 	         if( conshdlrdata->boundcutsfromsos1 || conshdlrdata->switchcutsfromsos1 )
7277 	         {
7278 	            SCIP_Bool cutoff;
7279 	
7280 	            SCIP_CALL( initsepaBoundInequalityFromSOS1Cons(scip, conshdlr, conshdlrdata, conss, nconss, sol, TRUE, maxboundcuts, &ngen, &cutoff) );
7281 	            if ( cutoff )
7282 	            {
7283 	               *result = SCIP_CUTOFF;
7284 	               return SCIP_OKAY;
7285 	            }
7286 	         }
7287 	
7288 	         /* separate bound inequalities from the conflict graph */
7289 	         if( conshdlrdata->boundcutsfromgraph && ! conshdlrdata->switchcutsfromsos1 )
7290 	         {
7291 	            SCIP_Bool cutoff;
7292 	            SCIP_CALL( sepaBoundInequalitiesFromGraph(scip, conshdlr, conshdlrdata, sol, maxboundcuts, &ngen, &cutoff) );
7293 	            if ( cutoff )
7294 	            {
7295 	               *result = SCIP_CUTOFF;
7296 	               return SCIP_OKAY;
7297 	            }
7298 	         }
7299 	      }
7300 	
7301 	      /* evaluate results */
7302 	      if ( ngen > 0 )
7303 	         *result = SCIP_SEPARATED;
7304 	      SCIPdebugMsg(scip, "Separated %d bound (clique) inequalities.\n", ngen);
7305 	   }
7306 	
7307 	   /* separate implied bound inequalities */
7308 	   if ( conshdlrdata->implcutsfreq >= 0 &&
7309 	      ( (conshdlrdata->implcutsfreq == 0 && depth == 0) || (conshdlrdata->implcutsfreq > 0 && depth % conshdlrdata->implcutsfreq == 0)) )
7310 	   {
7311 	      int maximplcuts;
7312 	      int ngen = 0;
7313 	
7314 	      /* determine maximal number of cuts*/
7315 	      if ( depth == 0 )
7316 	         maximplcuts = conshdlrdata->maximplcutsroot;
7317 	      else
7318 	         maximplcuts = conshdlrdata->maximplcuts;
7319 	
7320 	      /* call separator for implied bound cuts */
7321 	      if ( maximplcuts >= 1 )
7322 	      {
7323 	         SCIP_Bool cutoff;
7324 	         SCIP_CALL( sepaImplBoundCutsSOS1(scip, conshdlr, conshdlrdata, sol, maximplcuts, &ngen, &cutoff) );
7325 	         if ( cutoff )
7326 	         {
7327 	            *result = SCIP_CUTOFF;
7328 	            return SCIP_OKAY;
7329 	         }
7330 	      }
7331 	
7332 	      /* evaluate results */
7333 	      if ( ngen > 0 )
7334 	         *result = SCIP_SEPARATED;
7335 	      SCIPdebugMsg(scip, "Separated %d implied bound inequalities.\n", ngen);
7336 	   }
7337 	
7338 	   return SCIP_OKAY;
7339 	}
7340 	
7341 	
7342 	/* -------------------------- heuristic methods --------------------------------*/
7343 	
7344 	/** gets weights determining an order of the variables in a heuristic for the maximum weighted independent set problem */
7345 	static
7346 	SCIP_RETCODE getVectorOfWeights(
7347 	   SCIP*                 scip,               /**< SCIP pointer */
7348 	   SCIP_SOL*             sol,                /**< primal solution or NULL for current LP solution */
7349 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
7350 	   int                   nsos1vars,          /**< number of SOS1 variables */
7351 	   SCIP_Bool*            indicatorzero,      /**< vector that indicates which variables are currently fixed to zero */
7352 	   SCIP_Real*            weights             /**< pointer to store weights determining the order of the variables (length = nsos1vars) */
7353 	   )
7354 	{
7355 	   SCIP_VAR* var;
7356 	   SCIP_Real val;
7357 	   SCIP_Real sum;
7358 	   int nviols;
7359 	   int* succ;
7360 	   int nsucc;
7361 	   int i;
7362 	   int j;
7363 	
7364 	   assert( scip != NULL );
7365 	   assert( conflictgraph != NULL );
7366 	   assert( indicatorzero != NULL );
7367 	   assert( weights != NULL );
7368 	
7369 	   for (i = 0; i < nsos1vars; ++i)
7370 	   {
7371 	      nsucc = SCIPdigraphGetNSuccessors(conflictgraph, i);
7372 	
7373 	      if( nsucc == 0 || indicatorzero[i] )
7374 	         weights[i] = 0.0;
7375 	      else
7376 	      {
7377 	         var = SCIPnodeGetVarSOS1(conflictgraph, i);
7378 	         val = REALABS( SCIPgetSolVal(scip, sol, var) );
7379 	         if ( SCIPisFeasZero(scip, val) )
7380 	            weights[i] = 0.0;
7381 	         else
7382 	         {
7383 	            succ = SCIPdigraphGetSuccessors(conflictgraph, i);
7384 	
7385 	            nviols = 0;
7386 	            sum = 0.0;
7387 	            for (j = 0; j < nsucc; ++j)
7388 	            {
7389 	               SCIP_Real valsucc;
7390 	
7391 	               valsucc = REALABS( SCIPgetSolVal(scip, sol, SCIPnodeGetVarSOS1(conflictgraph, succ[j])) );
7392 	               if( ! SCIPisFeasZero(scip, valsucc) )
7393 	               {
7394 	                  sum += MIN(10E05, valsucc);
7395 	                  ++nviols;
7396 	               }
7397 	            }
7398 	
7399 	            if ( nviols == 0 )
7400 	               weights[i] = 0.0;
7401 	            else
7402 	            {
7403 	               assert( SCIPisFeasPositive(scip, sum * (SCIP_Real)nviols));
7404 	               val = MIN(1e6, val);
7405 	               weights[i] = ( val + SCIPsumepsilon(scip) ) / ( sum * (SCIP_Real)nviols + SCIPsumepsilon(scip) );
7406 	            }
7407 	         }
7408 	      }
7409 	   }
7410 	
7411 	   return SCIP_OKAY;
7412 	}
7413 	
7414 	
7415 	/* marks neighbors of a given node as not a member of the maximal independent set */
7416 	static
7417 	SCIP_RETCODE markNeighborsMWISHeuristic(
7418 	   SCIP*                 scip,               /**< SCIP pointer */
7419 	   SCIP_CONSHDLR*        conshdlr,           /**< SOS1 constraint handler */
7420 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
7421 	   int                   node,               /**< node of the conflict graph */
7422 	   SCIP_Bool*            mark,               /**< indicator vector of processed nodes */
7423 	   SCIP_Bool*            indset,             /**< indicator vector of current independent */
7424 	   int*                  cnt,                /**< pointer to store number of marked nodes */
7425 	   SCIP_Bool*            cutoff              /**< pointer to store whether operation is infeasible */
7426 	   )
7427 	{
7428 	   int nsucc;
7429 	   int* succ;
7430 	   int j;
7431 	
7432 	   assert( scip != NULL );
7433 	   assert( conflictgraph != NULL );
7434 	   assert( mark != NULL );
7435 	   assert( indset != NULL );
7436 	   assert( cutoff != NULL );
7437 	   assert( cnt != NULL );
7438 	
7439 	   *cutoff = FALSE;
7440 	
7441 	   nsucc = SCIPdigraphGetNSuccessors(conflictgraph, node);
7442 	   succ = SCIPdigraphGetSuccessors(conflictgraph, node);
7443 	
7444 	   /* for all successors */
7445 	   for (j = 0; j < nsucc && !(*cutoff); ++j)
7446 	   {
7447 	      int succj;
7448 	
7449 	      succj = succ[j];
7450 	      assert( indset[succj] == 0 );
7451 	      if( ! mark[succj] )
7452 	      {
7453 	         SCIP_VARSTATUS varstatus;
7454 	         SCIP_VAR* var;
7455 	
7456 	         /* mark node as processed */
7457 	         mark[succj] = TRUE;
7458 	         ++(*cnt);
7459 	
7460 	         /* get variable and variable status corresponding to successor node */
7461 	         var = SCIPnodeGetVarSOS1(conflictgraph, succj);
7462 	         varstatus = SCIPvarGetStatus(var);
7463 	
7464 	         /* if variable is aggregated */
7465 	         if ( varstatus == SCIP_VARSTATUS_AGGREGATED )
7466 	         {
7467 	            int aggrnode;
7468 	
7469 	            aggrnode = SCIPvarGetNodeSOS1(conshdlr, SCIPvarGetAggrVar(var));
7470 	
7471 	            /* if aggregated variable is an SOS1 variable */
7472 	            if ( aggrnode >= 0 )
7473 	            {
7474 	               /* if aggregated variable is implied to be zero */
7475 	               if ( SCIPisFeasZero(scip, SCIPvarGetAggrConstant(var)) )
7476 	               {
7477 	                  if ( ! mark[aggrnode] )
7478 	                  {
7479 	                     mark[aggrnode] = TRUE;
7480 	                     ++(*cnt);
7481 	                  }
7482 	                  else if ( indset[aggrnode] == 1 )
7483 	                  {
7484 	                     *cutoff = TRUE;
7485 	                     return SCIP_OKAY;
7486 	                  }
7487 	               }
7488 	               else
7489 	               {
7490 	                  /* if aggregated variable is not already a member of the maximal independent set */
7491 	                  if ( indset[aggrnode] == 0 )
7492 	                  {
7493 	                     /* if variable is already marked */
7494 	                     if ( mark[aggrnode] )
7495 	                     {
7496 	                        *cutoff = TRUE;
7497 	                        return SCIP_OKAY;
7498 	                     }
7499 	                     else
7500 	                     {
7501 	                        indset[aggrnode] = 1;
7502 	                        mark[aggrnode] = TRUE;
7503 	                        ++(*cnt);
7504 	                     }
7505 	
7506 	                     /* mark neighbors of aggregated variable */
7507 	                     SCIP_CALL( markNeighborsMWISHeuristic(scip, conshdlr, conflictgraph, aggrnode, mark, indset, cnt, cutoff) );
7508 	                  }
7509 	               }
7510 	            }
7511 	         }
7512 	         else if ( varstatus == SCIP_VARSTATUS_NEGATED )
7513 	         {
7514 	            int negnode;
7515 	
7516 	            negnode = SCIPvarGetNodeSOS1(conshdlr, SCIPvarGetNegationVar(var));
7517 	
7518 	            /* if negated variable is an SOS1 variable */
7519 	            if ( negnode >= 0 )
7520 	            {
7521 	               if ( SCIPisFeasZero(scip, SCIPvarGetNegationConstant(var) ) )
7522 	               {
7523 	                  if ( indset[negnode] == 1 )
7524 	                  {
7525 	                     *cutoff = TRUE;
7526 	                     return SCIP_OKAY;
7527 	                  }
7528 	                  else if ( ! mark[negnode] )
7529 	                  {
7530 	                     mark[negnode] = TRUE;
7531 	                     ++(*cnt);
7532 	                  }
7533 	               }
7534 	            }
7535 	         }
7536 	      }
7537 	   }
7538 	
7539 	   return SCIP_OKAY;
7540 	}
7541 	
7542 	
7543 	/** calls greedy algorithm for the maximum weighted independent set problem (MWIS)
7544 	 *
7545 	 * We compute a feasible solution to
7546 	 * \f[
7547 	 *  \begin{array}{ll}
7548 	 *  \min\limits_{z} & {x^*}^T z \\
7549 	 *                  & z_i + z_j \leq 1, \qquad (i,j)\in E \\
7550 	 *                  &       z_i \in  \{0,1\}, \qquad\quad  i\in V
7551 	 * \end{array}
7552 	 * \f]
7553 	 * by the algorithm GGWMIN of Shuichi Sakai, Mitsunori Togasaki and Koichi Yamazaki in "A note on greedy algorithms for the
7554 	 * maximum weighted independent set problem", Discrete Applied Mathematics. Here \f$x^*\f$ denotes the current LP
7555 	 * relaxation solution. Note that the solution of the MWIS is the indicator vector of an independent set.
7556 	 */
7557 	static
7558 	SCIP_RETCODE maxWeightIndSetHeuristic(
7559 	   SCIP*                 scip,               /**< SCIP pointer */
7560 	   SCIP_SOL*             sol,                /**< primal solution or NULL for current LP solution */
7561 	   SCIP_CONSHDLR*        conshdlr,           /**< SOS1 constraint handler */
7562 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
7563 	   int                   nsos1vars,          /**< number of SOS1 variables */
7564 	   SCIP_Bool*            indicatorzero,      /**< vector that indicates which variables are currently fixed to zero */
7565 	   SCIP_Bool*            indset              /**< pointer to store indicator vector of an independent set */
7566 	   )
7567 	{
7568 	   SCIP_Bool* mark = NULL;
7569 	   SCIP_Real* weights = NULL;
7570 	   int* indscipvars = NULL;
7571 	   int ind;
7572 	   int nsucc;
7573 	   int i;
7574 	   int k;
7575 	
7576 	   assert( scip != NULL );
7577 	   assert( conflictgraph != NULL );
7578 	   assert( indicatorzero != NULL );
7579 	   assert( indset != NULL );
7580 	
7581 	   /* allocate buffer arrays */
7582 	   SCIP_CALL( SCIPallocBufferArray(scip, &mark, nsos1vars) );
7583 	   SCIP_CALL( SCIPallocBufferArray(scip, &weights, nsos1vars) );
7584 	   SCIP_CALL( SCIPallocBufferArray(scip, &indscipvars, nsos1vars) );
7585 	
7586 	   /* sort SOS1 variables in nonincreasing order of weights */
7587 	   for (i = 0; i < nsos1vars; ++i)
7588 	      indscipvars[i] = i;
7589 	
7590 	   SCIP_CALL( getVectorOfWeights(scip, sol, conflictgraph, nsos1vars, indicatorzero, weights) );
7591 	   SCIPsortDownRealInt(weights, indscipvars, nsos1vars);
7592 	
7593 	   /* mark fixed variables and variables without any neighbors in the conflict graph */
7594 	   k = 0;
7595 	   for (i = 0; i < nsos1vars; ++i)
7596 	   {
7597 	      nsucc = SCIPdigraphGetNSuccessors(conflictgraph, i);
7598 	
7599 	      if ( indset[i] == 0 )
7600 	      {
7601 	         if( indicatorzero[i] )
7602 	         {
7603 	            mark[i] = TRUE;
7604 	            ++k;
7605 	         }
7606 	         else if ( nsucc == 0 )
7607 	         {
7608 	            indset[i] = 1;
7609 	            mark[i] = TRUE;
7610 	            ++k;
7611 	         }
7612 	         else
7613 	            mark[i] = FALSE;
7614 	      }
7615 	      else
7616 	      {
7617 	         SCIP_Bool cutoff;
7618 	
7619 	         ++k;
7620 	         mark[i] = TRUE;
7621 	
7622 	         SCIP_CALL( markNeighborsMWISHeuristic(scip, conshdlr, conflictgraph, i, mark, indset, &k, &cutoff) );
7623 	         assert( ! cutoff );
7624 	      }
7625 	   }
7626 	
7627 	   /* mark vertices in the order of their largest weight */
7628 	   for (i = 0; k < nsos1vars; ++i) /*lint !e440*/
7629 	   {
7630 	      assert( i < nsos1vars );
7631 	
7632 	      ind = indscipvars[i];
7633 	
7634 	      if ( ! mark[ind] )
7635 	      {
7636 	         SCIP_Bool cutoff;
7637 	
7638 	         /* mark ind */
7639 	         indset[ind] = 1;
7640 	         mark[ind] = TRUE;
7641 	         ++k;
7642 	
7643 	         SCIP_CALL( markNeighborsMWISHeuristic(scip, conshdlr, conflictgraph, ind, mark, indset, &k, &cutoff) );
7644 	         if ( cutoff )
7645 	            indset[ind] = 0;
7646 	      }
7647 	   }
7648 	   assert( k == nsos1vars );
7649 	
7650 	   /* free buffer arrays */
7651 	   SCIPfreeBufferArrayNull(scip, &indscipvars);
7652 	   SCIPfreeBufferArrayNull(scip, &weights);
7653 	   SCIPfreeBufferArrayNull(scip, &mark);
7654 	
7655 	   return SCIP_OKAY;
7656 	}
7657 	
7658 	
7659 	/** based on solution values of the variables, fixes variables of the conflict graph to zero to turn all SOS1 constraints feasible
7660 	 *
7661 	 *  if the SOS1 constraints do not overlap, the method makeSOS1constraintsFeasible() may be faster
7662 	 */
7663 	static
7664 	SCIP_RETCODE makeSOS1conflictgraphFeasible(
7665 	   SCIP*                 scip,               /**< SCIP pointer */
7666 	   SCIP_CONSHDLR*        conshdlr,           /**< SOS1 constraint handler */
7667 	   SCIP_SOL*             sol,                /**< solution */
7668 	   SCIP_Bool*            changed,            /**< pointer to store whether the solution has been changed */
7669 	   SCIP_Bool*            allroundable        /**< pointer to store whether all variables are roundable */
7670 	   )
7671 	{
7672 	   SCIP_DIGRAPH* conflictgraph;  /* conflict graph for SOS1 constraints */
7673 	   SCIP_Bool* indicatorzero;     /* indicates which solution values are zero */
7674 	   SCIP_Bool* indset;            /* indicator vector of feasible solution; i.e., an independent set */
7675 	   int nsos1vars;
7676 	   int j;
7677 	
7678 	   assert( scip != NULL );
7679 	   assert( conshdlr != NULL );
7680 	   assert( sol != NULL );
7681 	   assert( changed != NULL );
7682 	   assert( allroundable != NULL );
7683 	
7684 	   *allroundable = TRUE;
7685 	   *changed = FALSE;
7686 	
7687 	   /* get number of SOS1 variables */
7688 	   nsos1vars = SCIPgetNSOS1Vars(conshdlr);
7689 	   assert( nsos1vars >= 0 );
7690 	
7691 	   /* get conflict graph */
7692 	   conflictgraph = SCIPgetConflictgraphSOS1(conshdlr);
7693 	   assert( conflictgraph != NULL );
7694 	
7695 	   /* allocate buffer arrays */
7696 	   SCIP_CALL( SCIPallocBufferArray(scip, &indset, nsos1vars) );
7697 	   SCIP_CALL( SCIPallocBufferArray(scip, &indicatorzero, nsos1vars) );
7698 	
7699 	   /* determine if variables with nonzero solution value are roundable */
7700 	   for (j = 0; j < nsos1vars; ++j)
7701 	   {
7702 	      SCIP_VAR* var;
7703 	      SCIP_Real lb;
7704 	      SCIP_Real ub;
7705 	
7706 	      var = SCIPnodeGetVarSOS1(conflictgraph, j);
7707 	      lb = SCIPvarGetLbLocal(var);
7708 	      ub = SCIPvarGetUbLocal(var);
7709 	      indset[j] = 0;
7710 	
7711 	      /* if solution value of variable is zero */
7712 	      if ( SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, var)) )
7713 	         indicatorzero[j] = TRUE;
7714 	      else
7715 	      {
7716 	         indicatorzero[j] = FALSE;
7717 	
7718 	         /* if variable is not roundable */
7719 	         if ( ! SCIPvarMayRoundDown(var) && ! SCIPvarMayRoundUp(var) )
7720 	         {
7721 	            *allroundable = FALSE;
7722 	            break;
7723 	         }
7724 	
7725 	         /* if bounds of variable are fixed to zero */
7726 	         if ( SCIPisFeasZero(scip, ub) && SCIPisFeasZero(scip, lb) )
7727 	            indicatorzero[j] = TRUE;
7728 	         else if ( SCIPisFeasPositive(scip, lb) || SCIPisFeasNegative(scip, ub) ) /* if variable is fixed to be nonzero */
7729 	            indset[j] = 1;
7730 	      }
7731 	   }
7732 	
7733 	   /* return if at least one SOS1 variable is not roundable */
7734 	   if ( ! (*allroundable) )
7735 	   {
7736 	      SCIPfreeBufferArray(scip, &indicatorzero);
7737 	      SCIPfreeBufferArray(scip, &indset);
7738 	      return SCIP_OKAY;
7739 	   }
7740 	
7741 	   /* call greedy algorithm for the maximum weighted independent set problem */
7742 	   SCIP_CALL( maxWeightIndSetHeuristic(scip, sol, conshdlr, conflictgraph, nsos1vars, indicatorzero, indset) );
7743 	
7744 	   /* make solution feasible */
7745 	   for (j = 0; j < nsos1vars; ++j)
7746 	   {
7747 	      if ( indset[j] == 0 )
7748 	      {
7749 	         SCIP_CALL( SCIPsetSolVal(scip, sol, SCIPnodeGetVarSOS1(conflictgraph, j), 0.0) );
7750 	         *changed = TRUE;
7751 	      }
7752 	   }
7753 	
7754 	   /* free buffer arrays */
7755 	   SCIPfreeBufferArray(scip, &indicatorzero);
7756 	   SCIPfreeBufferArray(scip, &indset);
7757 	
7758 	#ifdef SCIP_NDEBUG
7759 	   {
7760 	      SCIP_CONSDATA* consdata;
7761 	      SCIP_CONS** conss;
7762 	      int nconss;
7763 	      int c;
7764 	
7765 	      conss = SCIPconshdlrGetConss(conshdlr);
7766 	      nconss = SCIPconshdlrGetNConss(conshdlr);
7767 	      for (c = 0; c < nconss; ++c)
7768 	      {
7769 	         int cnt = 0;
7770 	         consdata = SCIPconsGetData(conss[c]);
7771 	         assert( consdata != NULL );
7772 	
7773 	         for (j = 0; j < consdata->nvars; ++j)
7774 	         {
7775 	            if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vars[j])) )
7776 	            {
7777 	               ++cnt;
7778 	            }
7779 	         }
7780 	         assert( cnt < 2 );
7781 	      }
7782 	   }
7783 	#endif
7784 	
7785 	   return SCIP_OKAY;
7786 	}
7787 	
7788 	
7789 	/** based on solution values of the variables, fixes variables of the SOS1 constraints to zero to turn these constraints feasible
7790 	 *
7791 	 *  if the SOS1 constraints overlap, the method makeSOS1constraintsFeasible() may result in better primal solutions
7792 	 */
7793 	static
7794 	SCIP_RETCODE makeSOS1constraintsFeasible(
7795 	   SCIP*                 scip,               /**< SCIP pointer */
7796 	   SCIP_CONSHDLR*        conshdlr,           /**< SOS1 constraint handler */
7797 	   SCIP_SOL*             sol,                /**< solution */
7798 	   SCIP_Bool*            changed,            /**< pointer to store whether the solution has been changed */
7799 	   SCIP_Bool*            allroundable        /**< pointer to store whether all variables are roundable */
7800 	   )
7801 	{
7802 	   SCIP_CONSDATA* consdata;
7803 	   SCIP_CONS** conss;
7804 	   int nconss;
7805 	   int c;
7806 	
7807 	   assert( scip != NULL );
7808 	   assert( conshdlr != NULL );
7809 	   assert( sol != NULL );
7810 	   assert( changed != NULL );
7811 	   assert( allroundable != NULL );
7812 	
7813 	   *allroundable = TRUE;
7814 	   *changed = FALSE;
7815 	
7816 	   /* get SOS1 constraints and number of SOS1 constraints */
7817 	   conss = SCIPconshdlrGetConss(conshdlr);
7818 	   nconss = SCIPconshdlrGetNConss(conshdlr);
7819 	   assert( nconss > 0 );
7820 	
7821 	   /* loop through all SOS1 constraints */
7822 	   for (c = 0; c < nconss && *allroundable; ++c)
7823 	   {
7824 	      SCIP_CONS* cons;
7825 	      SCIP_VAR** vars;
7826 	      SCIP_Bool varisfixed = FALSE;
7827 	      SCIP_Real maxval = 0.0;
7828 	      int pos = -1;
7829 	      int nvars;
7830 	      int j;
7831 	
7832 	      cons = conss[c];
7833 	      assert( cons != NULL );
7834 	      consdata = SCIPconsGetData(cons);
7835 	      assert( consdata != NULL );
7836 	
7837 	      nvars = consdata->nvars;
7838 	      vars = consdata->vars;
7839 	
7840 	      /* search for maximum solution value */
7841 	      for (j = 0; j < nvars; ++j)
7842 	      {
7843 	         SCIP_VAR* var;
7844 	
7845 	         var = vars[j];
7846 	
7847 	         if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, var)) )
7848 	         {
7849 	            SCIP_Real lb;
7850 	            SCIP_Real ub;
7851 	
7852 	            lb = SCIPvarGetLbLocal(var);
7853 	            ub = SCIPvarGetUbLocal(var);
7854 	
7855 	            /* if variable is not roundable */
7856 	            if ( ! SCIPvarMayRoundDown(var) && ! SCIPvarMayRoundUp(var) )
7857 	            {
7858 	               *allroundable = FALSE;
7859 	               break;
7860 	            }
7861 	
7862 	            /* it is possible that the bounds were proagated to zero although the current solution value is nonzero
7863 	             * in this case fix the solution value to zero */
7864 	            if ( SCIPisFeasZero(scip, ub) && SCIPisFeasZero(scip, lb) )
7865 	            {
7866 	               SCIP_CALL( SCIPsetSolVal(scip, sol, var, 0.0) );
7867 	               *changed = TRUE;
7868 	            }
7869 	            else if ( SCIPisFeasPositive(scip, lb) || SCIPisFeasNegative(scip, ub) ) /* if variable is fixed to be nonzero */
7870 	            {
7871 	               assert( ! varisfixed );
7872 	               varisfixed = TRUE;
7873 	               maxval = SCIPgetSolVal(scip, sol, var);
7874 	               pos = j;
7875 	            }
7876 	            else if ( ! varisfixed && SCIPisFeasGT(scip, REALABS(SCIPgetSolVal(scip, sol, var)), REALABS(maxval)) ) /* search for variable with maximum solution value */
7877 	            {
7878 	               maxval = SCIPgetSolVal(scip, sol, var);
7879 	               pos = j;
7880 	            }
7881 	
7882 	            /* fix variable to zero; the solution value of the variable with maximum solution value
7883 	             * will be restored in a later step */
7884 	            SCIP_CALL( SCIPsetSolVal(scip, sol, var, 0.0) );
7885 	            *changed = TRUE;
7886 	         }
7887 	      }
7888 	
7889 	      if ( ! (*allroundable) )
7890 	         break;
7891 	      else if ( pos >= 0 ) /* restore solution of variable with maximum solution value */
7892 	      {
7893 	         SCIP_CALL( SCIPsetSolVal(scip, sol, vars[pos], maxval) );
7894 	      }
7895 	   }
7896 	
7897 	#ifdef SCIP_NDEBUG
7898 	   if ( *allroundable )
7899 	   {
7900 	      for (c = 0; c < nconss; ++c)
7901 	      {
7902 	         int cnt = 0;
7903 	         int j;
7904 	
7905 	         consdata = SCIPconsGetData(conss[c]);
7906 	         assert( consdata != NULL );
7907 	
7908 	         for (j = 0; j < consdata->nvars; ++j)
7909 	         {
7910 	            if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vars[j])) )
7911 	            {
7912 	               ++cnt;
7913 	            }
7914 	         }
7915 	         assert( cnt < 2 );
7916 	      }
7917 	   }
7918 	#endif
7919 	
7920 	   return SCIP_OKAY;
7921 	}
7922 	
7923 	
7924 	/** determine a diving variables and boundchanges of diving variables by analyzing the conflict graph
7925 	 *
7926 	 *  if the SOS1 constraints do not overlap, the method getDiveBdChgsSOS1constraints() may be faster
7927 	 */
7928 	static
7929 	SCIP_RETCODE getDiveBdChgsSOS1conflictgraph(
7930 	   SCIP*                 scip,               /**< SCIP pointer */
7931 	   SCIP_CONSHDLR*        conshdlr,           /**< SOS1 constraint handler */
7932 	   SCIP_DIVESET*         diveset,            /**< diving settings */
7933 	   SCIP_SOL*             sol,                /**< solution */
7934 	   SCIP_Bool*            success             /**< pointer to store */
7935 	   )
7936 	{
7937 	   SCIP_DIGRAPH* conflictgraph;
7938 	   SCIP_VAR* bestvar = NULL;
7939 	   SCIP_Bool bestvarfixneigh = FALSE;
7940 	   SCIP_Real bestscore = SCIP_REAL_MIN;
7941 	   int bestnode = -1;
7942 	   int nsos1vars;
7943 	   int v;
7944 	
7945 	   assert( scip != NULL );
7946 	   assert( conshdlr != NULL );
7947 	   assert( diveset != NULL );
7948 	   assert( success != NULL );
7949 	
7950 	   *success = FALSE;
7951 	
7952 	   /* get number of SOS1 variables */
7953 	   nsos1vars = SCIPgetNSOS1Vars(conshdlr);
7954 	
7955 	   /* get conflict graph of SOS1 constraints */
7956 	   conflictgraph = SCIPgetConflictgraphSOS1(conshdlr);
7957 	
7958 	   /* loop over SOS1 variables  */
7959 	   for (v = 0; v < nsos1vars; ++v)
7960 	   {
7961 	      /* check whether the variable violates an SOS1 constraint together with at least one other variable */
7962 	      if ( isViolatedSOS1(scip, conflictgraph, v, sol) )
7963 	      {
7964 	         SCIP_VAR* var;
7965 	         SCIP_Real solval;
7966 	         SCIP_Real score;
7967 	         SCIP_Real bound;
7968 	         SCIP_Real fracval;
7969 	         SCIP_Bool fixneigh;
7970 	
7971 	         var = SCIPnodeGetVarSOS1(conflictgraph, v);
7972 	         solval = SCIPgetSolVal(scip, sol, var);
7973 	
7974 	         /* compute (variable) bound of candidate */
7975 	         if ( SCIPisFeasNegative(scip, solval) )
7976 	            bound = nodeGetSolvalVarboundLbSOS1(scip, conflictgraph, sol, v);
7977 	         else
7978 	            bound = nodeGetSolvalVarboundUbSOS1(scip, conflictgraph, sol, v);
7979 	
7980 	         /* ensure finiteness */
7981 	         bound = MIN(DIVINGCUTOFFVALUE, REALABS(bound)); /*lint !e666*/
7982 	         fracval = MIN(DIVINGCUTOFFVALUE, REALABS(solval)); /*lint !e666*/
7983 	         assert( ! SCIPisInfinity(scip, bound) );
7984 	         assert( ! SCIPisInfinity(scip, fracval) );
7985 	         assert( SCIPisPositive(scip, bound) );
7986 	
7987 	         /* bound may have changed in propagation; ensure that fracval <= 1 */
7988 	         if ( SCIPisFeasLT(scip, bound, fracval) )
7989 	            bound = fracval;
7990 	
7991 	         /* get fractionality of candidate */
7992 	         fracval /= (bound + SCIPsumepsilon(scip));
7993 	
7994 	         /* should SOS1 variables be scored by the diving heuristics specific score function;
7995 	          *  otherwise use the score function of the SOS1 constraint handler */
7996 	         if ( SCIPdivesetSupportsType(diveset, SCIP_DIVETYPE_SOS1VARIABLE) )
7997 	         {
7998 	            SCIP_Bool roundup;
7999 	
8000 	            SCIP_CALL( SCIPgetDivesetScore(scip, diveset, SCIP_DIVETYPE_SOS1VARIABLE, var, solval, fracval,
8001 	                  &score, &roundup) );
8002 	
8003 	            fixneigh = roundup;
8004 	            if ( SCIPisFeasNegative(scip, solval) )
8005 	               fixneigh = !fixneigh;
8006 	         }
8007 	         else
8008 	         {
8009 	            /* we always fix the candidates neighbors in the conflict graph to zero */
8010 	            fixneigh = TRUE;
8011 	
8012 	            /* score fractionality of candidate */
8013 	            score = fracval;
8014 	         }
8015 	
8016 	         /* best candidate maximizes the score */
8017 	         if ( score > bestscore )
8018 	         {
8019 	            bestscore = score;
8020 	
8021 	            *success = TRUE;
8022 	            bestvar = var;
8023 	            bestnode = v;
8024 	            bestvarfixneigh = fixneigh;
8025 	         }
8026 	      }
8027 	   }
8028 	   assert( !(*success) || bestvar != NULL );
8029 	
8030 	   if ( *success )
8031 	   {
8032 	      int* succ;
8033 	      int nsucc;
8034 	      int s;
8035 	
8036 	      assert( bestnode >= 0 && bestnode < nsos1vars );
8037 	
8038 	      nsucc = SCIPdigraphGetNSuccessors(conflictgraph, bestnode);
8039 	      succ = SCIPdigraphGetSuccessors(conflictgraph, bestnode);
8040 	
8041 	      /* if the diving score voted for fixing the best variable to 0.0, we add this as the preferred bound change;
8042 	       * otherwise, fixing the neighbors in the conflict graph to 0.0 is the preferred bound change.
8043 	       */
8044 	      assert( SCIPisFeasNegative(scip, SCIPvarGetLbLocal(bestvar)) || SCIPisFeasPositive(scip, SCIPvarGetUbLocal(bestvar)) );
8045 	      SCIP_CALL( SCIPaddDiveBoundChange(scip, bestvar, SCIP_BRANCHDIR_FIXED, 0.0, !bestvarfixneigh) );
8046 	      for (s = 0; s < nsucc; ++s)
8047 	      {
8048 	         SCIP_VAR* var;
8049 	
8050 	         var = SCIPnodeGetVarSOS1(conflictgraph, succ[s]);
8051 	
8052 	         /* if variable is not already fixed */
8053 	         if ( SCIPisFeasNegative(scip, SCIPvarGetLbLocal(var)) || SCIPisFeasPositive(scip, SCIPvarGetUbLocal(var)) )
8054 	         {
8055 	            SCIP_CALL( SCIPaddDiveBoundChange(scip, var, SCIP_BRANCHDIR_FIXED, 0.0, bestvarfixneigh) );
8056 	         }
8057 	      }
8058 	   }
8059 	
8060 	   return SCIP_OKAY;
8061 	}
8062 	
8063 	
8064 	/** determine a diving variables and boundchanges of diving variables by analyzing the SOS1 constraints
8065 	 *
8066 	 *  if the SOS1 constraints overlap, the method getDiveBdChgsSOS1conflictgraph() may produce better results (e.g., due to more
8067 	 *  diving candidates)
8068 	 */
8069 	static
8070 	SCIP_RETCODE getDiveBdChgsSOS1constraints(
8071 	   SCIP*                 scip,               /**< SCIP pointer */
8072 	   SCIP_CONSHDLR*        conshdlr,           /**< SOS1 constraint handler */
8073 	   SCIP_DIVESET*         diveset,            /**< diving settings */
8074 	   SCIP_SOL*             sol,                /**< solution */
8075 	   SCIP_Bool*            success             /**< pointer to store */
8076 	   )
8077 	{
8078 	   SCIP_VAR* bestvar = NULL;
8079 	   SCIP_Bool bestvarfixcomp = FALSE;
8080 	   SCIP_Real bestscore = SCIP_REAL_MIN;
8081 	   SCIP_CONSDATA* consdata;
8082 	   SCIP_CONS** conss;
8083 	   int nconss;
8084 	   int bestcons = -1;
8085 	   int c;
8086 	
8087 	   assert( scip != NULL );
8088 	   assert( conshdlr != NULL );
8089 	   assert( diveset != NULL );
8090 	   assert( success != NULL );
8091 	
8092 	   *success = FALSE;
8093 	
8094 	   /* get SOS1 constraints and number of SOS1 constraints */
8095 	   conss = SCIPconshdlrGetConss(conshdlr);
8096 	   nconss = SCIPconshdlrGetNConss(conshdlr);
8097 	
8098 	   /* loop through all SOS1 constraints */
8099 	   for (c = 0; c < nconss; ++c)
8100 	   {
8101 	      SCIP_VAR** vars;
8102 	      int nvars;
8103 	      int cnt = 0;
8104 	      int j;
8105 	
8106 	      consdata = SCIPconsGetData(conss[c]);
8107 	      assert( consdata != NULL );
8108 	
8109 	      nvars = consdata->nvars;
8110 	      vars = consdata->vars;
8111 	
8112 	      /* check whether SOS1 constraint is violated */
8113 	      for (j = 0; j < nvars && cnt < 2; ++j)
8114 	      {
8115 	         SCIP_VAR* var;
8116 	
8117 	         var = vars[j];
8118 	
8119 	         /* check whether variable is nonzero w.r.t. sol and the bounds have not been fixed to zero by propagation */
8120 	         if ( !SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, var))
8121 	               && (!SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) || !SCIPisFeasZero(scip, SCIPvarGetUbLocal(var))) )
8122 	            ++cnt;
8123 	      }
8124 	
8125 	      /* if SOS1 constraint is not violated then continue with the next SOS1 constraint */
8126 	      if ( cnt < 2 )
8127 	         continue;
8128 	
8129 	      /* get diving score of every variable in constraint */
8130 	      for (j = 0; j < nvars; ++j)
8131 	      {
8132 	         SCIP_VAR* var;
8133 	         SCIP_Real solval;
8134 	         SCIP_Real score;
8135 	         SCIP_Real bound;
8136 	         SCIP_Real fracval;
8137 	         SCIP_Real lb;
8138 	         SCIP_Real ub;
8139 	         SCIP_Bool fixcomp;  /* whether to fix the complementary variables of the candidate in the SOS1 constraint to zero */
8140 	
8141 	         var = vars[j];
8142 	         solval = SCIPgetSolVal(scip, sol, var);
8143 	         lb = SCIPvarGetLbLocal(var);
8144 	         ub = SCIPvarGetUbLocal(var);
8145 	
8146 	         /* check whether variable is nonzero w.r.t. sol and the bounds have not been fixed to zero by propagation */
8147 	         if ( ! SCIPisFeasZero(scip, solval) && ( ! SCIPisFeasZero(scip, lb) || ! SCIPisFeasZero(scip, ub) ) )
8148 	         {
8149 	            /* compute (variable) bound of candidate */
8150 	            if ( SCIPisFeasNegative(scip, solval) )
8151 	               bound = lb;
8152 	            else
8153 	               bound = ub;
8154 	
8155 	            /* bound may have changed in propagation; ensure that fracval <= 1 */
8156 	            if ( SCIPisFeasLT(scip, REALABS(bound), REALABS(solval)) )
8157 	               bound = solval;
8158 	
8159 	            /* ensure finiteness */
8160 	            bound = MIN(DIVINGCUTOFFVALUE, REALABS(bound)); /*lint !e666*/
8161 	            fracval = MIN(DIVINGCUTOFFVALUE, REALABS(solval)); /*lint !e666*/
8162 	            assert( ! SCIPisInfinity(scip, bound) );
8163 	            assert( ! SCIPisInfinity(scip, fracval) );
8164 	            assert( SCIPisPositive(scip, bound) );
8165 	
8166 	            /* get fractionality of candidate */
8167 	            fracval /= (bound + SCIPsumepsilon(scip));
8168 	
8169 	            /* should SOS1 variables be scored by the diving heuristics specific score function;
8170 	             *  otherwise use the score function of the SOS1 constraint handler
8171 	             */
8172 	            if ( SCIPdivesetSupportsType(diveset, SCIP_DIVETYPE_SOS1VARIABLE) )
8173 	            {
8174 	               SCIP_Bool roundup;
8175 	
8176 	               SCIP_CALL( SCIPgetDivesetScore(scip, diveset, SCIP_DIVETYPE_SOS1VARIABLE, var, solval, fracval,
8177 	                &score, &roundup) );
8178 	
8179 	               fixcomp = roundup;
8180 	               if ( SCIPisFeasNegative(scip, solval) )
8181 	                  fixcomp = !fixcomp;
8182 	            }
8183 	            else
8184 	            {
8185 	               /* we always fix the complementary variables of the candidate in the SOS1 constraint to zero */
8186 	               fixcomp = TRUE;
8187 	
8188 	               /* score fractionality of candidate */
8189 	               score = fracval;
8190 	            }
8191 	
8192 	            /* best candidate maximizes the score */
8193 	            if ( score > bestscore )
8194 	            {
8195 	               bestscore = score;
8196 	
8197 	               *success = TRUE;
8198 	               bestvar = var;
8199 	               bestcons = c;
8200 	               bestvarfixcomp = fixcomp;
8201 	            }
8202 	         }
8203 	      }
8204 	   }
8205 	   assert( !(*success) || bestvar != NULL );
8206 	
8207 	   if ( *success )
8208 	   {
8209 	      SCIP_VAR** vars;
8210 	      int nvars;
8211 	      int j;
8212 	
8213 	      consdata = SCIPconsGetData(conss[bestcons]);
8214 	      assert( consdata != NULL );
8215 	
8216 	      nvars = consdata->nvars;
8217 	      vars = consdata->vars;
8218 	
8219 	      assert( bestcons >= 0 && bestcons < nconss );
8220 	
8221 	      /* if the diving score voted for fixing the best variable to 0.0, we add this as the preferred bound change;
8222 	       * otherwise, fixing the complementary variables of the candidate in the SOS1 constraint to 0.0 is the preferred bound change.
8223 	       */
8224 	      assert( SCIPisFeasNegative(scip, SCIPvarGetLbLocal(bestvar)) || SCIPisFeasPositive(scip, SCIPvarGetUbLocal(bestvar)) );
8225 	
8226 	      SCIP_CALL( SCIPaddDiveBoundChange(scip, bestvar, SCIP_BRANCHDIR_FIXED, 0.0, !bestvarfixcomp) );
8227 	      for (j = 0; j < nvars; ++j)
8228 	      {
8229 	         SCIP_VAR* var;
8230 	
8231 	         var = vars[j];
8232 	
8233 	         /* if variable is not already fixed and is not the candidate variable */
8234 	         if ( var != bestvar && ( SCIPisFeasNegative(scip, SCIPvarGetLbLocal(var)) || SCIPisFeasPositive(scip, SCIPvarGetUbLocal(var)) ) )
8235 	         {
8236 	            SCIP_CALL( SCIPaddDiveBoundChange(scip, var, SCIP_BRANCHDIR_FIXED, 0.0, bestvarfixcomp) );
8237 	         }
8238 	      }
8239 	   }
8240 	
8241 	   return SCIP_OKAY;
8242 	}
8243 	
8244 	
8245 	/* --------------------initialization/deinitialization ------------------------*/
8246 	
8247 	/** check whether \f$x_1\f$ is a bound variable of \f$x_0\f$; i.e., \f$x_0 \leq c\cdot x_1\f$ or \f$x_0 \geq d\cdot x_1\f$
8248 	 *  for positive values \f$c, d\f$. If true, then add this information to the node data of the conflict graph.
8249 	 */
8250 	static
8251 	SCIP_RETCODE detectVarboundSOS1(
8252 	   SCIP*                 scip,               /**< SCIP pointer */
8253 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< SOS1 constraint handler data */
8254 	   SCIP_VAR*             var0,               /**< first variable */
8255 	   SCIP_VAR*             var1,               /**< second variable */
8256 	   SCIP_Real             val0,               /**< first coefficient */
8257 	   SCIP_Real             val1                /**< second coefficient */
8258 	   )
8259 	{
8260 	   int node0;
8261 	
8262 	   assert( scip != NULL );
8263 	   assert( conshdlrdata != NULL );
8264 	   assert( var0 != NULL && var1 != NULL );
8265 	
8266 	   /* get nodes of variable in the conflict graph (node = -1 if no SOS1 variable) */
8267 	   node0 = varGetNodeSOS1(conshdlrdata, var0);
8268 	
8269 	   /* if var0 is an SOS1 variable */
8270 	   if ( node0 >= 0 )
8271 	   {
8272 	      SCIP_Real val;
8273 	
8274 	      assert( ! SCIPisFeasZero(scip, val0) );
8275 	      val = -val1/val0;
8276 	
8277 	      /* check variable bound relation of variables */
8278 	
8279 	      /* handle lower bound case */
8280 	      if ( SCIPisFeasNegative(scip, val0) && SCIPisFeasNegative(scip, val) )
8281 	      {
8282 	         SCIP_NODEDATA* nodedata;
8283 	
8284 	         /* get node data of the conflict graph */
8285 	         nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conshdlrdata->conflictgraph, node0);
8286 	
8287 	         /* @todo: maybe save multiple variable bounds for each SOS1 variable */
8288 	         if ( nodedata->lbboundvar == NULL )
8289 	         {
8290 	            /* add variable bound information to node data */
8291 	            nodedata->lbboundvar = var1;
8292 	            nodedata->lbboundcoef = val;
8293 	
8294 	            SCIPdebugMsg(scip, "detected variable bound constraint %s >= %f %s.\n", SCIPvarGetName(var0), val, SCIPvarGetName(var1));
8295 	         }
8296 	      }
8297 	      /* handle upper bound case */
8298 	      else if ( SCIPisFeasPositive(scip, val0) && SCIPisFeasPositive(scip, val) )
8299 	      {
8300 	         SCIP_NODEDATA* nodedata;
8301 	         assert( SCIPisFeasPositive(scip, val0) );
8302 	
8303 	         /* get node data of the conflict graph */
8304 	         nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conshdlrdata->conflictgraph, node0);
8305 	
8306 	         if ( nodedata->ubboundvar == NULL )
8307 	         {
8308 	            /* add variable bound information to node data */
8309 	            nodedata->ubboundvar = var1;
8310 	            nodedata->ubboundcoef = val;
8311 	
8312 	            SCIPdebugMsg(scip, "detected variable bound constraint %s <= %f %s.\n", SCIPvarGetName(var0), val, SCIPvarGetName(var1));
8313 	         }
8314 	      }
8315 	   }
8316 	
8317 	   return SCIP_OKAY;
8318 	}
8319 	
8320 	
8321 	/** pass connected component \f$C\f$ of the conflict graph and check whether all the variables correspond to a unique variable upper bound variable \f$z\f$,
8322 	 *  i.e., \f$x_i \leq u_i z\f$ for every \f$i\in C\f$.
8323 	 *
8324 	 *  @note if the bound variable is unique, then bound inequalities can be strengthened.
8325 	 */
8326 	static
8327 	SCIP_RETCODE passConComponentVarbound(
8328 	   SCIP*                 scip,               /**< SCIP pointer */
8329 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
8330 	   int                   node,               /**< current node of connected component */
8331 	   SCIP_VAR*             boundvar,           /**< bound variable of connected component */
8332 	   SCIP_Bool             checklb,            /**< whether to check lower bound variable (else upper bound variable) */
8333 	   SCIP_Bool*            processed,          /**< states for each variable whether it has been processed */
8334 	   int*                  concomp,            /**< current connected component */
8335 	   int*                  nconcomp,           /**< pointer to store number of elements of connected component */
8336 	   SCIP_Bool*            unique              /**< pointer to store whether bound variable is unique */
8337 	   )
8338 	{
8339 	   int* succ;
8340 	   int nsucc;
8341 	   int s;
8342 	
8343 	   assert( scip != NULL );
8344 	   assert( conflictgraph != NULL );
8345 	   assert( processed != NULL );
8346 	   assert( concomp != NULL );
8347 	   assert( nconcomp != NULL );
8348 	   assert( unique != NULL );
8349 	
8350 	   processed[node] = TRUE;/*lint !e737*/
8351 	   concomp[(*nconcomp)++] = node;
8352 	
8353 	   /* if bound variable of connected component without new node is unique */
8354 	   if ( *unique )
8355 	   {
8356 	      SCIP_NODEDATA* nodedata;
8357 	      SCIP_VAR* comparevar;
8358 	      nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, node);
8359 	      assert( nodedata != NULL );
8360 	
8361 	      if ( checklb )
8362 	         comparevar = nodedata->lbboundvar;
8363 	      else
8364 	         comparevar = nodedata->ubboundvar;
8365 	
8366 	      /* check whether bound variable is unique for connected component without new node */
8367 	      if ( boundvar == NULL )
8368 	      {
8369 	         if ( comparevar != NULL )
8370 	            *unique = FALSE;
8371 	      }
8372 	      else
8373 	      {
8374 	         if ( comparevar == NULL )
8375 	            *unique = FALSE;
8376 	         else if ( SCIPvarCompare(boundvar, comparevar) != 0 )
8377 	            *unique = FALSE;
8378 	      }
8379 	   }
8380 	
8381 	   /* pass through successor variables */
8382 	   nsucc = SCIPdigraphGetNSuccessors(conflictgraph, node);
8383 	   succ = SCIPdigraphGetSuccessors(conflictgraph, node);
8384 	   for (s = 0; s < nsucc; ++s)
8385 	   {
8386 	      if ( ! processed[succ[s]] )
8387 	         SCIP_CALL( passConComponentVarbound(scip, conflictgraph, succ[s], boundvar, checklb, processed, concomp, nconcomp, unique) );
8388 	   }
8389 	
8390 	   return SCIP_OKAY;
8391 	}
8392 	
8393 	
8394 	/** for each connected component \f$C\f$ of the conflict graph check whether all the variables correspond to a unique variable upper bound variable \f$z\f$
8395 	 *  (e.g., for the upper bound case this means that \f$x_i \leq u_i z\f$ for every \f$i\in C\f$).
8396 	 *
8397 	 *  @note if the bound variable is unique, then bound inequalities can be strengthened.
8398 	 */
8399 	static
8400 	SCIP_RETCODE checkConComponentsVarbound(
8401 	   SCIP*                 scip,               /**< SCIP pointer */
8402 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
8403 	   int                   nsos1vars,          /**< number of SOS1 variables */
8404 	   SCIP_Bool             checklb             /**< whether to check lower bound variable (else check upper bound variable) */
8405 	   )
8406 	{
8407 	   SCIP_Bool* processed;  /* states for each variable whether it has been processed */
8408 	   int* concomp;          /* current connected component */
8409 	   int nconcomp;
8410 	   int j;
8411 	
8412 	   assert( scip != NULL );
8413 	   assert( conflictgraph != NULL );
8414 	
8415 	   /* allocate buffer arrays and initialize 'processed' array */
8416 	   SCIP_CALL( SCIPallocBufferArray(scip, &processed, nsos1vars) );
8417 	   SCIP_CALL( SCIPallocBufferArray(scip, &concomp, nsos1vars) );
8418 	   for (j = 0; j < nsos1vars; ++j)
8419 	      processed[j] = FALSE;
8420 	
8421 	   /* run through all SOS1 variables */
8422 	   for (j = 0; j < nsos1vars; ++j)
8423 	   {
8424 	      /* if variable belongs to a connected component that has not been processed so far */
8425 	      if ( ! processed[j] )
8426 	      {
8427 	         SCIP_NODEDATA* nodedata;
8428 	         SCIP_VAR* boundvar;
8429 	         SCIP_Bool unique;
8430 	         int* succ;
8431 	         int nsucc;
8432 	         int s;
8433 	
8434 	         nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, j);
8435 	         assert( nodedata != NULL );
8436 	
8437 	         if ( checklb )
8438 	            boundvar = nodedata->lbboundvar;
8439 	         else
8440 	            boundvar = nodedata->ubboundvar;
8441 	         unique = TRUE;
8442 	
8443 	         processed[j] = TRUE;
8444 	         concomp[0] = j;
8445 	         nconcomp = 1;
8446 	
8447 	         /* pass through successor variables */
8448 	         nsucc = SCIPdigraphGetNSuccessors(conflictgraph, j);
8449 	         succ = SCIPdigraphGetSuccessors(conflictgraph, j);
8450 	         for (s = 0; s < nsucc; ++s)
8451 	         {
8452 	            if ( ! processed[succ[s]] )
8453 	            {
8454 	               SCIP_CALL( passConComponentVarbound(scip, conflictgraph, succ[s], boundvar, checklb, processed, concomp, &nconcomp, &unique) );
8455 	            }
8456 	         }
8457 	
8458 	         /* if the connected component has a unique bound variable */
8459 	         if ( unique && boundvar != NULL )
8460 	         {
8461 	            for (s = 0; s < nconcomp; ++s)
8462 	            {
8463 	               nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, concomp[s]);
8464 	               assert( processed[concomp[s]] == TRUE );
8465 	               assert( nodedata != NULL );
8466 	
8467 	               if ( checklb )
8468 	                  nodedata->lbboundcomp = TRUE;
8469 	               else
8470 	                  nodedata->ubboundcomp = TRUE;
8471 	            }
8472 	            SCIPdebugMsg(scip, "Found a connected component of size <%i> with unique bound variable.\n", nconcomp);
8473 	         }
8474 	      }
8475 	   }
8476 	
8477 	   /* free buffer arrays */
8478 	   SCIPfreeBufferArray(scip, &concomp);
8479 	   SCIPfreeBufferArray(scip, &processed);
8480 	
8481 	   return SCIP_OKAY;
8482 	}
8483 	
8484 	
8485 	/** check all linear constraints for variable bound constraints of the form \f$c\cdot z \leq x \leq d\cdot z\f$, where @p x is some SOS1
8486 	 *  variable and @p z is some arbitrary variable (not necessarily binary)
8487 	 */
8488 	static
8489 	SCIP_RETCODE checkLinearConssVarboundSOS1(
8490 	   SCIP*                 scip,               /**< SCIP pointer */
8491 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< SOS1 constraint handler data */
8492 	   SCIP_CONS**           linconss,           /**< linear constraints */
8493 	   int                   nlinconss           /**< number of linear constraints */
8494 	   )
8495 	{
8496 	   int c;
8497 	
8498 	   /* loop through linear constraints */
8499 	   for (c = 0; c < nlinconss; ++c)
8500 	   {
8501 	      SCIP_CONS* lincons;
8502 	      int nvars;
8503 	
8504 	      lincons = linconss[c];
8505 	
8506 	      /* variable bound constraints only contain two variables */
8507 	      nvars = SCIPgetNVarsLinear(scip, lincons);
8508 	      if ( nvars == 2 )
8509 	      {
8510 	         SCIP_VAR** vars;
8511 	         SCIP_Real* vals;
8512 	         SCIP_VAR* var0;
8513 	         SCIP_VAR* var1;
8514 	         SCIP_Real lhs;
8515 	         SCIP_Real rhs;
8516 	
8517 	         /* get constraint data */
8518 	         vars = SCIPgetVarsLinear(scip, lincons);
8519 	         vals = SCIPgetValsLinear(scip, lincons);
8520 	         lhs = SCIPgetLhsLinear(scip, lincons);
8521 	         rhs = SCIPgetRhsLinear(scip, lincons);
8522 	
8523 	         var0 = vars[0];
8524 	         var1 = vars[1];
8525 	         assert( var0 != NULL && var1 != NULL );
8526 	
8527 	         /* at least one variable should be an SOS1 variable */
8528 	         if ( varIsSOS1(conshdlrdata, var0) || varIsSOS1(conshdlrdata, var1) )
8529 	         {
8530 	            SCIP_Real val0;
8531 	            SCIP_Real val1;
8532 	
8533 	            /* check whether right hand side or left hand side of constraint is zero */
8534 	            if ( SCIPisFeasZero(scip, lhs) )
8535 	            {
8536 	               val0 = -vals[0];
8537 	               val1 = -vals[1];
8538 	
8539 	               /* check whether the two variables are in a variable bound relation */
8540 	               SCIP_CALL( detectVarboundSOS1(scip, conshdlrdata, var0, var1, val0, val1) );
8541 	               SCIP_CALL( detectVarboundSOS1(scip, conshdlrdata, var1, var0, val1, val0) );
8542 	            }
8543 	            else if( SCIPisFeasZero(scip, rhs) )
8544 	            {
8545 	               val0 = vals[0];
8546 	               val1 = vals[1];
8547 	
8548 	               /* check whether the two variables are in a variable bound relation */
8549 	               SCIP_CALL( detectVarboundSOS1(scip, conshdlrdata, var0, var1, val0, val1) );
8550 	               SCIP_CALL( detectVarboundSOS1(scip, conshdlrdata, var1, var0, val1, val0) );
8551 	            }
8552 	         }
8553 	      }
8554 	   }
8555 	
8556 	   return SCIP_OKAY;
8557 	}
8558 	
8559 	
8560 	/** switch to SOS1 branching and separating bound iniqualities from SOS1 constraints if the SOS1 constraints do not overlap */
8561 	static
8562 	SCIP_RETCODE checkSwitchNonoverlappingSOS1Methods(
8563 	   SCIP*                 scip,               /**< SCIP pointer */
8564 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< SOS1 constraint handler data */
8565 	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
8566 	   SCIP_CONS**           conss,              /**< SOS1 constraints */
8567 	   int                   nconss              /**< number of SOS1 constraints */
8568 	   )
8569 	{
8570 	   SCIP_Bool nonoverlap = TRUE;
8571 	   int c;
8572 	
8573 	   /* loop through all SOS1 constraints */
8574 	   if ( conshdlrdata->nsos1vars > 0 )
8575 	   {
8576 	      for (c = 0; c < nconss && nonoverlap; ++c)
8577 	      {
8578 	         SCIP_CONSDATA* consdata;
8579 	         SCIP_VAR** vars;
8580 	         int notfixed = 0;
8581 	         int nvars;
8582 	         int i;
8583 	
8584 	         assert( conss[c] != NULL );
8585 	
8586 	         /* get constraint data field of the constraint */
8587 	         consdata = SCIPconsGetData(conss[c]);
8588 	         assert( consdata != NULL );
8589 	
8590 	         /* get variables and number of variables of constraint */
8591 	         nvars = consdata->nvars;
8592 	         vars = consdata->vars;
8593 	
8594 	         /* get number of variables of SOS1 constraint that are not fixed to zero */
8595 	         for (i = 0; i < nvars; ++i)
8596 	         {
8597 	            if ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(vars[i])) || ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(vars[i])) )
8598 	               ++notfixed;
8599 	         }
8600 	
8601 	         /* check variables of SOS1 constraint */
8602 	         for (i = 0; i < nvars; ++i)
8603 	         {
8604 	            int node;
8605 	
8606 	            assert( vars[i] != NULL );
8607 	
8608 	            node = varGetNodeSOS1(conshdlrdata, vars[i]);
8609 	            assert( node >= 0 || ( SCIPisFeasZero(scip, SCIPvarGetLbLocal(vars[i])) && SCIPisFeasZero(scip, SCIPvarGetUbLocal(vars[i]))) );
8610 	            assert( node < conshdlrdata->nsos1vars );
8611 	            assert( node < 0 || SCIPdigraphGetNSuccessors(conflictgraph, node) >= notfixed-1 );
8612 	            if ( node >= 0 && SCIPdigraphGetNSuccessors(conflictgraph, node) > notfixed-1 )
8613 	            {
8614 	               nonoverlap = FALSE;
8615 	               break;
8616 	            }
8617 	         }
8618 	      }
8619 	   }
8620 	
8621 	   /* if the SOS1 constraints do not overlap */
8622 	   if ( nonoverlap )
8623 	   {
8624 	      if ( conshdlrdata->autosos1branch )
8625 	      {
8626 	         conshdlrdata->switchsos1branch = TRUE;
8627 	         SCIPdebugMsg(scip, "Switched to SOS1 branching, since the SOS1 constraints do not overlap\n");
8628 	      }
8629 	
8630 	      if ( conshdlrdata->autocutsfromsos1 )
8631 	      {
8632 	         conshdlrdata->switchcutsfromsos1 = TRUE;
8633 	         SCIPdebugMsg(scip, "Switched to separating bound cuts from SOS1 constraints (and not from the conflict graph), since the SOS1 constraints do not overlap\n");
8634 	      }
8635 	   }
8636 	
8637 	   return SCIP_OKAY;
8638 	}
8639 	
8640 	
8641 	/** sets node data of conflict graph nodes */
8642 	static
8643 	SCIP_RETCODE computeNodeDataSOS1(
8644 	   SCIP*                 scip,               /**< SCIP pointer */
8645 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< SOS1 constraint handler data */
8646 	   int                   nsos1vars           /**< number of SOS1 variables */
8647 	   )
8648 	{
8649 	   SCIP_CONSHDLR* linconshdlr;
8650 	   SCIP_CONS** linconss;
8651 	   int nlinconss;
8652 	
8653 	   /* if no SOS1 variables exist -> exit */
8654 	   if ( nsos1vars == 0 )
8655 	      return SCIP_OKAY;
8656 	
8657 	   /* get constraint handler data of linear constraints */
8658 	   linconshdlr = SCIPfindConshdlr(scip, "linear");
8659 	   if ( linconshdlr == NULL )
8660 	      return SCIP_OKAY;
8661 	
8662 	   /* get linear constraints and number of linear constraints */
8663 	   nlinconss = SCIPconshdlrGetNConss(linconshdlr);
8664 	   linconss = SCIPconshdlrGetConss(linconshdlr);
8665 	
8666 	   /* check linear constraints for variable bound constraints */
8667 	   SCIP_CALL( checkLinearConssVarboundSOS1(scip, conshdlrdata, linconss, nlinconss) );
8668 	
8669 	   /* for each connected component of the conflict graph check whether all the variables correspond to a unique variable
8670 	    * upper bound variable */
8671 	   SCIP_CALL( checkConComponentsVarbound(scip, conshdlrdata->conflictgraph, conshdlrdata->nsos1vars, TRUE) );
8672 	   SCIP_CALL( checkConComponentsVarbound(scip, conshdlrdata->conflictgraph, conshdlrdata->nsos1vars, FALSE) );
8673 	
8674 	   return SCIP_OKAY;
8675 	}
8676 	
8677 	
8678 	/** initialize conflictgraph and create hashmap for SOS1 variables */
8679 	static
8680 	SCIP_RETCODE initConflictgraph(
8681 	   SCIP*                 scip,               /**< SCIP pointer */
8682 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
8683 	   SCIP_CONS**           conss,              /**< SOS1 constraints */
8684 	   int                   nconss              /**< number of SOS1 constraints */
8685 	   )
8686 	{
8687 	   SCIP_Bool* nodecreated; /* nodecreated[i] = TRUE if a node in the conflict graph is already created for index i
8688 	                            * (with i index of the original variables) */
8689 	   int* nodeorig;          /* nodeorig[i] = node of original variable x_i in the conflict graph */
8690 	   int ntotalvars;
8691 	   int cntsos;
8692 	   int i;
8693 	   int j;
8694 	   int c;
8695 	
8696 	   assert( conshdlrdata != NULL );
8697 	   assert( nconss == 0 || conss != NULL );
8698 	
8699 	   /* get the number of original problem variables */
8700 	   ntotalvars = SCIPgetNTotalVars(scip);
8701 	
8702 	   /* initialize vector 'nodecreated' */
8703 	   SCIP_CALL( SCIPallocBufferArray(scip, &nodeorig, ntotalvars) );
8704 	   SCIP_CALL( SCIPallocBufferArray(scip, &nodecreated, ntotalvars) );
8705 	   for (i = 0; i < ntotalvars; ++i)
8706 	      nodecreated[i] = FALSE;
8707 	
8708 	   /* compute number of SOS1 variables */
8709 	   cntsos = 0;
8710 	   for (c = 0; c < nconss; ++c)
8711 	   {
8712 	      SCIP_CONSDATA* consdata;
8713 	      SCIP_VAR** vars;
8714 	      int nvars;
8715 	
8716 	      assert( conss[c] != NULL );
8717 	
8718 	      /* get constraint data field of the constraint */
8719 	      consdata = SCIPconsGetData(conss[c]);
8720 	      assert( consdata != NULL );
8721 	
8722 	      /* get variables and number of variables of constraint */
8723 	      nvars = consdata->nvars;
8724 	      vars = consdata->vars;
8725 	
8726 	      /* update number of SOS1 variables */
8727 	      for (i = 0; i < nvars; ++i)
8728 	      {
8729 	         SCIP_VAR* var;
8730 	
8731 	         var = vars[i];
8732 	
8733 	         /* if the variable is not fixed to zero */
8734 	         if ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) || ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
8735 	         {
8736 	            int ind;
8737 	
8738 	            ind = SCIPvarGetIndex(var);
8739 	            assert( ind >= 0 && ind < ntotalvars );
8740 	            if ( ! nodecreated[ind] )
8741 	            {
8742 	               nodecreated[ind] = TRUE; /* mark node as counted */
8743 	               nodeorig[ind] = cntsos;
8744 	               ++cntsos;
8745 	            }
8746 	         }
8747 	      }
8748 	   }
8749 	   if ( cntsos <= 0 )
8750 	   {
8751 	      /* free buffer arrays */
8752 	      SCIPfreeBufferArray(scip, &nodecreated);
8753 	      SCIPfreeBufferArray(scip, &nodeorig);
8754 	      conshdlrdata->nsos1vars = 0;
8755 	      return SCIP_OKAY;
8756 	   }
8757 	
8758 	   /* reinitialize vector 'nodecreated' */
8759 	   for (i = 0; i < ntotalvars; ++i)
8760 	      nodecreated[i] = FALSE;
8761 	
8762 	   /* create conflict graph */
8763 	   SCIP_CALL( SCIPcreateDigraph(scip, &conshdlrdata->conflictgraph, cntsos) );
8764 	
8765 	   /* set up hash map */
8766 	   SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->varhash, SCIPblkmem(scip), cntsos) );
8767 	
8768 	   /* for every SOS1 constraint */
8769 	   cntsos = 0;
8770 	   for (c = 0; c < nconss; ++c)
8771 	   {
8772 	      SCIP_CONSDATA* consdata;
8773 	      SCIP_VAR** vars;
8774 	      int nvars;
8775 	
8776 	      assert( conss[c] != NULL );
8777 	
8778 	      /* get constraint data field of the constraint */
8779 	      consdata = SCIPconsGetData(conss[c]);
8780 	      assert( consdata != NULL );
8781 	
8782 	      /* get variables and number of variables of constraint */
8783 	      nvars = consdata->nvars;
8784 	      vars = consdata->vars;
8785 	
8786 	      /* add edges to the conflict graph and create node data for each of its nodes */
8787 	      for (i = 0; i < nvars; ++i)
8788 	      {
8789 	         SCIP_VAR* var;
8790 	
8791 	         var = vars[i];
8792 	
8793 	         /* if the variable is not fixed to zero */
8794 	         if ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) || ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
8795 	         {
8796 	            int indi;
8797 	
8798 	            indi = SCIPvarGetIndex(var);
8799 	
8800 	            if ( ! nodecreated[indi] )
8801 	            {
8802 	               SCIP_NODEDATA* nodedata = NULL;
8803 	
8804 	               /* insert node number to hash map */
8805 	               assert( ! SCIPhashmapExists(conshdlrdata->varhash, var) );
8806 	               SCIP_CALL( SCIPhashmapInsertInt(conshdlrdata->varhash, var, cntsos) );
8807 	               assert( cntsos == SCIPhashmapGetImageInt(conshdlrdata->varhash, var) );
8808 	               assert( SCIPhashmapExists(conshdlrdata->varhash, var) );
8809 	
8810 	               /* create node data */
8811 	               SCIP_CALL( SCIPallocBlockMemory(scip, &nodedata) );
8812 	               nodedata->var = var;
8813 	               nodedata->lbboundvar = NULL;
8814 	               nodedata->ubboundvar = NULL;
8815 	               nodedata->lbboundcoef = 0.0;
8816 	               nodedata->ubboundcoef = 0.0;
8817 	               nodedata->lbboundcomp = FALSE;
8818 	               nodedata->ubboundcomp = FALSE;
8819 	
8820 	               /* set node data */
8821 	               SCIPdigraphSetNodeData(conshdlrdata->conflictgraph, (void*)nodedata, cntsos);
8822 	
8823 	               /* mark node and var data of node as created and update SOS1 counter */
8824 	               nodecreated[indi] = TRUE;
8825 	               ++cntsos;
8826 	            }
8827 	
8828 	            /* add edges to the conflict graph */
8829 	            for (j = i+1; j < nvars; ++j)
8830 	            {
8831 	               var = vars[j];
8832 	
8833 	               /* if the variable is not fixed to zero */
8834 	               if ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) || ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
8835 	               {
8836 	                  int indj;
8837 	
8838 	                  indj = SCIPvarGetIndex(var);
8839 	
8840 	                  /* in case indi = indj the variable will be deleted in the presolving step */
8841 	                  if ( indi != indj )
8842 	                  {
8843 	                     /* arcs have to be added 'safe' */
8844 	                     SCIP_CALL( SCIPdigraphAddArcSafe(conshdlrdata->conflictgraph, nodeorig[indi], nodeorig[indj], NULL) );
8845 	                     SCIP_CALL( SCIPdigraphAddArcSafe(conshdlrdata->conflictgraph, nodeorig[indj], nodeorig[indi], NULL) );
8846 	                  }
8847 	               }
8848 	            }
8849 	         }
8850 	      }
8851 	   }
8852 	
8853 	   /* set number of problem variables that are contained in at least one SOS1 constraint */
8854 	   conshdlrdata->nsos1vars = cntsos;
8855 	
8856 	   /* free buffer arrays */
8857 	   SCIPfreeBufferArray(scip, &nodecreated);
8858 	   SCIPfreeBufferArray(scip, &nodeorig);
8859 	
8860 	   /* sort successors in ascending order */
8861 	   for (j = 0; j < conshdlrdata->nsos1vars; ++j)
8862 	   {
8863 	      int nsucc;
8864 	
8865 	      nsucc = SCIPdigraphGetNSuccessors(conshdlrdata->conflictgraph, j);
8866 	      SCIPsortInt(SCIPdigraphGetSuccessors(conshdlrdata->conflictgraph, j), nsucc);
8867 	   }
8868 	
8869 	   return SCIP_OKAY;
8870 	}
8871 	
8872 	
8873 	/** free conflict graph, nodedata and hashmap */
8874 	static
8875 	SCIP_RETCODE freeConflictgraph(
8876 	   SCIP*                 scip,               /**< SCIP pointer */
8877 	   SCIP_CONSHDLRDATA*    conshdlrdata        /**< constraint handler data */
8878 	   )
8879 	{
8880 	   int j;
8881 	
8882 	   if ( conshdlrdata->conflictgraph == NULL )
8883 	   {
8884 	      assert( conshdlrdata->nsos1vars == 0 );
8885 	      return SCIP_OKAY;
8886 	   }
8887 	
8888 	   /* for every SOS1 variable */
8889 	   assert( conshdlrdata->nsos1vars > 0 );
8890 	   for (j = 0; j < conshdlrdata->nsos1vars; ++j)
8891 	   {
8892 	      SCIP_NODEDATA* nodedata;
8893 	
8894 	      /* get node data */
8895 	      assert( conshdlrdata->conflictgraph != NULL );
8896 	      nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conshdlrdata->conflictgraph, j);
8897 	      assert( nodedata != NULL );
8898 	
8899 	      /* free node data */
8900 	      SCIPfreeBlockMemory(scip, &nodedata);
8901 	      SCIPdigraphSetNodeData(conshdlrdata->conflictgraph, NULL, j);
8902 	   }
8903 	
8904 	   /* free conflict graph and hash map */
8905 	   assert( conshdlrdata->varhash != NULL );
8906 	   SCIPhashmapFree(&conshdlrdata->varhash);
8907 	   SCIPdigraphFree(&conshdlrdata->conflictgraph);
8908 	   conshdlrdata->nsos1vars = 0;
8909 	
8910 	   assert( conshdlrdata->varhash == NULL );
8911 	   assert( conshdlrdata->conflictgraph == NULL );
8912 	
8913 	   return SCIP_OKAY;
8914 	}
8915 	
8916 	
8917 	/* ---------------------------- constraint handler callback methods ----------------------*/
8918 	
8919 	/** copy method for constraint handler plugins (called when SCIP copies plugins) */
8920 	static
8921 	SCIP_DECL_CONSHDLRCOPY(conshdlrCopySOS1)
8922 	{  /*lint --e{715}*/
8923 	   assert( scip != NULL );
8924 	   assert( conshdlr != NULL );
8925 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
8926 	
8927 	   /* call inclusion method of constraint handler */
8928 	   SCIP_CALL( SCIPincludeConshdlrSOS1(scip) );
8929 	
8930 	   *valid = TRUE;
8931 	
8932 	   return SCIP_OKAY;
8933 	}
8934 	
8935 	
8936 	/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
8937 	static
8938 	SCIP_DECL_CONSFREE(consFreeSOS1)
8939 	{
8940 	   SCIP_CONSHDLRDATA* conshdlrdata;
8941 	
8942 	   assert( scip != NULL );
8943 	   assert( conshdlr != NULL );
8944 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
8945 	
8946 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
8947 	   assert(conshdlrdata != NULL);
8948 	
8949 	   /* free stack of variables fixed to nonzero (usually already freed in consExitsolSOS1 unless instance was solved during presolving) */
8950 	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->fixnonzerovars, conshdlrdata->maxnfixnonzerovars); /*lint !e737*/
8951 	
8952 	   SCIPfreeBlockMemory(scip, &conshdlrdata);
8953 	
8954 	   return SCIP_OKAY;
8955 	}
8956 	
8957 	
8958 	/** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
8959 	static
8960 	SCIP_DECL_CONSINITSOL(consInitsolSOS1)
8961 	{  /*lint --e{715}*/
8962 	    SCIP_CONSHDLRDATA* conshdlrdata;
8963 	
8964 	    assert( scip != NULL );
8965 	    assert( conshdlr != NULL );
8966 	    assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
8967 	
8968 	    conshdlrdata = SCIPconshdlrGetData(conshdlr);
8969 	    assert( conshdlrdata != NULL );
8970 	
8971 	    conshdlrdata->nsos1vars = 0;
8972 	    conshdlrdata->varhash = NULL;
8973 	
8974 	    if ( nconss > 0 )
8975 	    {
8976 	       /* initialize conflict graph and hashmap for SOS1 variables */
8977 	       SCIP_CALL( initConflictgraph(scip, conshdlrdata, conss, nconss) );
8978 	
8979 	       /* add data to conflict graph nodes */
8980 	       SCIP_CALL( computeNodeDataSOS1(scip, conshdlrdata, conshdlrdata->nsos1vars) );
8981 	
8982 	       if ( ( conshdlrdata->autosos1branch || conshdlrdata->autocutsfromsos1 )
8983 	          && ( ! conshdlrdata->switchsos1branch || ! conshdlrdata->switchcutsfromsos1 )
8984 	          )
8985 	       {
8986 	          /* switch to nonoverlapping methods if the SOS1 constraints do not overlap */
8987 	          SCIP_CALL( checkSwitchNonoverlappingSOS1Methods(scip, conshdlrdata, conshdlrdata->conflictgraph, conss, nconss) );
8988 	       }
8989 	
8990 	       /* initialize tclique graph */
8991 	       SCIP_CALL( initTCliquegraph(scip, conshdlr, conshdlrdata, conshdlrdata->conflictgraph, conshdlrdata->nsos1vars) );
8992 	
8993 	       /* create local conflict graph if needed */
8994 	       if ( conshdlrdata->addcomps )
8995 	       {
8996 	          SCIP_CALL( SCIPcreateDigraph(scip, &conshdlrdata->localconflicts, conshdlrdata->nsos1vars) );
8997 	       }
8998 	
8999 	       /* initialize stack of variables fixed to nonzero (memory may be already allocated in consTransSOS1()) */
9000 	       if ( conshdlrdata->fixnonzerovars == NULL )
9001 	       {
9002 	          conshdlrdata->maxnfixnonzerovars = conshdlrdata->nsos1vars;
9003 	          SCIP_CALL( SCIPallocBlockMemoryArray(scip, &conshdlrdata->fixnonzerovars, conshdlrdata->maxnfixnonzerovars) );
9004 	       }
9005 	    }
9006 	
9007 	    return SCIP_OKAY;
9008 	}
9009 	
9010 	
9011 	/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
9012 	static
9013 	SCIP_DECL_CONSEXITSOL(consExitsolSOS1)
9014 	{  /*lint --e{715}*/
9015 	   SCIP_CONSHDLRDATA* conshdlrdata;
9016 	   int c;
9017 	
9018 	   assert( scip != NULL );
9019 	   assert( conshdlr != NULL );
9020 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9021 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
9022 	   assert( conshdlrdata != NULL );
9023 	
9024 	   /* check each constraint */
9025 	   for (c = 0; c < nconss; ++c)
9026 	   {
9027 	      SCIP_CONSDATA* consdata;
9028 	
9029 	      assert( conss != NULL );
9030 	      assert( conss[c] != NULL );
9031 	      consdata = SCIPconsGetData(conss[c]);
9032 	      assert( consdata != NULL );
9033 	
9034 	      SCIPdebugMsg(scip, "Exiting SOS1 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
9035 	
9036 	      /* free rows */
9037 	      if ( consdata->rowub != NULL )
9038 	      {
9039 	         SCIP_CALL( SCIPreleaseRow(scip, &consdata->rowub) );
9040 	      }
9041 	
9042 	      if ( consdata->rowlb != NULL )
9043 	      {
9044 	         SCIP_CALL( SCIPreleaseRow(scip, &consdata->rowlb) );
9045 	      }
9046 	   }
9047 	
9048 	   /* free implication graph */
9049 	   if ( conshdlrdata->implgraph != NULL )
9050 	   {
9051 	      SCIP_CALL( freeImplGraphSOS1(scip, conshdlrdata) );
9052 	   }
9053 	   assert( conshdlrdata->implgraph == NULL );
9054 	
9055 	   /* free tclique graph and tclique data */
9056 	   if ( conshdlrdata->tcliquegraph != NULL )
9057 	   {
9058 	      assert( conshdlrdata->tcliquedata != NULL );
9059 	      SCIPfreeBlockMemory(scip, &conshdlrdata->tcliquedata);
9060 	      tcliqueFree(&conshdlrdata->tcliquegraph);
9061 	   }
9062 	   assert(conshdlrdata->tcliquegraph == NULL);
9063 	   assert(conshdlrdata->tcliquedata == NULL);
9064 	
9065 	   /* free stack of variables fixed to nonzero */
9066 	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->fixnonzerovars, conshdlrdata->maxnfixnonzerovars); /*lint !e737*/
9067 	   conshdlrdata->nfixnonzerovars = 0;
9068 	   conshdlrdata->maxnfixnonzerovars = 0;
9069 	
9070 	   /* free graph for storing local conflicts */
9071 	   if ( conshdlrdata->localconflicts != NULL )
9072 	      SCIPdigraphFree(&conshdlrdata->localconflicts);
9073 	   assert( conshdlrdata->localconflicts == NULL );
9074 	
9075 	   /* free conflict graph  */
9076 	   SCIP_CALL( freeConflictgraph(scip, conshdlrdata) );
9077 	   assert( conshdlrdata->conflictgraph == NULL );
9078 	
9079 	   return SCIP_OKAY;
9080 	}
9081 	
9082 	
9083 	/** frees specific constraint data */
9084 	static
9085 	SCIP_DECL_CONSDELETE(consDeleteSOS1)
9086 	{
9087 	   assert( scip != NULL );
9088 	   assert( conshdlr != NULL );
9089 	   assert( cons != NULL );
9090 	   assert( consdata != NULL );
9091 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9092 	
9093 	   SCIPdebugMsg(scip, "Deleting SOS1 constraint <%s>.\n", SCIPconsGetName(cons) );
9094 	
9095 	   /* drop events on transformed variables */
9096 	   if ( SCIPconsIsTransformed(cons) )
9097 	   {
9098 	      SCIP_CONSHDLRDATA* conshdlrdata;
9099 	      int j;
9100 	
9101 	      /* get constraint handler data */
9102 	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
9103 	      assert( conshdlrdata != NULL );
9104 	      assert( conshdlrdata->eventhdlr != NULL );
9105 	
9106 	      for (j = 0; j < (*consdata)->nvars; ++j)
9107 	      {
9108 	         SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->vars[j], EVENTHDLR_EVENT_TYPE, conshdlrdata->eventhdlr,
9109 	               (SCIP_EVENTDATA*)cons, -1) ); /*lint !e737 !e740*/
9110 	      }
9111 	   }
9112 	
9113 	   SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->maxvars);
9114 	   if ( (*consdata)->weights != NULL )
9115 	   {
9116 	      SCIPfreeBlockMemoryArray(scip, &(*consdata)->weights, (*consdata)->maxvars);
9117 	   }
9118 	
9119 	   /* free rows */
9120 	   if ( (*consdata)->rowub != NULL )
9121 	   {
9122 	      SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->rowub) );
9123 	   }
9124 	   if ( (*consdata)->rowlb != NULL )
9125 	   {
9126 	      SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->rowlb) );
9127 	   }
9128 	   assert( (*consdata)->rowub == NULL );
9129 	   assert( (*consdata)->rowlb == NULL );
9130 	
9131 	   SCIPfreeBlockMemory(scip, consdata);
9132 	
9133 	   return SCIP_OKAY;
9134 	}
9135 	
9136 	
9137 	/** transforms constraint data into data belonging to the transformed problem */
9138 	static
9139 	SCIP_DECL_CONSTRANS(consTransSOS1)
9140 	{
9141 	   SCIP_CONSDATA* consdata;
9142 	   SCIP_CONSHDLRDATA* conshdlrdata;
9143 	   SCIP_CONSDATA* sourcedata;
9144 	   char s[SCIP_MAXSTRLEN];
9145 	   int j;
9146 	
9147 	   assert( scip != NULL );
9148 	   assert( conshdlr != NULL );
9149 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9150 	   assert( sourcecons != NULL );
9151 	   assert( targetcons != NULL );
9152 	
9153 	   /* get constraint handler data */
9154 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
9155 	   assert( conshdlrdata != NULL );
9156 	   assert( conshdlrdata->eventhdlr != NULL );
9157 	
9158 	   SCIPdebugMsg(scip, "Transforming SOS1 constraint: <%s>.\n", SCIPconsGetName(sourcecons) );
9159 	
9160 	   /* get data of original constraint */
9161 	   sourcedata = SCIPconsGetData(sourcecons);
9162 	   assert( sourcedata != NULL );
9163 	   assert( sourcedata->nvars > 0 );
9164 	   assert( sourcedata->nvars <= sourcedata->maxvars );
9165 	
9166 	   /* initialize stack of variables fixed to nonzero */
9167 	   if ( conshdlrdata->fixnonzerovars == NULL )
9168 	   {
9169 	      conshdlrdata->maxnfixnonzerovars = SCIPgetNTotalVars(scip);
9170 	      SCIP_CALL( SCIPallocBlockMemoryArray(scip, &conshdlrdata->fixnonzerovars, conshdlrdata->maxnfixnonzerovars) );
9171 	   }
9172 	
9173 	   /* create constraint data */
9174 	   SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
9175 	
9176 	   consdata->nvars = sourcedata->nvars;
9177 	   consdata->maxvars = sourcedata->nvars;
9178 	   consdata->rowub = NULL;
9179 	   consdata->rowlb = NULL;
9180 	   consdata->nfixednonzeros = 0;
9181 	   consdata->local = sourcedata->local;
9182 	
9183 	   SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, consdata->nvars) );
9184 	
9185 	   /* if weights were used */
9186 	   if ( sourcedata->weights != NULL )
9187 	   {
9188 	      SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->weights, sourcedata->weights, consdata->nvars) );
9189 	   }
9190 	   else
9191 	      consdata->weights = NULL;
9192 	
9193 	   for (j = 0; j < sourcedata->nvars; ++j)
9194 	   {
9195 	      assert( sourcedata->vars[j] != 0 );
9196 	      SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->vars[j], &(consdata->vars[j])) );
9197 	
9198 	      /* if variable is fixed to be nonzero */
9199 	      if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(consdata->vars[j])) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(consdata->vars[j])) )
9200 	         ++(consdata->nfixednonzeros);
9201 	   }
9202 	
9203 	   /* create transformed constraint with the same flags */
9204 	   (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons));
9205 	   SCIP_CALL( SCIPcreateCons(scip, targetcons, s, conshdlr, consdata,
9206 	         SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
9207 	         SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
9208 	         SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
9209 	         SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
9210 	         SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
9211 	
9212 	   /* catch bound change events on variable */
9213 	   for (j = 0; j < consdata->nvars; ++j)
9214 	   {
9215 	      SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[j], EVENTHDLR_EVENT_TYPE, conshdlrdata->eventhdlr,
9216 	            (SCIP_EVENTDATA*)*targetcons, NULL) ); /*lint !e740*/
9217 	   }
9218 	
9219 	#ifdef SCIP_DEBUG
9220 	   if ( consdata->nfixednonzeros > 0 )
9221 	   {
9222 	      SCIPdebugMsg(scip, "constraint <%s> has %d variables fixed to be nonzero.\n", SCIPconsGetName(*targetcons),
9223 	         consdata->nfixednonzeros );
9224 	   }
9225 	#endif
9226 	
9227 	   return SCIP_OKAY;
9228 	}
9229 	
9230 	
9231 	/** presolving method of constraint handler */
9232 	static
9233 	SCIP_DECL_CONSPRESOL(consPresolSOS1)
9234 	{  /*lint --e{715}*/
9235 	   SCIP_CONSHDLRDATA* conshdlrdata;
9236 	   SCIPdebug( int oldnfixedvars = *nfixedvars; )
9237 	   SCIPdebug( int oldnchgbds = *nchgbds; )
9238 	   SCIPdebug( int oldndelconss = *ndelconss; )
9239 	   SCIPdebug( int oldnupgdconss = *nupgdconss; )
9240 	   int nremovedvars;
9241 	
9242 	   assert( scip != NULL );
9243 	   assert( conshdlr != NULL );
9244 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9245 	   assert( result != NULL );
9246 	
9247 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
9248 	   assert( conshdlrdata != NULL );
9249 	
9250 	   SCIPdebugMsg(scip, "Presolving SOS1 constraints.\n");
9251 	
9252 	   *result = SCIP_DIDNOTRUN;
9253 	
9254 	   nremovedvars = 0;
9255 	
9256 	   /* only run if success if possible */
9257 	   if( nconss > 0 && ( nrounds == 0 || nnewfixedvars > 0 || nnewaggrvars > 0 || nnewchgbds > 0 ) )
9258 	   {
9259 	      SCIP_Bool** adjacencymatrix = NULL;
9260 	      SCIP_DIGRAPH* conflictgraph;
9261 	      SCIP_EVENTHDLR* eventhdlr;
9262 	      int nsos1vars;
9263 	      int i;
9264 	      int j;
9265 	
9266 	      *result = SCIP_DIDNOTFIND;
9267 	
9268 	      /* get constraint handler data */
9269 	      assert( SCIPconshdlrGetData(conshdlr) != NULL );
9270 	      eventhdlr = SCIPconshdlrGetData(conshdlr)->eventhdlr;
9271 	      assert( eventhdlr != NULL );
9272 	
9273 	      /* initialize conflict graph */
9274 	      SCIP_CALL( initConflictgraph(scip, conshdlrdata, conss, nconss));
9275 	
9276 	      /* get conflict graph and number of SOS1 variables */
9277 	      conflictgraph = conshdlrdata->conflictgraph;
9278 	      nsos1vars = conshdlrdata->nsos1vars;
9279 	      if ( nsos1vars < 2 )
9280 	      {
9281 	         SCIP_CALL( freeConflictgraph(scip, conshdlrdata));
9282 	         return SCIP_OKAY;
9283 	      }
9284 	
9285 	      /* we do not create the adjacency matrix of the conflict graph if the number of SOS1 variables is larger than a predefined value */
9286 	      if ( conshdlrdata->maxsosadjacency == -1 || nsos1vars <= conshdlrdata->maxsosadjacency )
9287 	      {
9288 	         /* allocate buffer arrays for adjacency matrix  */
9289 	         SCIP_CALL( SCIPallocBufferArray(scip, &adjacencymatrix, nsos1vars) );
9290 	         for (i = 0; i < nsos1vars; ++i)
9291 	         {
9292 	            SCIP_CALL( SCIPallocBufferArray(scip, &adjacencymatrix[i], i+1) );/*lint !e866*/
9293 	         }
9294 	
9295 	         /* create adjacency matrix */
9296 	         for (i = 0; i < nsos1vars; ++i)
9297 	         {
9298 	            for (j = 0; j < i+1; ++j)
9299 	               adjacencymatrix[i][j] = 0;
9300 	         }
9301 	         for (i = 0; i < nsos1vars; ++i)
9302 	         {
9303 	            int* succ;
9304 	            int nsucc;
9305 	
9306 	            succ = SCIPdigraphGetSuccessors(conflictgraph, i);
9307 	            nsucc = SCIPdigraphGetNSuccessors(conflictgraph, i);
9308 	
9309 	            for (j = 0; j < nsucc; ++j)
9310 	            {
9311 	               if ( i > succ[j] )
9312 	                  adjacencymatrix[i][succ[j]] = 1;
9313 	            }
9314 	         }
9315 	      }
9316 	      else
9317 	      {
9318 	         SCIPdebugMsg(scip, "Adjacency matrix was not created since number of SOS1 variables (%d) is larger than %d.\n", nsos1vars, conshdlrdata->maxsosadjacency);
9319 	      }
9320 	
9321 	      /* perform one presolving round for SOS1 constraints */
9322 	      SCIP_CALL( presolRoundConssSOS1(scip, eventhdlr, conshdlrdata, conflictgraph, adjacencymatrix, conss, nconss, nsos1vars, naddconss, ndelconss, nupgdconss, nfixedvars, &nremovedvars, result) );
9323 	
9324 	      if ( adjacencymatrix != NULL )
9325 	      {
9326 	         /* perform one presolving round for SOS1 variables */
9327 	         if ( conshdlrdata->maxtightenbds != 0 && *result != SCIP_CUTOFF )
9328 	         {
9329 	            SCIP_CALL( presolRoundVarsSOS1(scip, conshdlrdata, conflictgraph, adjacencymatrix, nsos1vars, nfixedvars, nchgbds, naddconss, result) );
9330 	         }
9331 	
9332 	         /* free adjacency matrix */
9333 	         for (j = nsos1vars-1; j >= 0; --j)
9334 	            SCIPfreeBufferArrayNull(scip, &adjacencymatrix[j]);
9335 	         SCIPfreeBufferArrayNull(scip, &adjacencymatrix);
9336 	      }
9337 	
9338 	      /* free memory allocated in function initConflictgraph() */
9339 	      SCIP_CALL( freeConflictgraph(scip, conshdlrdata));
9340 	   }
9341 	   (*nchgcoefs) += nremovedvars;
9342 	
9343 	   SCIPdebug( SCIPdebugMsg(scip, "presolving fixed %d variables, changed %d bounds, removed %d variables, deleted %d constraints, and upgraded %d constraints.\n",
9344 	                *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds, nremovedvars, *ndelconss - oldndelconss, *nupgdconss - oldnupgdconss); )
9345 	
9346 	   return SCIP_OKAY;
9347 	}
9348 	
9349 	
9350 	/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
9351 	static
9352 	SCIP_DECL_CONSINITLP(consInitlpSOS1)
9353 	{
9354 	   SCIP_CONSHDLRDATA* conshdlrdata;
9355 	
9356 	   assert( scip != NULL );
9357 	   assert( conshdlr != NULL );
9358 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9359 	
9360 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
9361 	   assert( conshdlrdata != NULL );
9362 	
9363 	   *infeasible = FALSE;
9364 	
9365 	   /* checking for initial rows for SOS1 constraints */
9366 	   if( conshdlrdata->boundcutsfromsos1 || conshdlrdata->switchcutsfromsos1 )
9367 	   {
9368 	      SCIP_CALL( initsepaBoundInequalityFromSOS1Cons(scip, conshdlr, conshdlrdata, conss, nconss, NULL, FALSE, -1, NULL, infeasible) );
9369 	   }
9370 	
9371 	   return SCIP_OKAY;
9372 	}
9373 	
9374 	
9375 	/** separation method of constraint handler for LP solutions */
9376 	static
9377 	SCIP_DECL_CONSSEPALP(consSepalpSOS1)
9378 	{  /*lint --e{715}*/
9379 	   assert( scip != NULL );
9380 	   assert( conshdlr != NULL );
9381 	   assert( conss != NULL );
9382 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9383 	   assert( result != NULL );
9384 	
9385 	   SCIP_CALL( separateSOS1(scip, conshdlr, NULL, nconss, conss, result) );
9386 	
9387 	   return SCIP_OKAY;
9388 	}
9389 	
9390 	
9391 	/** separation method of constraint handler for arbitrary primal solutions */
9392 	static
9393 	SCIP_DECL_CONSSEPASOL(consSepasolSOS1)
9394 	{  /*lint --e{715}*/
9395 	   assert( scip != NULL );
9396 	   assert( conshdlr != NULL );
9397 	   assert( conss != NULL );
9398 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9399 	   assert( result != NULL );
9400 	
9401 	   SCIP_CALL( separateSOS1(scip, conshdlr, sol, nconss, conss, result) );
9402 	
9403 	   return SCIP_OKAY;
9404 	}
9405 	
9406 	
9407 	/** constraint enforcing method of constraint handler for LP solutions */
9408 	static
9409 	SCIP_DECL_CONSENFOLP(consEnfolpSOS1)
9410 	{  /*lint --e{715}*/
9411 	   assert( scip != NULL );
9412 	   assert( conshdlr != NULL );
9413 	   assert( conss != NULL );
9414 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9415 	   assert( result != NULL );
9416 	
9417 	   SCIP_CALL( enforceSOS1(scip, conshdlr, nconss, conss, NULL, result) );
9418 	
9419 	   return SCIP_OKAY;
9420 	}
9421 	
9422 	
9423 	/** constraint enforcing method of constraint handler for relaxation solutions */
9424 	static
9425 	SCIP_DECL_CONSENFORELAX(consEnforelaxSOS1)
9426 	{  /*lint --e{715}*/
9427 	   assert( scip != NULL );
9428 	   assert( conshdlr != NULL );
9429 	   assert( conss != NULL );
9430 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9431 	   assert( result != NULL );
9432 	
9433 	   SCIP_CALL( enforceSOS1(scip, conshdlr, nconss, conss, sol, result) );
9434 	
9435 	   return SCIP_OKAY;
9436 	}
9437 	
9438 	
9439 	/** constraint enforcing method of constraint handler for pseudo solutions */
9440 	static
9441 	SCIP_DECL_CONSENFOPS(consEnfopsSOS1)
9442 	{  /*lint --e{715}*/
9443 	   assert( scip != NULL );
9444 	   assert( conshdlr != NULL );
9445 	   assert( conss != NULL );
9446 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9447 	   assert( result != NULL );
9448 	
9449 	   SCIP_CALL( enforceSOS1(scip, conshdlr, nconss, conss, NULL, result) );
9450 	
9451 	   return SCIP_OKAY;
9452 	}
9453 	
9454 	
9455 	/** feasibility check method of constraint handler for integral solutions
9456 	 *
9457 	 *  We simply check whether at most one variable is nonzero in the given solution.
9458 	 */
9459 	static
9460 	SCIP_DECL_CONSCHECK(consCheckSOS1)
9461 	{  /*lint --e{715}*/
9462 	   int c;
9463 	
9464 	   assert( scip != NULL );
9465 	   assert( conshdlr != NULL );
9466 	   assert( conss != NULL );
9467 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9468 	   assert( result != NULL );
9469 	
9470 	   *result = SCIP_FEASIBLE;
9471 	
9472 	   /* check each constraint */
9473 	   for (c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c)
9474 	   {
9475 	      SCIP_CONSDATA* consdata;
9476 	      int j;
9477 	      int cnt;
9478 	
9479 	      cnt = 0;
9480 	      assert( conss[c] != NULL );
9481 	      consdata = SCIPconsGetData(conss[c]);
9482 	      assert( consdata != NULL );
9483 	      SCIPdebugMsg(scip, "Checking SOS1 constraint <%s>.\n", SCIPconsGetName(conss[c]));
9484 	
9485 	      /* check all variables */
9486 	      for (j = 0; j < consdata->nvars; ++j)
9487 	      {
9488 	         /* if variable is nonzero */
9489 	         if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vars[j])) )
9490 	         {
9491 	            ++cnt;
9492 	
9493 	            /* if more than one variable is nonzero */
9494 	            if ( cnt > 1 )
9495 	            {
9496 	               SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
9497 	               *result = SCIP_INFEASIBLE;
9498 	
9499 	               /* update constraint violation in solution */
9500 	               if ( sol != NULL )
9501 	                  SCIPupdateSolConsViolation(scip, sol, 1.0, 1.0);
9502 	
9503 	               if ( printreason )
9504 	               {
9505 	                  int l;
9506 	
9507 	                  SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) );
9508 	                  SCIPinfoMessage(scip, NULL, ";\nviolation: ");
9509 	
9510 	                  for (l = 0; l < consdata->nvars; ++l)
9511 	                  {
9512 	                     /* if variable is nonzero */
9513 	                     if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vars[l])) )
9514 	                     {
9515 	                        SCIPinfoMessage(scip, NULL, "<%s> = %.15g ",
9516 	                           SCIPvarGetName(consdata->vars[l]), SCIPgetSolVal(scip, sol, consdata->vars[l]));
9517 	                     }
9518 	                  }
9519 	                  SCIPinfoMessage(scip, NULL, "\n");
9520 	               }
9521 	            }
9522 	         }
9523 	      }
9524 	   }
9525 	
9526 	   return SCIP_OKAY;
9527 	}
9528 	
9529 	
9530 	/** domain propagation method of constraint handler */
9531 	static
9532 	SCIP_DECL_CONSPROP(consPropSOS1)
9533 	{  /*lint --e{715}*/
9534 	   SCIP_CONSHDLRDATA* conshdlrdata;
9535 	   SCIP_DIGRAPH* conflictgraph;
9536 	   SCIP_DIGRAPH* implgraph;
9537 	   int ngen = 0;
9538 	
9539 	   assert( scip != NULL );
9540 	   assert( conshdlr != NULL );
9541 	   assert( conss != NULL );
9542 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9543 	   assert( result != NULL );
9544 	   assert( SCIPisTransformed(scip) );
9545 	
9546 	   /* return if number of SOS1 constraints is zero */
9547 	   if ( nconss < 1 )
9548 	   {
9549 	      *result = SCIP_DIDNOTRUN;
9550 	      return SCIP_OKAY;
9551 	   }
9552 	   *result = SCIP_DIDNOTFIND;
9553 	
9554 	   /* get constraint handler data */
9555 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
9556 	   assert( conshdlrdata != NULL );
9557 	
9558 	   /* get conflict graph */
9559 	   conflictgraph = conshdlrdata->conflictgraph;
9560 	
9561 	   /* get/initialize implication graph */
9562 	   implgraph = conshdlrdata->implgraph;
9563 	   if ( implgraph == NULL && conshdlrdata->implprop && conflictgraph != NULL )
9564 	   {
9565 	      if ( SCIPgetDepth(scip) == 0 )
9566 	      {
9567 	         SCIP_Bool success;
9568 	         SCIP_Bool cutoff;
9569 	         int nchbds;
9570 	
9571 	         SCIP_CALL( initImplGraphSOS1(scip, conshdlrdata, conflictgraph, conshdlrdata->nsos1vars, conshdlrdata->maxtightenbds, &nchbds, &cutoff, &success) );
9572 	         if ( ! success )
9573 	            conshdlrdata->implprop = FALSE;
9574 	
9575 	         if ( cutoff )
9576 	         {
9577 	            *result = SCIP_CUTOFF;
9578 	            return SCIP_OKAY;
9579 	         }
9580 	         else if ( nchbds > 0 )
9581 	            *result = SCIP_REDUCEDDOM;
9582 	         implgraph = conshdlrdata->implgraph;
9583 	      }
9584 	      else
9585 	         conshdlrdata->implprop = FALSE;
9586 	   }
9587 	
9588 	   /* if conflict graph propagation shall be used */
9589 	   if ( conshdlrdata->conflictprop && conflictgraph != NULL )
9590 	   {
9591 	      SCIP_VAR** fixnonzerovars;
9592 	      int nfixnonzerovars;
9593 	      int j;
9594 	
9595 	      assert( nconss > 0 );
9596 	
9597 	      /* stack of variables fixed to nonzero */
9598 	      nfixnonzerovars = conshdlrdata->nfixnonzerovars;
9599 	      fixnonzerovars = conshdlrdata->fixnonzerovars;
9600 	      assert( fixnonzerovars != NULL );
9601 	
9602 	      /* check each variable from stack */
9603 	      for (j = 0; j < nfixnonzerovars; ++j)
9604 	      {
9605 	         SCIP_VAR* var;
9606 	
9607 	         var = fixnonzerovars[j];
9608 	         if ( var != NULL )
9609 	         {
9610 	            int node;
9611 	            node = varGetNodeSOS1(conshdlrdata, var);
9612 	
9613 	            /* if variable is involved in an SOS1 constraint */
9614 	            if ( node >= 0 )
9615 	            {
9616 	               assert( varGetNodeSOS1(conshdlrdata, var) < conshdlrdata->nsos1vars );
9617 	               SCIPdebugMsg(scip, "Propagating SOS1 variable <%s>.\n", SCIPvarGetName(var) );
9618 	
9619 	               /* if zero is outside the domain of variable */
9620 	               if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var)) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(var)) )
9621 	               {
9622 	                  SCIP_Bool cutoff;
9623 	
9624 	                  SCIP_CALL( propVariableNonzero(scip, conflictgraph, implgraph, conss[0], node, conshdlrdata->implprop, &cutoff, &ngen) );
9625 	                  if ( cutoff )
9626 	                  {
9627 	                     *result = SCIP_CUTOFF;
9628 	                     return SCIP_OKAY;
9629 	                  }
9630 	               }
9631 	            }
9632 	         }
9633 	      }
9634 	   }
9635 	   conshdlrdata->nfixnonzerovars = 0;
9636 	
9637 	   /* if SOS1 constraint propagation shall be used */
9638 	   if ( conshdlrdata->sosconsprop || conflictgraph == NULL )
9639 	   {
9640 	      int c;
9641 	
9642 	      /* check each constraint */
9643 	      for (c = 0; c < nconss; ++c)
9644 	      {
9645 	         SCIP_CONS* cons;
9646 	         SCIP_CONSDATA* consdata;
9647 	         SCIP_Bool cutoff;
9648 	
9649 	         assert( conss[c] != NULL );
9650 	         cons = conss[c];
9651 	         consdata = SCIPconsGetData(cons);
9652 	         assert( consdata != NULL );
9653 	         SCIPdebugMsg(scip, "Propagating SOS1 constraint <%s>.\n", SCIPconsGetName(cons) );
9654 	
9655 	         SCIP_CALL( propConsSOS1(scip, cons, consdata, &cutoff, &ngen) );
9656 	         if ( cutoff )
9657 	         {
9658 	            *result = SCIP_CUTOFF;
9659 	            return SCIP_OKAY;
9660 	         }
9661 	      }
9662 	   }
9663 	
9664 	   SCIPdebugMsg(scip, "Propagated %d domains.\n", ngen);
9665 	   if ( ngen > 0 )
9666 	      *result = SCIP_REDUCEDDOM;
9667 	
9668 	   return SCIP_OKAY;
9669 	}
9670 	
9671 	
9672 	/** propagation conflict resolving method of constraint handler
9673 	 *
9674 	 *  We check which bound changes were the reason for infeasibility. We
9675 	 *  use that @a inferinfo stores the index of the variable that has
9676 	 *  bounds that fix it to be nonzero (these bounds are the reason). */
9677 	static
9678 	SCIP_DECL_CONSRESPROP(consRespropSOS1)
9679 	{  /*lint --e{715}*/
9680 	   SCIP_VAR* var;
9681 	
9682 	   assert( scip != NULL );
9683 	   assert( cons != NULL );
9684 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9685 	   assert( infervar != NULL );
9686 	   assert( bdchgidx != NULL );
9687 	   assert( result != NULL );
9688 	
9689 	   *result = SCIP_DIDNOTFIND;
9690 	   SCIPdebugMsg(scip, "Propagation resolution method of SOS1 constraint <%s>.\n", SCIPconsGetName(cons));
9691 	
9692 	   /* check whether conflict was detected in variable propagation or constraint propagation */
9693 	   if ( inferinfo < 0 )
9694 	   {
9695 	      SCIP_CONSHDLRDATA* conshdlrdata;
9696 	
9697 	      assert( conshdlr != NULL );
9698 	
9699 	      /* get constraint handler data */
9700 	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
9701 	      assert( conshdlrdata != NULL );
9702 	      assert( conshdlrdata->conflictgraph != NULL );
9703 	      assert( inferinfo >= -conshdlrdata->maxnfixnonzerovars );
9704 	      assert( inferinfo >= -conshdlrdata->nsos1vars );
9705 	      assert( inferinfo <= -1 );
9706 	
9707 	      var = SCIPnodeGetVarSOS1(conshdlrdata->conflictgraph, -inferinfo - 1);  /*lint !e2704*/
9708 	   }
9709 	   else
9710 	   {
9711 	      SCIP_CONSDATA* consdata;
9712 	
9713 	      /* get constraint data */
9714 	      consdata = SCIPconsGetData(cons);
9715 	      assert( consdata != NULL );
9716 	      assert( inferinfo < consdata->nvars );
9717 	
9718 	      var = consdata->vars[inferinfo];
9719 	   }
9720 	   assert( var != NULL );
9721 	   assert( var != infervar );
9722 	
9723 	   /* check if lower bound of var was the reason */
9724 	   if ( SCIPisFeasPositive(scip, SCIPgetVarLbAtIndex(scip, var, bdchgidx, FALSE)) )
9725 	   {
9726 	      SCIP_CALL( SCIPaddConflictLb(scip, var, bdchgidx) );
9727 	      *result = SCIP_SUCCESS;
9728 	   }
9729 	
9730 	   /* check if upper bound of var was the reason */
9731 	   if ( SCIPisFeasNegative(scip, SCIPgetVarUbAtIndex(scip, var, bdchgidx, FALSE)) )
9732 	   {
9733 	      SCIP_CALL( SCIPaddConflictUb(scip, var, bdchgidx) );
9734 	      *result = SCIP_SUCCESS;
9735 	   }
9736 	
9737 	   return SCIP_OKAY;
9738 	}
9739 	
9740 	
9741 	/** variable rounding lock method of constraint handler
9742 	 *
9743 	 *  Let lb and ub be the lower and upper bounds of a
9744 	 *  variable. Preprocessing usually makes sure that lb <= 0 <= ub.
9745 	 *
9746 	 *  - If lb < 0 then rounding down may violate the constraint.
9747 	 *  - If ub > 0 then rounding up may violated the constraint.
9748 	 *  - If lb > 0 or ub < 0 then the constraint is infeasible and we do
9749 	 *    not have to deal with it here.
9750 	 *  - If lb == 0 then rounding down does not violate the constraint.
9751 	 *  - If ub == 0 then rounding up does not violate the constraint.
9752 	 */
9753 	static
9754 	SCIP_DECL_CONSLOCK(consLockSOS1)
9755 	{
9756 	   SCIP_CONSDATA* consdata;
9757 	   SCIP_VAR** vars;
9758 	   int nvars;
9759 	   int j;
9760 	
9761 	   assert( scip != NULL );
9762 	   assert( conshdlr != NULL );
9763 	   assert( cons != NULL );
9764 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9765 	   assert(locktype == SCIP_LOCKTYPE_MODEL);
9766 	
9767 	   consdata = SCIPconsGetData(cons);
9768 	   assert( consdata != NULL );
9769 	
9770 	   SCIPdebugMsg(scip, "Locking constraint <%s>.\n", SCIPconsGetName(cons));
9771 	
9772 	   vars = consdata->vars;
9773 	   nvars = consdata->nvars;
9774 	   assert( vars != NULL );
9775 	
9776 	   for (j = 0; j < nvars; ++j)
9777 	   {
9778 	      SCIP_VAR* var;
9779 	      var = vars[j];
9780 	
9781 	      /* if lower bound is negative, rounding down may violate constraint */
9782 	      if ( SCIPisFeasNegative(scip, SCIPvarGetLbGlobal(var)) )
9783 	      {
9784 	         SCIP_CALL( SCIPaddVarLocksType(scip, var, locktype, nlockspos, nlocksneg) );
9785 	      }
9786 	
9787 	      /* additionally: if upper bound is positive, rounding up may violate constraint */
9788 	      if ( SCIPisFeasPositive(scip, SCIPvarGetUbGlobal(var)) )
9789 	      {
9790 	         SCIP_CALL( SCIPaddVarLocksType(scip, var, locktype, nlocksneg, nlockspos) );
9791 	      }
9792 	   }
9793 	
9794 	   return SCIP_OKAY;
9795 	}
9796 	
9797 	
9798 	/** constraint display method of constraint handler */
9799 	static
9800 	SCIP_DECL_CONSPRINT(consPrintSOS1)
9801 	{  /*lint --e{715}*/
9802 	   SCIP_CONSDATA* consdata;
9803 	   int j;
9804 	
9805 	   assert( scip != NULL );
9806 	   assert( conshdlr != NULL );
9807 	   assert( cons != NULL );
9808 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9809 	
9810 	   consdata = SCIPconsGetData(cons);
9811 	   assert( consdata != NULL );
9812 	
9813 	   for (j = 0; j < consdata->nvars; ++j)
9814 	   {
9815 	      if ( j > 0 )
9816 	         SCIPinfoMessage(scip, file, ", ");
9817 	      SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[j], FALSE) );
9818 	      if ( consdata->weights == NULL )
9819 	         SCIPinfoMessage(scip, file, " (%d)", j+1);
9820 	      else
9821 	         SCIPinfoMessage(scip, file, " (%3.2f)", consdata->weights[j]);
9822 	   }
9823 	
9824 	   return SCIP_OKAY;
9825 	}
9826 	
9827 	
9828 	/** constraint copying method of constraint handler */
9829 	static
9830 	SCIP_DECL_CONSCOPY(consCopySOS1)
9831 	{  /*lint --e{715}*/
9832 	   SCIP_CONSDATA* sourceconsdata;
9833 	   SCIP_VAR** sourcevars;
9834 	   SCIP_VAR** targetvars;
9835 	   SCIP_Real* targetweights = NULL;
9836 	   const char* consname;
9837 	   int nvars;
9838 	   int v;
9839 	
9840 	   assert( scip != NULL );
9841 	   assert( sourcescip != NULL );
9842 	   assert( sourcecons != NULL );
9843 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(sourcecons)), CONSHDLR_NAME) == 0 );
9844 	   assert( valid != NULL );
9845 	
9846 	   *valid = TRUE;
9847 	
9848 	   if ( name != NULL )
9849 	      consname = name;
9850 	   else
9851 	      consname = SCIPconsGetName(sourcecons);
9852 	
9853 	   SCIPdebugMsg(scip, "Copying SOS1 constraint <%s> ...\n", consname);
9854 	
9855 	   sourceconsdata = SCIPconsGetData(sourcecons);
9856 	   assert( sourceconsdata != NULL );
9857 	
9858 	   /* get variables and weights of the source constraint */
9859 	   nvars = sourceconsdata->nvars;
9860 	   assert( nvars >= 0 );
9861 	
9862 	   /* duplicate weights array */
9863 	   if ( sourceconsdata->weights != NULL )
9864 	   {
9865 	      SCIP_CALL( SCIPduplicateBufferArray(sourcescip, &targetweights, sourceconsdata->weights, nvars) );
9866 	   }
9867 	
9868 	   /* get copied variables in target SCIP */
9869 	   sourcevars = sourceconsdata->vars;
9870 	   SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetvars, nvars) );
9871 	   for (v = 0; v < nvars && *valid; ++v)
9872 	   {
9873 	      assert( sourcevars != NULL );
9874 	      SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &(targetvars[v]), varmap, consmap, global, valid) );
9875 	   }
9876 	
9877 	   /* only create the target constraint, if all variables were be copied */
9878 	   if ( *valid )
9879 	   {
9880 	      SCIP_CALL( SCIPcreateConsSOS1(scip, cons, consname, nvars, targetvars, targetweights,
9881 	            initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
9882 	   }
9883 	
9884 	   /* free buffer array */
9885 	   SCIPfreeBufferArray(sourcescip, &targetvars);
9886 	   SCIPfreeBufferArrayNull(sourcescip, &targetweights);
9887 	
9888 	   return SCIP_OKAY;
9889 	}
9890 	
9891 	
9892 	/** constraint parsing method of constraint handler */
9893 	static
9894 	SCIP_DECL_CONSPARSE(consParseSOS1)
9895 	{  /*lint --e{715}*/
9896 	   SCIP_VAR* var;
9897 	   SCIP_Real weight;
9898 	   const char* s;
9899 	   char* t;
9900 	
9901 	   assert(scip != NULL);
9902 	   assert(conshdlr != NULL);
9903 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
9904 	   assert(cons != NULL);
9905 	   assert(success != NULL);
9906 	
9907 	   *success = TRUE;
9908 	   s = str;
9909 	
9910 	   /* create empty SOS1 constraint */
9911 	   SCIP_CALL( SCIPcreateConsSOS1(scip, cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
9912 	
9913 	   /* loop through string */
9914 	   while( *s != '\0' )
9915 	   {
9916 	      /* parse variable name */
9917 	      SCIP_CALL( SCIPparseVarName(scip, s, &var, &t) );
9918 	
9919 	      if( var == NULL )
9920 	         break;
9921 	
9922 	      /* skip until beginning of weight */
9923 	      t = strchr(t, '(');
9924 	
9925 	      if( t == NULL )
9926 	      {
9927 	         SCIPerrorMessage("Syntax error: expected opening '(' at input: %s\n", s);
9928 	         *success = FALSE;
9929 	         break;
9930 	      }
9931 	
9932 	      s = t;
9933 	
9934 	      /* skip '(' */
9935 	      ++s;
9936 	
9937 	      /* find weight */
9938 	      weight = strtod(s, &t);
9939 	
9940 	      if( t == NULL )
9941 	      {
9942 	         SCIPerrorMessage("Syntax error during parsing of the weight: %s\n", s);
9943 	         *success = FALSE;
9944 	         break;
9945 	      }
9946 	
9947 	      s = t;
9948 	
9949 	      /* skip until ending of weight */
9950 	      t = strchr(t, ')');
9951 	
9952 	      if( t == NULL )
9953 	      {
9954 	         SCIPerrorMessage("Syntax error: expected closing ')' at input %s\n", s);
9955 	         *success = FALSE;
9956 	         break;
9957 	      }
9958 	
9959 	      s = t;
9960 	
9961 	      /* skip ')' */
9962 	      ++s;
9963 	
9964 	      /* skip white space */
9965 	      SCIP_CALL( SCIPskipSpace((char**)&s) );
9966 	
9967 	      /* skip ',' */
9968 	      if( *s == ',' )
9969 	         ++s;
9970 	
9971 	      /* add variable */
9972 	      SCIP_CALL( SCIPaddVarSOS1(scip, *cons, var, weight) );
9973 	   }
9974 	
9975 	   if( !*success )
9976 	      SCIP_CALL( SCIPreleaseCons(scip, cons) );
9977 	
9978 	   return SCIP_OKAY;
9979 	}
9980 	
9981 	
9982 	/** constraint method of constraint handler which returns the variables (if possible) */
9983 	static
9984 	SCIP_DECL_CONSGETVARS(consGetVarsSOS1)
9985 	{  /*lint --e{715}*/
9986 	   SCIP_CONSDATA* consdata;
9987 	
9988 	   consdata = SCIPconsGetData(cons);
9989 	   assert(consdata != NULL);
9990 	
9991 	   if( varssize < consdata->nvars )
9992 	      (*success) = FALSE;
9993 	   else
9994 	   {
9995 	      assert(vars != NULL);
9996 	
9997 	      BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
9998 	      (*success) = TRUE;
9999 	   }
10000	
10001	   return SCIP_OKAY;
10002	}
10003	
10004	
10005	/** constraint method of constraint handler which returns the number of variables (if possible) */
10006	static
10007	SCIP_DECL_CONSGETNVARS(consGetNVarsSOS1)
10008	{  /*lint --e{715}*/
10009	   SCIP_CONSDATA* consdata;
10010	
10011	   consdata = SCIPconsGetData(cons);
10012	   assert(consdata != NULL);
10013	
10014	   (*nvars) = consdata->nvars;
10015	   (*success) = TRUE;
10016	
10017	   return SCIP_OKAY;
10018	}
10019	
10020	
10021	/* ---------------- Callback methods of event handler ---------------- */
10022	
10023	/** exec the event handler
10024	 *
10025	 *  We update the number of variables fixed to be nonzero
10026	 */
10027	static
10028	SCIP_DECL_EVENTEXEC(eventExecSOS1)
10029	{
10030	   SCIP_CONSHDLRDATA* conshdlrdata;
10031	   SCIP_EVENTTYPE eventtype;
10032	   SCIP_CONSHDLR* conshdlr;
10033	   SCIP_CONSDATA* consdata;
10034	   SCIP_CONS* cons;
10035	   SCIP_VAR* var;
10036	   SCIP_Real oldbound;
10037	   SCIP_Real newbound;
10038	
10039	   assert( eventhdlr != NULL );
10040	   assert( eventdata != NULL );
10041	   assert( strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0 );
10042	   assert( event != NULL );
10043	
10044	   cons = (SCIP_CONS*)eventdata;
10045	   assert( cons != NULL );
10046	   consdata = SCIPconsGetData(cons);
10047	   assert( 0 <= consdata->nfixednonzeros && consdata->nfixednonzeros <= consdata->nvars );
10048	
10049	   oldbound = SCIPeventGetOldbound(event);
10050	   newbound = SCIPeventGetNewbound(event);
10051	
10052	   eventtype = SCIPeventGetType(event);
10053	   switch ( eventtype )
10054	   {
10055	   case SCIP_EVENTTYPE_LBTIGHTENED:
10056	      /* if variable is now fixed to be nonzero */
10057	      if ( ! SCIPisFeasPositive(scip, oldbound) && SCIPisFeasPositive(scip, newbound) )
10058	      {
10059	         conshdlr = SCIPconsGetHdlr(cons);
10060	         assert( conshdlr != NULL );
10061	         conshdlrdata = SCIPconshdlrGetData(conshdlr);
10062	         assert( conshdlrdata != NULL );
10063	
10064	         /* store variable fixed to be nonzero on stack */
10065	         assert( 0 <= conshdlrdata->nfixnonzerovars && conshdlrdata->nfixnonzerovars <= SCIPgetNTotalVars(scip) );
10066	         if ( conshdlrdata->nfixnonzerovars < conshdlrdata->maxnfixnonzerovars )
10067	         {
10068	            assert( conshdlrdata->fixnonzerovars != NULL );
10069	            assert( SCIPeventGetVar(event) != NULL );
10070	            conshdlrdata->fixnonzerovars[conshdlrdata->nfixnonzerovars++] = SCIPeventGetVar(event);
10071	         }
10072	
10073	         ++(consdata->nfixednonzeros);
10074	      }
10075	      break;
10076	
10077	   case SCIP_EVENTTYPE_UBTIGHTENED:
10078	      /* if variable is now fixed to be nonzero */
10079	      if ( ! SCIPisFeasNegative(scip, oldbound) && SCIPisFeasNegative(scip, newbound) )
10080	      {
10081	         conshdlr = SCIPconsGetHdlr(cons);
10082	         assert( conshdlr != NULL );
10083	         conshdlrdata = SCIPconshdlrGetData(conshdlr);
10084	         assert( conshdlrdata != NULL );
10085	
10086	         /* store variable fixed to be nonzero on stack */
10087	         assert( 0 <= conshdlrdata->nfixnonzerovars && conshdlrdata->nfixnonzerovars <= SCIPgetNTotalVars(scip) );
10088	         if ( conshdlrdata->nfixnonzerovars < conshdlrdata->maxnfixnonzerovars )
10089	         {
10090	            assert( conshdlrdata->fixnonzerovars != NULL );
10091	            assert( SCIPeventGetVar(event) != NULL );
10092	            conshdlrdata->fixnonzerovars[conshdlrdata->nfixnonzerovars++] = SCIPeventGetVar(event);
10093	         }
10094	
10095	         ++(consdata->nfixednonzeros);
10096	      }
10097	      break;
10098	
10099	   case SCIP_EVENTTYPE_LBRELAXED:
10100	      /* if variable is not fixed to be nonzero anymore */
10101	      if ( SCIPisFeasPositive(scip, oldbound) && ! SCIPisFeasPositive(scip, newbound) )
10102	         --(consdata->nfixednonzeros);
10103	      break;
10104	
10105	   case SCIP_EVENTTYPE_UBRELAXED:
10106	      /* if variable is not fixed to be nonzero anymore */
10107	      if ( SCIPisFeasNegative(scip, oldbound) && ! SCIPisFeasNegative(scip, newbound) )
10108	         --(consdata->nfixednonzeros);
10109	      break;
10110	
10111	   case SCIP_EVENTTYPE_GLBCHANGED:
10112	      var = SCIPeventGetVar(event);
10113	      assert(var != NULL);
10114	
10115	      /* global lower bound is not negative anymore -> remove down lock */
10116	      if ( SCIPisFeasNegative(scip, oldbound) && ! SCIPisFeasNegative(scip, newbound) )
10117	         SCIP_CALL( SCIPunlockVarCons(scip, var, cons, TRUE, FALSE) );
10118	      /* global lower bound turned negative -> add down lock */
10119	      else if ( ! SCIPisFeasNegative(scip, oldbound) && SCIPisFeasNegative(scip, newbound) )
10120	         SCIP_CALL( SCIPlockVarCons(scip, var, cons, TRUE, FALSE) );
10121	      break;
10122	
10123	   case SCIP_EVENTTYPE_GUBCHANGED:
10124	      var = SCIPeventGetVar(event);
10125	      assert(var != NULL);
10126	
10127	      /* global upper bound is not positive anymore -> remove up lock */
10128	      if ( SCIPisFeasPositive(scip, oldbound) && ! SCIPisFeasPositive(scip, newbound) )
10129	         SCIP_CALL( SCIPunlockVarCons(scip, var, cons, FALSE, TRUE) );
10130	      /* global upper bound turned positive -> add up lock */
10131	      else if ( ! SCIPisFeasPositive(scip, oldbound) && SCIPisFeasPositive(scip, newbound) )
10132	         SCIP_CALL( SCIPlockVarCons(scip, var, cons, FALSE, TRUE) );
10133	      break;
10134	
10135	   default:
10136	      SCIPerrorMessage("invalid event type.\n");
10137	      return SCIP_INVALIDDATA;
10138	   }
10139	   assert( 0 <= consdata->nfixednonzeros && consdata->nfixednonzeros <= consdata->nvars );
10140	
10141	   SCIPdebugMsg(scip, "changed bound of variable <%s> from %f to %f (nfixednonzeros: %d).\n", SCIPvarGetName(SCIPeventGetVar(event)),
10142	                    oldbound, newbound, consdata->nfixednonzeros);
10143	
10144	   return SCIP_OKAY;
10145	}
10146	
10147	
10148	/** constraint handler method to determine a diving variable by assigning a variable and two values for diving */
10149	static
10150	SCIP_DECL_CONSGETDIVEBDCHGS(consGetDiveBdChgsSOS1)
10151	{
10152	   SCIP_CONSHDLRDATA* conshdlrdata;
10153	
10154	   assert( scip != NULL );
10155	   assert( conshdlr != NULL );
10156	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
10157	   assert( diveset != NULL );
10158	   assert( success != NULL );
10159	   assert( infeasible != NULL );
10160	
10161	   *infeasible = FALSE;
10162	   *success = FALSE;
10163	
10164	   if ( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
10165	   {
10166	      SCIPerrorMessage("not an SOS1 constraint handler.\n");
10167	      return SCIP_INVALIDDATA;
10168	   }
10169	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
10170	   assert( conshdlrdata != NULL );
10171	
10172	   /* if the SOS1 constraints do not overlap, we apply a faster method getDiveBdChgsSOS1constraints() that does not make use of the conflict graph;
10173	    * for overlapping SOS1 constraints we apply the method getDiveBdChgsSOS1conflictgraph(), which then may produce better results (e.g. due to more
10174	    * diving candidates) */
10175	   if ( conshdlrdata->switchsos1branch )
10176	   {
10177	      SCIP_CALL( getDiveBdChgsSOS1constraints(scip, conshdlr, diveset, sol, success) );
10178	   }
10179	   else
10180	   {
10181	      SCIP_CALL( getDiveBdChgsSOS1conflictgraph(scip, conshdlr, diveset, sol, success) );
10182	   }
10183	
10184	   return SCIP_OKAY;
10185	}
10186	
10187	
10188	/** constraint handler method which returns the permutation symmetry detection graph of a constraint */
10189	static
10190	SCIP_DECL_CONSGETPERMSYMGRAPH(consGetPermsymGraphSOS1)
10191	{  /*lint --e{715}*/
10192	   SCIP_CONSDATA* consdata;
10193	   SCIP_VAR** consvars;
10194	   SCIP_VAR** locvars;
10195	   SCIP_Real* locvals;
10196	   SCIP_Real constant = 0.0;
10197	   int consnodeidx;
10198	   int nodeidx;
10199	   int nconsvars;
10200	   int nlocvars;
10201	   int nvars;
10202	   int i;
10203	
10204	   consdata = SCIPconsGetData(cons);
10205	   assert(consdata != NULL);
10206	
10207	   /* get active variables of the constraint */
10208	   nvars = SCIPgetNVars(scip);
10209	   nconsvars = consdata->nvars;
10210	   consvars = SCIPgetVarsSOS1(scip, cons);
10211	   assert(consvars != NULL);
10212	
10213	   SCIP_CALL( SCIPallocBufferArray(scip, &locvars, nvars) );
10214	   SCIP_CALL( SCIPallocBufferArray(scip, &locvals, nvars) );
10215	
10216	   /* add node initializing constraint (with artificial rhs) */
10217	   SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
10218	
10219	   /* for all (aggregations of) variables, add a node to graph and connect it with the root */
10220	   for( i = 0; i < nconsvars; ++i )
10221	   {
10222	      locvars[0] = consvars[i];
10223	      locvals[0] = 1.0;
10224	      constant = 0.0;
10225	      nlocvars = 1;
10226	
10227	      /* ignore weights of SOS1 constraint (variables are sorted according to these weights) */
10228	      SCIP_CALL( SCIPgetActiveVariables(scip, SYM_SYMTYPE_PERM, &locvars, &locvals,
10229	            &nlocvars, &constant, SCIPisTransformed(scip)) );
10230	
10231	      if( nlocvars == 1 && SCIPisZero(scip, constant) && SCIPisEQ(scip, locvals[0], 1.0) )
10232	      {
10233	         nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, locvars[0]);
10234	         SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, nodeidx, FALSE, 0.0) );
10235	      }
10236	      else
10237	      {
10238	         SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &nodeidx) ); /*lint !e641*/
10239	         SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, nodeidx, FALSE, 0.0) );
10240	         SCIP_CALL( SCIPaddSymgraphVarAggegration(scip, graph, nodeidx, locvars, locvals, nlocvars, constant) );
10241	      }
10242	   }
10243	
10244	   SCIPfreeBufferArray(scip, &locvals);
10245	   SCIPfreeBufferArray(scip, &locvars);
10246	
10247	   return SCIP_OKAY;
10248	}
10249	
10250	
10251	/** constraint handler method which returns the signed permutation symmetry detection graph of a constraint */
10252	static
10253	SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH(consGetSignedPermsymGraphSOS1)
10254	{  /*lint --e{715}*/
10255	   SCIP_CONSDATA* consdata;
10256	   SCIP_VAR** consvars;
10257	   SCIP_VAR** locvars;
10258	   SCIP_Real* locvals;
10259	   SCIP_Real constant = 0.0;
10260	   int consnodeidx;
10261	   int nodeidx;
10262	   int nconsvars;
10263	   int nlocvars;
10264	   int nvars;
10265	   int i;
10266	
10267	   consdata = SCIPconsGetData(cons);
10268	   assert(consdata != NULL);
10269	
10270	   /* get active variables of the constraint */
10271	   nvars = SCIPgetNVars(scip);
10272	   nconsvars = consdata->nvars;
10273	   consvars = SCIPgetVarsSOS1(scip, cons);
10274	   assert(consvars != NULL);
10275	
10276	   SCIP_CALL( SCIPallocBufferArray(scip, &locvars, nvars) );
10277	   SCIP_CALL( SCIPallocBufferArray(scip, &locvals, nvars) );
10278	
10279	   /* add node initializing constraint (with artificial rhs) */
10280	   SCIP_CALL( SCIPaddSymgraphConsnode(scip, graph, cons, 0.0, 0.0, &consnodeidx) );
10281	
10282	   /* for all (aggregation of) variables, add a node to graph and connect it with the root */
10283	   for( i = 0; i < nconsvars; ++i )
10284	   {
10285	      locvars[0] = consvars[i];
10286	      locvals[0] = 1.0;
10287	      constant = 0.0;
10288	      nlocvars = 1;
10289	
10290	      /* ignore weights of SOS1 constraint (variables are sorted according to these weights) */
10291	
10292	      /* use SYM_SYMTYPE_PERM here to NOT center variable domains at 0, as the latter might not preserve
10293	       * SOS1 constraints */
10294	      SCIP_CALL( SCIPgetActiveVariables(scip, SYM_SYMTYPE_PERM, &locvars, &locvals,
10295	            &nlocvars, &constant, SCIPisTransformed(scip)) );
10296	
10297	      if( nlocvars == 1 && SCIPisZero(scip, constant) && SCIPisEQ(scip, locvals[0], 1.0) )
10298	      {
10299	         SCIP_Bool allownegation = FALSE;
10300	
10301	         /* a negation is allowed if it is centered around 0 */
10302	         if ( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(locvars[0])) == SCIPisInfinity(scip, SCIPvarGetUbGlobal(locvars[0]))
10303	            && (SCIPisInfinity(scip, SCIPvarGetUbGlobal(locvars[0]))
10304	               || SCIPisZero(scip, (SCIPvarGetLbGlobal(locvars[0]) + SCIPvarGetUbGlobal(locvars[0]))/2)) )
10305	            allownegation = TRUE;
10306	
10307	         nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, locvars[0]);
10308	         SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, nodeidx, TRUE, 1.0) );
10309	
10310	         nodeidx = SCIPgetSymgraphNegatedVarnodeidx(scip, graph, locvars[0]);
10311	         if( allownegation )
10312	         {
10313	            SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, nodeidx, TRUE, 1.0) );
10314	         }
10315	         else
10316	         {
10317	            SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, nodeidx, TRUE, -1.0) );
10318	         }
10319	      }
10320	      else
10321	      {
10322	         int sumnodeidx;
10323	         int j;
10324	
10325	         SCIP_CALL( SCIPaddSymgraphOpnode(scip, graph, (int) SYM_CONSOPTYPE_SUM, &sumnodeidx) ); /*lint !e641*/
10326	         SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, consnodeidx, sumnodeidx, FALSE, 0.0) );
10327	
10328	         /* add nodes and edges for variables in aggregation, do not add edges to negated variables
10329	          * since this might not necessarily be a symmetry of the SOS1 constraint; therefore,
10330	          * do not use SCIPaddSymgraphVarAggegration() */
10331	         for( j = 0; j < nlocvars; ++j )
10332	         {
10333	            nodeidx = SCIPgetSymgraphVarnodeidx(scip, graph, locvars[j]);
10334	            SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, sumnodeidx, nodeidx, TRUE, locvals[j]) );
10335	         }
10336	
10337	         /* possibly add node for constant */
10338	         if( ! SCIPisZero(scip, constant) )
10339	         {
10340	            SCIP_CALL( SCIPaddSymgraphValnode(scip, graph, constant, &nodeidx) );
10341	            SCIP_CALL( SCIPaddSymgraphEdge(scip, graph, sumnodeidx, nodeidx, FALSE, 0.0) );
10342	         }
10343	      }
10344	   }
10345	
10346	   SCIPfreeBufferArray(scip, &locvals);
10347	   SCIPfreeBufferArray(scip, &locvars);
10348	
10349	   return SCIP_OKAY;
10350	}
10351	
10352	
10353	/* ---------------- Constraint specific interface methods ---------------- */
10354	
10355	/** creates the handler for SOS1 constraints and includes it in SCIP */
10356	SCIP_RETCODE SCIPincludeConshdlrSOS1(
10357	   SCIP*                 scip                /**< SCIP data structure */
10358	   )
10359	{
10360	   SCIP_CONSHDLRDATA* conshdlrdata;
10361	   SCIP_CONSHDLR* conshdlr;
10362	
10363	   /* create constraint handler data */
10364	   SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
10365	   conshdlrdata->branchsos = TRUE;
10366	   conshdlrdata->switchsos1branch = FALSE;
10367	   conshdlrdata->switchcutsfromsos1 = FALSE;
10368	   conshdlrdata->eventhdlr = NULL;
10369	   conshdlrdata->fixnonzerovars = NULL;
10370	   conshdlrdata->maxnfixnonzerovars = 0;
10371	   conshdlrdata->nfixnonzerovars = 0;
10372	   conshdlrdata->conflictgraph = NULL;
10373	   conshdlrdata->localconflicts = NULL;
10374	   conshdlrdata->isconflocal = FALSE;
10375	   conshdlrdata->implgraph = NULL;
10376	   conshdlrdata->nimplnodes = 0;
10377	   conshdlrdata->nboundcuts = 0;
10378	   conshdlrdata->tcliquegraph = NULL;
10379	   conshdlrdata->tcliquedata = NULL;
10380	   conshdlrdata->cntextsos1 = -1;
10381	   conshdlrdata->varhash = NULL;
10382	
10383	   /* create event handler for bound change events */
10384	   SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &conshdlrdata->eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecSOS1, NULL) );
10385	   if ( conshdlrdata->eventhdlr == NULL )
10386	   {
10387	      SCIPerrorMessage("event handler for SOS1 constraints not found.\n");
10388	      return SCIP_PLUGINNOTFOUND;
10389	   }
10390	
10391	   /* include constraint handler */
10392	   SCIP_CALL( SCIPincludeConshdlrBasic(scip, &conshdlr, CONSHDLR_NAME, CONSHDLR_DESC,
10393	         CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY, CONSHDLR_EAGERFREQ, CONSHDLR_NEEDSCONS,
10394	         consEnfolpSOS1, consEnfopsSOS1, consCheckSOS1, consLockSOS1, conshdlrdata) );
10395	   assert(conshdlr != NULL);
10396	
10397	   /* set non-fundamental callbacks via specific setter functions */
10398	   SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopySOS1, consCopySOS1) );
10399	   SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteSOS1) );
10400	   SCIP_CALL( SCIPsetConshdlrGetDiveBdChgs(scip, conshdlr, consGetDiveBdChgsSOS1) );
10401	   SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolSOS1) );
10402	   SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolSOS1) );
10403	   SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeSOS1) );
10404	   SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsSOS1) );
10405	   SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsSOS1) );
10406	   SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpSOS1) );
10407	   SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseSOS1) );
10408	   SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolSOS1, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
10409	   SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintSOS1) );
10410	   SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropSOS1, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP, CONSHDLR_PROP_TIMING) );
10411	   SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropSOS1) );
10412	   SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpSOS1, consSepasolSOS1, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
10413	   SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransSOS1) );
10414	   SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxSOS1) );
10415	   SCIP_CALL( SCIPsetConshdlrGetPermsymGraph(scip, conshdlr, consGetPermsymGraphSOS1) );
10416	   SCIP_CALL( SCIPsetConshdlrGetSignedPermsymGraph(scip, conshdlr, consGetSignedPermsymGraphSOS1) );
10417	
10418	   /* add SOS1 constraint handler parameters */
10419	
10420	   /* adjacency matrix parameters */
10421	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/maxsosadjacency",
10422	         "do not create an adjacency matrix if number of SOS1 variables is larger than predefined value (-1: no limit)",
10423	         &conshdlrdata->maxsosadjacency, TRUE, DEFAULT_MAXSOSADJACENCY, -1, INT_MAX, NULL, NULL) );
10424	
10425	   /* presolving parameters */
10426	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/maxextensions",
10427	         "maximal number of extensions that will be computed for each SOS1 constraint  (-1: no limit)",
10428	         &conshdlrdata->maxextensions, TRUE, DEFAULT_MAXEXTENSIONS, -1, INT_MAX, NULL, NULL) );
10429	
10430	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/maxtightenbds",
10431	         "maximal number of bound tightening rounds per presolving round (-1: no limit)",
10432	         &conshdlrdata->maxtightenbds, TRUE, DEFAULT_MAXTIGHTENBDS, -1, INT_MAX, NULL, NULL) );
10433	
10434	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/perfimplanalysis",
10435	         "if TRUE then perform implication graph analysis (might add additional SOS1 constraints)",
10436	         &conshdlrdata->perfimplanalysis, TRUE, DEFAULT_PERFIMPLANALYSIS, NULL, NULL) );
10437	
10438	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/depthimplanalysis",
10439	         "number of recursive calls of implication graph analysis (-1: no limit)",
10440	         &conshdlrdata->depthimplanalysis, TRUE, DEFAULT_DEPTHIMPLANALYSIS, -1, INT_MAX, NULL, NULL) );
10441	
10442	   /* propagation parameters */
10443	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/conflictprop",
10444	         "whether to use conflict graph propagation",
10445	         &conshdlrdata->conflictprop, TRUE, DEFAULT_CONFLICTPROP, NULL, NULL) );
10446	
10447	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/implprop",
10448	         "whether to use implication graph propagation",
10449	         &conshdlrdata->implprop, TRUE, DEFAULT_IMPLPROP, NULL, NULL) );
10450	
10451	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/sosconsprop",
10452	         "whether to use SOS1 constraint propagation",
10453	         &conshdlrdata->sosconsprop, TRUE, DEFAULT_SOSCONSPROP, NULL, NULL) );
10454	
10455	   /* branching parameters */
10456	   SCIP_CALL( SCIPaddCharParam(scip, "constraints/" CONSHDLR_NAME "/branchingrule",
10457	         "which branching rule should be applied ? ('n': neighborhood, 'b': bipartite, 's': SOS1/clique) (note: in some cases an automatic switching to SOS1 branching is possible)",
10458	         &conshdlrdata->branchingrule, TRUE, DEFAULT_BRANCHINGRULE, DEFAULT_BRANCHSTRATEGIES, NULL, NULL) );
10459	
10460	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/autosos1branch",
10461	         "if TRUE then automatically switch to SOS1 branching if the SOS1 constraints do not overlap",
10462	         &conshdlrdata->autosos1branch, TRUE, DEFAULT_AUTOSOS1BRANCH, NULL, NULL) );
10463	
10464	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/fixnonzero",
10465	         "if neighborhood branching is used, then fix the branching variable (if positive in sign) to the value of the feasibility tolerance",
10466	         &conshdlrdata->fixnonzero, TRUE, DEFAULT_FIXNONZERO, NULL, NULL) );
10467	
10468	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/addcomps",
10469	         "if TRUE then add complementarity constraints to the branching nodes (can be used in combination with neighborhood or bipartite branching)",
10470	         &conshdlrdata->addcomps, TRUE, DEFAULT_ADDCOMPS, NULL, NULL) );
10471	
10472	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/maxaddcomps",
10473	         "maximal number of complementarity constraints added per branching node (-1: no limit)",
10474	         &conshdlrdata->maxaddcomps, TRUE, DEFAULT_MAXADDCOMPS, -1, INT_MAX, NULL, NULL) );
10475	
10476	   SCIP_CALL( SCIPaddRealParam(scip, "constraints/" CONSHDLR_NAME "/addcompsfeas",
10477	         "minimal feasibility value for complementarity constraints in order to be added to the branching node",
10478	         &conshdlrdata->addcompsfeas, TRUE, DEFAULT_ADDCOMPSFEAS, -SCIP_REAL_MAX, SCIP_REAL_MAX, NULL, NULL) );
10479	
10480	   SCIP_CALL( SCIPaddRealParam(scip, "constraints/" CONSHDLR_NAME "/addbdsfeas",
10481	         "minimal feasibility value for bound inequalities in order to be added to the branching node",
10482	         &conshdlrdata->addbdsfeas, TRUE, DEFAULT_ADDBDSFEAS, -SCIP_REAL_MAX, SCIP_REAL_MAX, NULL, NULL) );
10483	
10484	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/addextendedbds",
10485	         "should added complementarity constraints be extended to SOS1 constraints to get tighter bound inequalities",
10486	         &conshdlrdata->addextendedbds, TRUE, DEFAULT_ADDEXTENDEDBDS, NULL, NULL) );
10487	
10488	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/branchsos",
10489	         "Use SOS1 branching in enforcing (otherwise leave decision to branching rules)? This value can only be set to false if all SOS1 variables are binary",
10490	         &conshdlrdata->branchsos, FALSE, TRUE, NULL, NULL) );
10491	
10492	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/branchnonzeros",
10493	         "Branch on SOS constraint with most number of nonzeros?",
10494	         &conshdlrdata->branchnonzeros, FALSE, FALSE, NULL, NULL) );
10495	
10496	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/branchweight",
10497	         "Branch on SOS cons. with highest nonzero-variable weight for branching (needs branchnonzeros = false)?",
10498	         &conshdlrdata->branchweight, FALSE, FALSE, NULL, NULL) );
10499	
10500	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/addcompsdepth",
10501	         "only add complementarity constraints to branching nodes for predefined depth (-1: no limit)",
10502	         &conshdlrdata->addcompsdepth, TRUE, DEFAULT_ADDCOMPSDEPTH, -1, INT_MAX, NULL, NULL) );
10503	
10504	   /* selection rule parameters */
10505	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/nstrongrounds",
10506	         "maximal number of strong branching rounds to perform for each node (-1: auto); only available for neighborhood and bipartite branching",
10507	         &conshdlrdata->nstrongrounds, TRUE, DEFAULT_NSTRONGROUNDS, -1, INT_MAX, NULL, NULL) );
10508	
10509	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/nstrongiter",
10510	         "maximal number LP iterations to perform for each strong branching round (-2: auto, -1: no limit)",
10511	         &conshdlrdata->nstrongiter, TRUE, DEFAULT_NSTRONGITER, -2, INT_MAX, NULL, NULL) );
10512	
10513	   /* separation parameters */
10514	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/boundcutsfromsos1",
10515	         "if TRUE separate bound inequalities from initial SOS1 constraints",
10516	         &conshdlrdata->boundcutsfromsos1, TRUE, DEFAULT_BOUNDCUTSFROMSOS1, NULL, NULL) );
10517	
10518	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/boundcutsfromgraph",
10519	         "if TRUE separate bound inequalities from the conflict graph",
10520	         &conshdlrdata->boundcutsfromgraph, TRUE, DEFAULT_BOUNDCUTSFROMGRAPH, NULL, NULL) );
10521	
10522	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/autocutsfromsos1",
10523	         "if TRUE then automatically switch to separating initial SOS1 constraints if the SOS1 constraints do not overlap",
10524	         &conshdlrdata->autocutsfromsos1, TRUE, DEFAULT_AUTOCUTSFROMSOS1, NULL, NULL) );
10525	
10526	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/boundcutsfreq",
10527	         "frequency for separating bound cuts; zero means to separate only in the root node",
10528	         &conshdlrdata->boundcutsfreq, TRUE, DEFAULT_BOUNDCUTSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
10529	
10530	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/boundcutsdepth",
10531	         "node depth of separating bound cuts (-1: no limit)",
10532	         &conshdlrdata->boundcutsdepth, TRUE, DEFAULT_BOUNDCUTSDEPTH, -1, INT_MAX, NULL, NULL) );
10533	
10534	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/maxboundcuts",
10535	         "maximal number of bound cuts separated per branching node",
10536	         &conshdlrdata->maxboundcuts, TRUE, DEFAULT_MAXBOUNDCUTS, 0, INT_MAX, NULL, NULL) );
10537	
10538	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/maxboundcutsroot",
10539	         "maximal number of bound cuts separated per iteration in the root node",
10540	         &conshdlrdata->maxboundcutsroot, TRUE, DEFAULT_MAXBOUNDCUTSROOT, 0, INT_MAX, NULL, NULL) );
10541	
10542	   SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/strthenboundcuts",
10543	         "if TRUE then bound cuts are strengthened in case bound variables are available",
10544	         &conshdlrdata->strthenboundcuts, TRUE, DEFAULT_STRTHENBOUNDCUTS, NULL, NULL) );
10545	
10546	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/implcutsfreq",
10547	         "frequency for separating implied bound cuts; zero means to separate only in the root node",
10548	         &conshdlrdata->implcutsfreq, TRUE, DEFAULT_IMPLCUTSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
10549	
10550	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/implcutsdepth",
10551	         "node depth of separating implied bound cuts (-1: no limit)",
10552	         &conshdlrdata->implcutsdepth, TRUE, DEFAULT_IMPLCUTSDEPTH, -1, INT_MAX, NULL, NULL) );
10553	
10554	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/maximplcuts",
10555	         "maximal number of implied bound cuts separated per branching node",
10556	         &conshdlrdata->maximplcuts, TRUE, DEFAULT_MAXIMPLCUTS, 0, INT_MAX, NULL, NULL) );
10557	
10558	   SCIP_CALL( SCIPaddIntParam(scip, "constraints/" CONSHDLR_NAME "/maximplcutsroot",
10559	         "maximal number of implied bound cuts separated per iteration in the root node",
10560	         &conshdlrdata->maximplcutsroot, TRUE, DEFAULT_MAXIMPLCUTSROOT, 0, INT_MAX, NULL, NULL) );
10561	
10562	   return SCIP_OKAY;
10563	}
10564	
10565	
10566	/** creates and captures a SOS1 constraint
10567	 *
10568	 *  We set the constraint to not be modifable. If the weights are non NULL, the variables are ordered according to these
10569	 *  weights (in ascending order).
10570	 *
10571	 *  @note The constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons().
10572	 */
10573	SCIP_RETCODE SCIPcreateConsSOS1(
10574	   SCIP*                 scip,               /**< SCIP data structure */
10575	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
10576	   const char*           name,               /**< name of constraint */
10577	   int                   nvars,              /**< number of variables in the constraint */
10578	   SCIP_VAR**            vars,               /**< array with variables of constraint entries */
10579	   SCIP_Real*            weights,            /**< weights determining the variable order, or NULL if natural order should be used */
10580	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
10581	                                              *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
10582	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
10583	                                              *   Usually set to TRUE. */
10584	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
10585	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
10586	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
10587	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
10588	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
10589	                                              *   Usually set to TRUE. */
10590	   SCIP_Bool             local,              /**< is constraint only valid locally?
10591	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
10592	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
10593	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
10594	                                              *   are separated as constraints. */
10595	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
10596	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
10597	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
10598	                                              *   if it may be moved to a more global node?
10599	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
10600	   )
10601	{
10602	   SCIP_CONSHDLR* conshdlr;
10603	   SCIP_CONSDATA* consdata;
10604	   SCIP_Bool modifiable;
10605	   SCIP_Bool transformed;
10606	   int v;
10607	
10608	   modifiable = FALSE;
10609	
10610	   /* find the SOS1 constraint handler */
10611	   conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
10612	   if ( conshdlr == NULL )
10613	   {
10614	      SCIPerrorMessage("<%s> constraint handler not found\n", CONSHDLR_NAME);
10615	      return SCIP_PLUGINNOTFOUND;
10616	   }
10617	
10618	   /* are we in the transformed problem? */
10619	   transformed = SCIPgetStage(scip) >= SCIP_STAGE_TRANSFORMED;
10620	
10621	   /* create constraint data */
10622	   SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
10623	   consdata->vars = NULL;
10624	   consdata->nvars = nvars;
10625	   consdata->maxvars = nvars;
10626	   consdata->rowub = NULL;
10627	   consdata->rowlb = NULL;
10628	   consdata->nfixednonzeros = transformed ? 0 : -1;
10629	   consdata->weights = NULL;
10630	   consdata->local = local;
10631	
10632	   if ( nvars > 0 )
10633	   {
10634	      SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->vars, vars, nvars) );
10635	
10636	      /* check weights */
10637	      if ( weights != NULL )
10638	      {
10639	         /* store weights */
10640	         SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->weights, weights, nvars) );
10641	
10642	         /* sort variables - ascending order */
10643	         SCIPsortRealPtr(consdata->weights, (void**)consdata->vars, nvars);
10644	      }
10645	   }
10646	   else
10647	   {
10648	      assert( weights == NULL );
10649	   }
10650	
10651	   /* branching on multiaggregated variables does not seem to work well, so avoid it */
10652	   for (v = 0; v < nvars; ++v)
10653	   {
10654	      SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, consdata->vars[v]) );
10655	   }
10656	
10657	   /* create constraint */
10658	   SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
10659	         local, modifiable, dynamic, removable, stickingatnode) );
10660	   assert( transformed == SCIPconsIsTransformed(*cons) );
10661	
10662	   /* replace original variables by transformed variables in transformed constraint, add locks, and catch events */
10663	   for (v = nvars - 1; v >= 0; --v)
10664	   {
10665	      SCIP_CONSHDLRDATA* conshdlrdata;
10666	
10667	      /* always use transformed variables in transformed constraints */
10668	      if ( transformed )
10669	      {
10670	         SCIP_CALL( SCIPgetTransformedVar(scip, consdata->vars[v], &(consdata->vars[v])) );
10671	      }
10672	      assert( consdata->vars[v] != NULL );
10673	      assert( transformed == SCIPvarIsTransformed(consdata->vars[v]) );
10674	
10675	      /* get constraint handler data */
10676	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
10677	      assert( conshdlrdata != NULL );
10678	
10679	      /* handle the new variable */
10680	      SCIP_CALL( handleNewVariableSOS1(scip, *cons, consdata, conshdlrdata, consdata->vars[v], transformed) );
10681	   }
10682	
10683	   return SCIP_OKAY;
10684	}
10685	
10686	
10687	/** creates and captures a SOS1 constraint with all constraint flags set to their default values.
10688	 *
10689	 *  @warning Do NOT set the constraint to be modifiable manually, because this might lead
10690	 *  to wrong results as the variable array will not be resorted
10691	 *
10692	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
10693	 */
10694	SCIP_RETCODE SCIPcreateConsBasicSOS1(
10695	   SCIP*                 scip,               /**< SCIP data structure */
10696	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
10697	   const char*           name,               /**< name of constraint */
10698	   int                   nvars,              /**< number of variables in the constraint */
10699	   SCIP_VAR**            vars,               /**< array with variables of constraint entries */
10700	   SCIP_Real*            weights             /**< weights determining the variable order, or NULL if natural order should be used */
10701	   )
10702	{
10703	   SCIP_CALL( SCIPcreateConsSOS1( scip, cons, name, nvars, vars, weights, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
10704	
10705	   return SCIP_OKAY;
10706	}
10707	
10708	
10709	/** adds variable to SOS1 constraint, the position is determined by the given weight */
10710	SCIP_RETCODE SCIPaddVarSOS1(
10711	   SCIP*                 scip,               /**< SCIP data structure */
10712	   SCIP_CONS*            cons,               /**< constraint */
10713	   SCIP_VAR*             var,                /**< variable to add to the constraint */
10714	   SCIP_Real             weight              /**< weight determining position of variable */
10715	   )
10716	{
10717	   SCIP_CONSHDLRDATA* conshdlrdata;
10718	   SCIP_CONSHDLR* conshdlr;
10719	
10720	   assert( scip != NULL );
10721	   assert( var != NULL );
10722	   assert( cons != NULL );
10723	
10724	   SCIPdebugMsg(scip, "adding variable <%s> to constraint <%s> with weight %g\n", SCIPvarGetName(var), SCIPconsGetName(cons), weight);
10725	
10726	   conshdlr = SCIPconsGetHdlr(cons);
10727	   assert( conshdlr != NULL );
10728	   if ( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
10729	   {
10730	      SCIPerrorMessage("constraint is not an SOS1 constraint.\n");
10731	      return SCIP_INVALIDDATA;
10732	   }
10733	
10734	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
10735	   assert( conshdlrdata != NULL );
10736	
10737	   SCIP_CALL( addVarSOS1(scip, cons, conshdlrdata, var, weight) );
10738	
10739	   return SCIP_OKAY;
10740	}
10741	
10742	
10743	/** appends variable to SOS1 constraint */
10744	SCIP_RETCODE SCIPappendVarSOS1(
10745	   SCIP*                 scip,               /**< SCIP data structure */
10746	   SCIP_CONS*            cons,               /**< constraint */
10747	   SCIP_VAR*             var                 /**< variable to add to the constraint */
10748	   )
10749	{
10750	   SCIP_CONSHDLRDATA* conshdlrdata;
10751	   SCIP_CONSHDLR* conshdlr;
10752	
10753	   assert( scip != NULL );
10754	   assert( var != NULL );
10755	   assert( cons != NULL );
10756	
10757	   SCIPdebugMsg(scip, "appending variable <%s> to constraint <%s>\n", SCIPvarGetName(var), SCIPconsGetName(cons));
10758	
10759	   conshdlr = SCIPconsGetHdlr(cons);
10760	   assert( conshdlr != NULL );
10761	   if ( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
10762	   {
10763	      SCIPerrorMessage("constraint is not an SOS1 constraint.\n");
10764	      return SCIP_INVALIDDATA;
10765	   }
10766	
10767	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
10768	   assert( conshdlrdata != NULL );
10769	
10770	   SCIP_CALL( appendVarSOS1(scip, cons, conshdlrdata, var) );
10771	
10772	   return SCIP_OKAY;
10773	}
10774	
10775	
10776	/** gets number of variables in SOS1 constraint */
10777	int SCIPgetNVarsSOS1(
10778	   SCIP*                 scip,               /**< SCIP data structure */
10779	   SCIP_CONS*            cons                /**< constraint */
10780	   )
10781	{
10782	   SCIP_CONSDATA* consdata;
10783	
10784	   assert( scip != NULL );
10785	   assert( cons != NULL );
10786	
10787	   if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
10788	   {
10789	      SCIPerrorMessage("constraint is not an SOS1 constraint.\n");
10790	      SCIPABORT();
10791	      return -1;  /*lint !e527*/
10792	   }
10793	
10794	   consdata = SCIPconsGetData(cons);
10795	   assert( consdata != NULL );
10796	
10797	   return consdata->nvars;
10798	}
10799	
10800	
10801	/** gets array of variables in SOS1 constraint */
10802	SCIP_VAR** SCIPgetVarsSOS1(
10803	   SCIP*                 scip,               /**< SCIP data structure */
10804	   SCIP_CONS*            cons                /**< constraint data */
10805	   )
10806	{
10807	   SCIP_CONSDATA* consdata;
10808	
10809	   assert( scip != NULL );
10810	   assert( cons != NULL );
10811	
10812	   if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
10813	   {
10814	      SCIPerrorMessage("constraint is not an SOS1 constraint.\n");
10815	      SCIPABORT();
10816	      return NULL;  /*lint !e527*/
10817	   }
10818	
10819	   consdata = SCIPconsGetData(cons);
10820	   assert( consdata != NULL );
10821	
10822	   return consdata->vars;
10823	}
10824	
10825	
10826	/** gets array of weights in SOS1 constraint (or NULL if not existent) */
10827	SCIP_Real* SCIPgetWeightsSOS1(
10828	   SCIP*                 scip,               /**< SCIP data structure */
10829	   SCIP_CONS*            cons                /**< constraint data */
10830	   )
10831	{
10832	   SCIP_CONSDATA* consdata;
10833	
10834	   assert( scip != NULL );
10835	   assert( cons != NULL );
10836	
10837	   if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
10838	   {
10839	      SCIPerrorMessage("constraint is not an SOS1 constraint.\n");
10840	      SCIPABORT();
10841	      return NULL;  /*lint !e527*/
10842	   }
10843	
10844	   consdata = SCIPconsGetData(cons);
10845	   assert( consdata != NULL );
10846	
10847	   return consdata->weights;
10848	}
10849	
10850	
10851	/** gets conflict graph of SOS1 constraints (or NULL if not existent)
10852	 *
10853	 *  @note The conflict graph is globally valid; local changes are not taken into account.
10854	 */
10855	SCIP_DIGRAPH* SCIPgetConflictgraphSOS1(
10856	   SCIP_CONSHDLR*        conshdlr            /**< SOS1 constraint handler */
10857	   )
10858	{
10859	   SCIP_CONSHDLRDATA* conshdlrdata;
10860	
10861	   assert( conshdlr != NULL );
10862	
10863	   if ( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
10864	   {
10865	      SCIPerrorMessage("not an SOS1 constraint handler.\n");
10866	      SCIPABORT();
10867	      return NULL;  /*lint !e527*/
10868	   }
10869	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
10870	   assert( conshdlrdata != NULL );
10871	
10872	   return conshdlrdata->conflictgraph;
10873	}
10874	
10875	
10876	/** gets number of problem variables that are part of the SOS1 conflict graph */
10877	int SCIPgetNSOS1Vars(
10878	   SCIP_CONSHDLR*        conshdlr            /**< SOS1 constraint handler */
10879	   )
10880	{
10881	   SCIP_CONSHDLRDATA* conshdlrdata;
10882	
10883	   assert( conshdlr != NULL );
10884	
10885	   if ( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
10886	   {
10887	      SCIPerrorMessage("not an SOS1 constraint handler.\n");
10888	      SCIPABORT();
10889	      return -1; /*lint !e527*/
10890	   }
10891	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
10892	   assert( conshdlrdata != NULL );
10893	
10894	   return conshdlrdata->nsos1vars;
10895	}
10896	
10897	
10898	/** returns whether variable is part of the SOS1 conflict graph */
10899	SCIP_Bool SCIPvarIsSOS1(
10900	   SCIP_CONSHDLR*        conshdlr,           /**< SOS1 constraint handler */
10901	   SCIP_VAR*             var                 /**< variable */
10902	   )
10903	{
10904	   SCIP_CONSHDLRDATA* conshdlrdata;
10905	
10906	   assert( var != NULL );
10907	   assert( conshdlr != NULL );
10908	
10909	   if ( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
10910	   {
10911	      SCIPerrorMessage("not an SOS1 constraint handler.\n");
10912	      SCIPABORT();
10913	      return FALSE; /*lint !e527*/
10914	   }
10915	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
10916	   assert( conshdlrdata != NULL );
10917	
10918	   return varIsSOS1(conshdlrdata, var);
10919	}
10920	
10921	
10922	/** returns SOS1 index of variable or -1 if variable is not part of the SOS1 conflict graph */
10923	int SCIPvarGetNodeSOS1(
10924	   SCIP_CONSHDLR*        conshdlr,           /**< SOS1 constraint handler */
10925	   SCIP_VAR*             var                 /**< variable */
10926	   )
10927	{
10928	   SCIP_CONSHDLRDATA* conshdlrdata;
10929	
10930	   assert( conshdlr != NULL );
10931	   assert( var != NULL );
10932	
10933	   if ( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
10934	   {
10935	      SCIPerrorMessage("Not an SOS1 constraint handler.\n");
10936	      SCIPABORT();
10937	      return -1;  /*lint !e527*/
10938	   }
10939	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
10940	   assert( conshdlrdata != NULL );
10941	
10942	   if ( conshdlrdata->varhash == NULL )
10943	   {
10944	      SCIPerrorMessage("Hashmap not yet initialized.\n");
10945	      SCIPABORT();
10946	      return -1;  /*lint !e527*/
10947	   }
10948	
10949	   return varGetNodeSOS1(conshdlrdata, var);
10950	}
10951	
10952	
10953	/** returns variable that belongs to a given node from the conflict graph */
10954	SCIP_VAR* SCIPnodeGetVarSOS1(
10955	   SCIP_DIGRAPH*         conflictgraph,      /**< conflict graph */
10956	   int                   node                /**< node from the conflict graph */
10957	   )
10958	{
10959	   SCIP_NODEDATA* nodedata;
10960	
10961	   assert( conflictgraph != NULL );
10962	   assert( node >= 0 && node < SCIPdigraphGetNNodes(conflictgraph) );
10963	
10964	   /* get node data */
10965	   nodedata = (SCIP_NODEDATA*)SCIPdigraphGetNodeData(conflictgraph, node);
10966	
10967	   if ( nodedata == NULL )
10968	   {
10969	      SCIPerrorMessage("variable is not assigned to an index.\n");
10970	      SCIPABORT();
10971	      return NULL;  /*lint !e527*/
10972	   }
10973	
10974	   return nodedata->var;
10975	}
10976	
10977	
10978	/** based on solution values of the variables, fixes variables to zero to turn all SOS1 constraints feasible */
10979	SCIP_RETCODE SCIPmakeSOS1sFeasible(
10980	   SCIP*                 scip,               /**< SCIP pointer */
10981	   SCIP_CONSHDLR*        conshdlr,           /**< SOS1 constraint handler */
10982	   SCIP_SOL*             sol,                /**< solution */
10983	   SCIP_Bool*            changed,            /**< pointer to store whether the solution has been changed */
10984	   SCIP_Bool*            success             /**< pointer to store whether SOS1 constraints have been turned feasible and
10985	                                              *   solution was good enough */
10986	   )
10987	{
10988	   SCIP_CONSHDLRDATA* conshdlrdata;
10989	   SCIP_Real roundobjval;
10990	   SCIP_Bool allroundable;
10991	
10992	   assert( scip != NULL );
10993	   assert( conshdlr != NULL );
10994	   assert( sol != NULL );
10995	   assert( changed != NULL );
10996	   assert( success != NULL );
10997	
10998	   if ( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
10999	   {
11000	      SCIPerrorMessage("Not an SOS1 constraint handler.\n");
11001	      return SCIP_PARAMETERWRONGVAL;
11002	   }
11003	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
11004	   assert( conshdlrdata != NULL );
11005	
11006	   *changed = FALSE;
11007	   *success = FALSE;
11008	   allroundable = FALSE;
11009	
11010	   /* check number of SOS1 constraints */
11011	   if ( SCIPconshdlrGetNConss(conshdlr) < 1 )
11012	   {
11013	      *success = TRUE;
11014	      return SCIP_OKAY;
11015	   }
11016	
11017	   /* if the SOS1 constraints do not overlap, we apply a faster method makeSOS1constraintsFeasible() that does not make use of the conflict graph;
11018	    * for overlapping SOS1 constraints we apply the method makeSOS1conflictgraphFeasible(), which then may produce better feasible solutions */
11019	   if ( conshdlrdata->switchsos1branch )
11020	   {
11021	      SCIP_CALL( makeSOS1constraintsFeasible(scip, conshdlr, sol, changed, &allroundable) );
11022	   }
11023	   else
11024	   {
11025	      SCIP_CALL( makeSOS1conflictgraphFeasible(scip, conshdlr, sol, changed, &allroundable) );
11026	   }
11027	
11028	   if ( ! allroundable ) /*lint !e774*/
11029	      return SCIP_OKAY;
11030	
11031	   /* check whether objective value of rounded solution is good enough */
11032	   roundobjval = SCIPgetSolOrigObj(scip, sol);
11033	   if ( SCIPgetObjsense(scip) == SCIP_OBJSENSE_MAXIMIZE )
11034	      roundobjval *= -1;
11035	
11036	   if ( SCIPisLT(scip, roundobjval, SCIPgetUpperbound(scip) ) )
11037	      *success = TRUE;
11038	
11039	   return SCIP_OKAY;
11040	}
11041