1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*    Copyright (C) 2002-2022 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SCIP is distributed under the terms of the ZIB Academic License.         */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SCIP; see the file COPYING. If not visit scipopt.org.         */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	/**@file   cons_indicator.c
17   	 * @ingroup DEFPLUGINS_CONS
18   	 * @brief  constraint handler for indicator constraints
19   	 * @author Marc Pfetsch
20   	 *
21   	 * An indicator constraint is given by a binary variable \f$y\f$ and an inequality \f$ax \leq
22   	 * b\f$. It states that if \f$y = 1\f$ then \f$ax \leq b\f$ holds.
23   	 *
24   	 * This constraint is handled by adding a slack variable \f$s:\; ax - s \leq b\f$ with \f$s \geq
25   	 * 0\f$. The constraint is enforced by fixing \f$s\f$ to 0 if \f$y = 1\f$.
26   	 *
27   	 * @note The constraint only implements an implication not an equivalence, i.e., it does not ensure
28   	 * that \f$y = 1\f$ if \f$ax \leq b\f$ or equivalently if \f$s = 0\f$ holds.
29   	 *
30   	 * This constraint is equivalent to a linear constraint \f$ax - s \leq b\f$ and an SOS1 constraint on
31   	 * \f$y\f$ and \f$s\f$ (at most one should be nonzero). In the indicator context we can, however,
32   	 * separate more inequalities.
33   	 *
34   	 * The name indicator apparently comes from CPLEX.
35   	 *
36   	 *
37   	 * @section SEPARATION Separation Methods
38   	 *
39   	 * We now explain the handling of indicator constraints in more detail.  The indicator constraint
40   	 * handler adds an inequality for each indicator constraint. We assume that this system (with added
41   	 * slack variables) is \f$ Ax - s \leq b \f$, where \f$ x \f$ are the original variables and \f$ s
42   	 * \f$ are the slack variables added by the indicator constraint. Variables \f$ y \f$ are the binary
43   	 * variables corresponding to the indicator constraints.
44   	 *
45   	 * @note In the implementation, we assume that bounds on the original variables \f$x\f$ cannot be
46   	 * influenced by the indicator constraint. If it should be possible to relax these constraints as
47   	 * well, then these constraints have to be added as indicator constraints.
48   	 *
49   	 * We separate inequalities by using the so-called alternative polyhedron.
50   	 *
51   	 *
52   	 * @section ALTERNATIVEPOLYHEDRON Separation via the Alternative Polyhedron
53   	 *
54   	 * We now describe the separation method of the first method in more detail.
55   	 *
56   	 * Consider the LP-relaxation of the current subproblem:
57   	 * \f[
58   	 * \begin{array}{ll}
59   	 *  min & c^T x + d^T z\\
60   	 *      & A x - s \leq b, \\
61   	 *      & D x + C z \leq f, \\
62   	 *      & l \leq x \leq u, \\
63   	 *      & u \leq z \leq v, \\
64   	 *      & 0 \leq s.
65   	 * \end{array}
66   	 * \f]
67   	 * As above \f$Ax - s \leq b\f$ contains all inequalities corresponding to indicator constraints,
68   	 * while the system \f$Dx + Cy \leq f\f$ contains all other inequalities (which are ignored in the
69   	 * following). Similarly, variables \f$z\f$ not appearing in indicator constraints are
70   	 * ignored. Bounds for the variables \f$x_j\f$ can be given, in particular, variables can be
71   	 * fixed. Note that \f$s \leq 0\f$ renders the system infeasible.
72   	 *
73   	 * To generate cuts, we construct the so-called @a alternative @a polyhedron:
74   	 * \f[
75   	 * \begin{array}{ll}
76   	 *      P = \{ (w,r,t) : & A^T w - r + t = 0,\\
77   	 *                       & b^T w - l^T r + u^T t = -1,\\
78   	 *                       & w, r, t \geq 0 \}.
79   	 * \end{array}
80   	 * \f]
81   	 * Here, \f$r\f$ and \f$t\f$ correspond to the lower and upper bounds on \f$x\f$, respectively.
82   	 *
83   	 * It turns out that the vertices of \f$P\f$ correspond to minimal infeasible subsystems of \f$A x
84   	 * \leq b\f$, \f$l \leq x \leq u\f$. If \f$I\f$ is the index set of such a system, it follows that not all \f$s_i\f$ for
85   	 * \f$i \in I\f$ can be 0, i.e., \f$y_i\f$ can be 1. In other words, the following cut is valid:
86   	 * \f[
87   	 *      \sum_{i \in I} y_i \leq |I| - 1.
88   	 * \f]
89   	 *
90   	 *
91   	 * @subsection DETAIL Separation heuristic
92   	 *
93   	 * We separate the above inequalities by a heuristic described in
94   	 *
95   	 *   Branch-And-Cut for the Maximum Feasible Subsystem Problem,@n
96   	 *   Marc Pfetsch, SIAM Journal on Optimization 19, No.1, 21-38 (2008)
97   	 *
98   	 * The first step in the separation heuristic is to apply the transformation \f$\bar{y} = 1 - y\f$, which
99   	 * transforms the above inequality into the constraint
100  	 * \f[
101  	 *      \sum_{i \in I} \bar{y}_i \geq 1,
102  	 * \f]
103  	 * that is, it is a set covering constraint on the negated variables.
104  	 *
105  	 * The basic idea is to use the current solution to the LP relaxation and use it as the objective,
106  	 * when optimizing of the alternative polyhedron. Since any vertex corresponds to such an
107  	 * inequality, we can check whether it is violated. To enlarge the chance that we find a @em
108  	 * violated inequality, we perform a fixing procedure, in which the variable corresponding to an
109  	 * arbitrary element of the last IIS \f$I\f$ is fixed to zero, i.e., cannot be used in the next
110  	 * IISs. This is repeated until the corresponding alternative polyhedron is infeasible, i.e., we
111  	 * have obtained an IIS-cover. For more details see the paper above.
112  	 *
113  	 *
114  	 * @subsection PREPROC Preprocessing
115  	 *
116  	 * Since each indicator constraint adds a linear constraint to the formulation, preprocessing of the
117  	 * linear constraints change the above approach as follows.
118  	 *
119  	 * The system as present in the formulation is the following (ignoring variables that are not
120  	 * contained in indicator constraints and the objective function):
121  	 * \f[
122  	 *    \begin{array}{ll}
123  	 *      & A x - s \leq b, \\
124  	 *      & l \leq x \leq u, \\
125  	 *      & s \leq 0.
126  	 *    \end{array}
127  	 * \f]
128  	 * Note again that the requirement \f$s \leq 0\f$ leads to an infeasible system. Consider now the
129  	 * preprocessing of the linear constraint (aggregation, bound strengthening, etc.) and assume that
130  	 * this changes the above system to the following:
131  	 * \f[
132  	 *    \begin{array}{ll}
133  	 *      & \tilde{A} x - \tilde{B} s \leq \tilde{b}, \\
134  	 *      & \tilde{l} \leq x \leq \tilde{u}, \\
135  	 *      & s \leq 0. \\
136  	 *    \end{array}
137  	 * \f]
138  	 * Note that we forbid multi-aggregation of the \f$s\f$ variables in order to be able to change their
139  	 * bounds in propagation/branching. The corresponding alternative system is the following:
140  	 * \f[
141  	 *    \begin{array}{ll}
142  	 *      & \tilde{A}^T w - r + t = 0,\\
143  	 *      & - \tilde{B}^T w + v = 0,\\
144  	 *      & b^T w - l^T r + u^T t = -1,\\
145  	 *      & w, v, r, t \geq 0
146  	 *    \end{array}
147  	 *    \qquad \Leftrightarrow \qquad
148  	 *    \begin{array}{ll}
149  	 *      & \tilde{A}^T w - r + t = 0,\\
150  	 *      & \tilde{B}^T w \geq 0,\\
151  	 *      & b^T w - l^T r + u^T t = -1,\\
152  	 *      & w, r, t \geq 0,
153  	 *    \end{array}
154  	 * \f]
155  	 * where the second form arises by substituting \f$v \geq 0\f$. A closer look at this system reveals
156  	 * that it is not larger than the original one:
157  	 *
158  	 * - (Multi-)Aggregation of variables \f$x\f$ will remove these variables from the formulation, such that
159  	 *   the corresponding column of \f$\tilde{A}\f$ (row of \f$\tilde{A}^T\f$) will be zero.
160  	 *
161  	 * - The rows of \f$\tilde{B}^T\f$ are not unit vectors, i.e., do not correspond to redundant
162  	 *   nonnegativity constraints, only if the corresponding slack variables appear in an aggregation.
163  	 *
164  	 * Taken together, these two observations yield the conclusion that the new system is roughly as
165  	 * large as the original one.
166  	 *
167  	 * @note Because of possible (multi-)aggregation it might happen that the linear constraint
168  	 * corresponding to an indicator constraint becomes redundant and is deleted. From this we cannot
169  	 * conclude that the indicator constraint is redundant as well (i.e. always fulfilled), because the
170  	 * corresponding slack variable is still present and its setting to 0 might influence other
171  	 * (linear) constraints. Thus, we have to rely on the dual presolving of the linear constraints to
172  	 * detect this case: If the linear constraint is really redundant, i.e., is always fulfilled, it is
173  	 * deleted and the slack variable can be fixed to 0. In this case, the indicator constraint can be
174  	 * deleted as well.
175  	 *
176  	 * @todo Accept arbitrary ranged linear constraints as input (in particular: equations). Internally
177  	 * create two indicator constraints or correct alternative polyhedron accordingly (need to split the
178  	 * variables there, but not in original problem).
179  	 *
180  	 * @todo Treat variable upper bounds in a special way: Do not create the artificial slack variable,
181  	 * but directly enforce the propagations etc.
182  	 *
183  	 * @todo Turn off separation if the alternative polyhedron is infeasible and updateBounds is false.
184  	 *
185  	 * @todo Improve parsing of indicator constraint in CIP-format. Currently, we have to rely on a particular name, i.e.,
186  	 * the slack variable has to start with "indslack" and end with the name of the corresponding linear constraint.
187  	 *
188  	 * @todo Check whether one can further use the fact that the slack variable is aggregated.
189  	 */
190  	
191  	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
192  	
193  	#include "blockmemshell/memory.h"
194  	#include "lpi/lpi.h"
195  	#include "lpi/type_lpi.h"
196  	#include "scip/expr_var.h"
197  	#include "scip/expr_product.h"
198  	#include "scip/cons_nonlinear.h"
199  	#include "scip/cons_indicator.h"
200  	#include "scip/cons_linear.h"
201  	#include "scip/cons_logicor.h"
202  	#include "scip/cons_varbound.h"
203  	#include "scip/heur_indicator.h"
204  	#include "scip/heur_trysol.h"
205  	#include "scip/pub_conflict.h"
206  	#include "scip/pub_cons.h"
207  	#include "scip/pub_event.h"
208  	#include "scip/pub_lp.h"
209  	#include "scip/pub_message.h"
210  	#include "scip/pub_misc.h"
211  	#include "scip/pub_paramset.h"
212  	#include "scip/pub_var.h"
213  	#include "scip/scip_branch.h"
214  	#include "scip/scip_conflict.h"
215  	#include "scip/scip_cons.h"
216  	#include "scip/scip_copy.h"
217  	#include "scip/scip_cut.h"
218  	#include "scip/scip_event.h"
219  	#include "scip/scip_general.h"
220  	#include "scip/scip_heur.h"
221  	#include "scip/scip_lp.h"
222  	#include "scip/scip_mem.h"
223  	#include "scip/scip_message.h"
224  	#include "scip/scip_nlp.h"
225  	#include "scip/scip_numerics.h"
226  	#include "scip/scip_param.h"
227  	#include "scip/scip_prob.h"
228  	#include "scip/scip_probing.h"
229  	#include "scip/scip_sol.h"
230  	#include "scip/scip_solve.h"
231  	#include "scip/scip_solvingstats.h"
232  	#include "scip/scip_tree.h"
233  	#include "scip/scip_var.h"
234  	#include <string.h>
235  	
236  	/* #define SCIP_OUTPUT */
237  	/* #define SCIP_ENABLE_IISCHECK */
238  	
239  	/* constraint handler properties */
240  	#define CONSHDLR_NAME          "indicator"
241  	#define CONSHDLR_DESC          "indicator constraint handler"
242  	#define CONSHDLR_SEPAPRIORITY        10 /**< priority of the constraint handler for separation */
243  	#define CONSHDLR_ENFOPRIORITY      -100 /**< priority of the constraint handler for constraint enforcing */
244  	#define CONSHDLR_CHECKPRIORITY -6000000 /**< priority of the constraint handler for checking feasibility */
245  	#define CONSHDLR_SEPAFREQ            10 /**< frequency for separating cuts; zero means to separate only in the root node */
246  	#define CONSHDLR_PROPFREQ             1 /**< frequency for propagating domains; zero means only preprocessing propagation */
247  	#define CONSHDLR_EAGERFREQ          100 /**< frequency for using all instead of only the useful constraints in separation,
248  	                                         *   propagation and enforcement, -1 for no eager evaluations, 0 for first only */
249  	#define CONSHDLR_MAXPREROUNDS        -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
250  	#define CONSHDLR_DELAYSEPA        FALSE /**< Should separation method be delayed, if other separators found cuts? */
251  	#define CONSHDLR_DELAYPROP        FALSE /**< Should propagation method be delayed, if other propagators found reductions? */
252  	#define CONSHDLR_NEEDSCONS         TRUE /**< Should the constraint handler be skipped, if no constraints are available? */
253  	
254  	#define CONSHDLR_PRESOLTIMING      SCIP_PRESOLTIMING_FAST
255  	#define CONSHDLR_PROP_TIMING       SCIP_PROPTIMING_BEFORELP
256  	
257  	
258  	/* event handler properties */
259  	#define EVENTHDLR_BOUND_NAME       "indicatorbound"
260  	#define EVENTHDLR_BOUND_DESC       "bound change event handler for indicator constraints"
261  	
262  	#define EVENTHDLR_RESTART_NAME     "indicatorrestart"
263  	#define EVENTHDLR_RESTART_DESC     "force restart if absolute gap is 1 or enough binary variables have been fixed"
264  	
265  	
266  	/* conflict handler properties */
267  	#define CONFLICTHDLR_NAME          "indicatorconflict"
268  	#define CONFLICTHDLR_DESC          "replace slack variables and generate logicor constraints"
269  	#define CONFLICTHDLR_PRIORITY      200000
270  	
271  	/* upgrade properties */
272  	#define LINCONSUPGD_PRIORITY      +100000    /**< priority of the constraint handler for upgrading of linear constraints */
273  	
274  	/* default values for parameters */
275  	#define DEFAULT_BRANCHINDICATORS    FALSE    /**< Branch on indicator constraints in enforcing? */
276  	#define DEFAULT_GENLOGICOR          FALSE    /**< Generate logicor constraints instead of cuts? */
277  	#define DEFAULT_ADDCOUPLING          TRUE    /**< Add coupling constraints or rows if big-M is small enough? */
278  	#define DEFAULT_MAXCOUPLINGVALUE      1e4    /**< maximum coefficient for binary variable in coupling constraint */
279  	#define DEFAULT_ADDCOUPLINGCONS     FALSE    /**< Add initial variable upper bound constraints, if 'addcoupling' is true? */
280  	#define DEFAULT_SEPACOUPLINGCUTS     TRUE    /**< Should the coupling inequalities be separated dynamically? */
281  	#define DEFAULT_SEPACOUPLINGLOCAL   FALSE    /**< Allow to use local bounds in order to separate coupling inequalities? */
282  	#define DEFAULT_SEPACOUPLINGVALUE     1e4    /**< maximum coefficient for binary variable in separated coupling constraint */
283  	#define DEFAULT_SEPAALTERNATIVELP   FALSE    /**< Separate using the alternative LP? */
284  	#define DEFAULT_SEPAPERSPECTIVE     FALSE    /**< Separate cuts based on perspective formulation? */
285  	#define DEFAULT_SEPAPERSPLOCAL       TRUE    /**< Allow to use local bounds in order to separate perspectice cuts? */
286  	#define DEFAULT_MAXSEPANONVIOLATED      3    /**< maximal number of separated non violated IISs, before separation is stopped */
287  	#define DEFAULT_TRYSOLFROMCOVER     FALSE    /**< Try to construct a feasible solution from a cover? */
288  	#define DEFAULT_UPGRADELINEAR       FALSE    /**< Try to upgrade linear constraints to indicator constraints? */
289  	#define DEFAULT_USEOTHERCONSS       FALSE    /**< Collect other constraints to alternative LP? */
290  	#define DEFAULT_USEOBJECTIVECUT     FALSE    /**< Use objective cut with current best solution to alternative LP? */
291  	#define DEFAULT_UPDATEBOUNDS        FALSE    /**< Update bounds of original variables for separation? */
292  	#define DEFAULT_MAXCONDITIONALTLP     0.0    /**< max. estimated condition of the solution basis matrix of the alt. LP to be trustworthy (0.0 to disable check) */
293  	#define DEFAULT_MAXSEPACUTS           100    /**< maximal number of cuts separated per separation round */
294  	#define DEFAULT_MAXSEPACUTSROOT      2000    /**< maximal number of cuts separated per separation round in the root node */
295  	#define DEFAULT_REMOVEINDICATORS    FALSE    /**< Remove indicator constraint if corresponding variable bound constraint has been added? */
296  	#define DEFAULT_GENERATEBILINEAR    FALSE    /**< Do not generate indicator constraint, but a bilinear constraint instead? */
297  	#define DEFAULT_SCALESLACKVAR       FALSE    /**< Scale slack variable coefficient at construction time? */
298  	#define DEFAULT_NOLINCONSCONT       FALSE    /**< Decompose problem (do not generate linear constraint if all variables are continuous)? */
299  	#define DEFAULT_TRYSOLUTIONS         TRUE    /**< Try to make solutions feasible by setting indicator variables? */
300  	#define DEFAULT_ENFORCECUTS         FALSE    /**< In enforcing try to generate cuts (only if sepaalternativelp is true)? */
301  	#define DEFAULT_DUALREDUCTIONS       TRUE    /**< Should dual reduction steps be performed? */
302  	#define DEFAULT_ADDOPPOSITE         FALSE    /**< Add opposite inequality in nodes in which the binary variable has been fixed to 0? */
303  	#define DEFAULT_CONFLICTSUPGRADE    FALSE    /**< Try to upgrade bounddisjunction conflicts by replacing slack variables? */
304  	#define DEFAULT_FORCERESTART        FALSE    /**< Force restart if absolute gap is 1 or enough binary variables have been fixed? */
305  	#define DEFAULT_RESTARTFRAC           0.9    /**< fraction of binary variables that need to be fixed before restart occurs (in forcerestart) */
306  	
307  	
308  	/* other values */
309  	#define OBJEPSILON                  0.001    /**< value to add to objective in alt. LP if the binary variable is 1 to get small IISs */
310  	#define SEPAALTTHRESHOLD               10    /**< only separate IIS cuts if the number of separated coupling cuts is less than this value */
311  	#define MAXROUNDINGROUNDS               1    /**< maximal number of rounds that produced cuts in separation */
312  	
313  	
314  	/** constraint data for indicator constraints */
315  	struct SCIP_ConsData
316  	{
317  	   SCIP_VAR*             binvar;             /**< binary variable for indicator constraint */
318  	   SCIP_VAR*             slackvar;           /**< slack variable of inequality of indicator constraint */
319  	   SCIP_CONS*            lincons;            /**< linear constraint corresponding to indicator constraint */
320  	   SCIP_Bool             activeone;          /**< whether the constraint is active on 1 or 0 */
321  	   SCIP_Bool             lessthanineq;       /**< whether the original linear constraint is less-than-rhs or greater-than-rhs */
322  	   int                   nfixednonzero;      /**< number of variables among binvar and slackvar fixed to be nonzero */
323  	   int                   colindex;           /**< column index in alternative LP */
324  	   unsigned int          linconsactive:1;    /**< whether linear constraint and slack variable are active */
325  	   unsigned int          implicationadded:1; /**< whether corresponding implication has been added */
326  	   unsigned int          slacktypechecked:1; /**< whether it has been checked to convert the slack variable to be implicit integer */
327  	};
328  	
329  	
330  	/** indicator constraint handler data */
331  	struct SCIP_ConshdlrData
332  	{
333  	   SCIP_EVENTHDLR*       eventhdlrbound;     /**< event handler for bound change events */
334  	   SCIP_EVENTHDLR*       eventhdlrrestart;   /**< event handler for performing restarts */
335  	   SCIP_Bool             removable;          /**< whether the separated cuts should be removable */
336  	   SCIP_Bool             scaled;             /**< if first row of alt. LP has been scaled */
337  	   SCIP_Bool             objindicatoronly;   /**< whether the objective is nonzero only for indicator variables */
338  	   SCIP_Bool             objothervarsonly;   /**< whether the objective is nonzero only for non-indicator variables */
339  	   SCIP_Real             minabsobj;          /**< minimum absolute nonzero objective of indicator variables */
340  	   SCIP_LPI*             altlp;              /**< alternative LP for cut separation */
341  	   int                   nrows;              /**< # rows in the alt. LP corr. to original variables in linear constraints and slacks */
342  	   int                   nlbbounds;          /**< # lower bounds of original variables */
343  	   int                   nubbounds;          /**< # upper bounds of original variables */
344  	   SCIP_HASHMAP*         varhash;            /**< hash map from variable to row index in alternative LP */
345  	   SCIP_HASHMAP*         lbhash;             /**< hash map from variable to index of lower bound column in alternative LP */
346  	   SCIP_HASHMAP*         ubhash;             /**< hash map from variable to index of upper bound column in alternative LP */
347  	   SCIP_HASHMAP*         slackhash;          /**< hash map from slack variable to row index in alternative LP */
348  	   SCIP_HASHMAP*         binvarhash;         /**< hash map from binary indicator variable to indicator constraint */
349  	   int                   nslackvars;         /**< # slack variables */
350  	   int                   niiscutsgen;        /**< number of IIS-cuts generated */
351  	   int                   nperspcutsgen;      /**< number of cuts based on perspective formulation generated */
352  	   int                   objcutindex;        /**< index of objective cut in alternative LP (-1 if not added) */
353  	   SCIP_Real             objupperbound;      /**< best upper bound on objective known */
354  	   SCIP_Real             objaltlpbound;      /**< upper objective bound stored in alternative LP (infinity if not added) */
355  	   int                   maxroundingrounds;  /**< maximal number of rounds that produced cuts in separation */
356  	   SCIP_Real             roundingminthres;   /**< minimal value for rounding in separation */
357  	   SCIP_Real             roundingmaxthres;   /**< maximal value for rounding in separation */
358  	   SCIP_Real             roundingoffset;     /**< offset for rounding in separation */
359  	   SCIP_Bool             branchindicators;   /**< Branch on indicator constraints in enforcing? */
360  	   SCIP_Bool             genlogicor;         /**< Generate logicor constraints instead of cuts? */
361  	   SCIP_Bool             addcoupling;        /**< whether the coupling inequalities should be added at the beginning */
362  	   SCIP_Bool             addcouplingcons;    /**< Add initial variable upper bound constraints, if 'addcoupling' is true? */
363  	   SCIP_Bool             sepacouplingcuts;   /**< Should the coupling inequalities be separated dynamically? */
364  	   SCIP_Bool             sepacouplinglocal;  /**< Allow to use local bounds in order to separate coupling inequalities? */
365  	   SCIP_Bool             sepaperspective;    /**< Separate cuts based on perspective formulation? */
366  	   SCIP_Bool             sepapersplocal;     /**< Allow to use local bounds in order to separate perspectice cuts? */
367  	   SCIP_Bool             removeindicators;   /**< Remove indicator constraint if corresponding variable bound constraint has been added? */
368  	   SCIP_Bool             updatebounds;       /**< whether the bounds of the original variables should be changed for separation */
369  	   SCIP_Bool             trysolutions;       /**< Try to make solutions feasible by setting indicator variables? */
370  	   SCIP_Bool             enforcecuts;        /**< in enforcing try to generate cuts (only if sepaalternativelp is true) */
371  	   SCIP_Bool             dualreductions;     /**< Should dual reduction steps be performed? */
372  	   SCIP_Bool             addopposite;        /**< Add opposite inequality in nodes in which the binary variable has been fixed to 0? */
373  	   SCIP_Bool             generatebilinear;   /**< Do not generate indicator constraint, but a bilinear constraint instead? */
374  	   SCIP_Bool             scaleslackvar;      /**< Scale slack variable coefficient at construction time? */
375  	   SCIP_Bool             conflictsupgrade;   /**< Try to upgrade bounddisjunction conflicts by replacing slack variables? */
376  	   SCIP_Bool             performedrestart;   /**< whether a restart has been performed already */
377  	   int                   maxsepacuts;        /**< maximal number of cuts separated per separation round */
378  	   int                   maxsepacutsroot;    /**< maximal number of cuts separated per separation round in root node */
379  	   int                   maxsepanonviolated; /**< maximal number of separated non violated IISs, before separation is stopped */
380  	   int                   nbinvarszero;       /**< binary variables globally fixed to zero */
381  	   int                   ninitconss;         /**< initial number of indicator constraints (needed in event handlers) */
382  	   SCIP_Real             maxcouplingvalue;   /**< maximum coefficient for binary variable in initial coupling constraint */
383  	   SCIP_Real             sepacouplingvalue;  /**< maximum coefficient for binary variable in separated coupling constraint */
384  	   SCIP_Real             maxconditionaltlp;  /**< maximum estimated condition number of the alternative LP to trust its solution */
385  	   SCIP_Real             restartfrac;        /**< fraction of binary variables that need to be fixed before restart occurs (in forcerestart) */
386  	   SCIP_HEUR*            heurtrysol;         /**< trysol heuristic */
387  	   SCIP_Bool             addedcouplingcons;  /**< whether the coupling constraints have been added already */
388  	   SCIP_CONS**           addlincons;         /**< additional linear constraints that should be added to the alternative LP */
389  	   int                   naddlincons;        /**< number of additional constraints */
390  	   int                   maxaddlincons;      /**< maximal number of additional constraints */
391  	   SCIP_Bool             useotherconss;      /**< Collect other constraints to alternative LP? */
392  	   SCIP_Bool             useobjectivecut;    /**< Use objective cut with current best solution to alternative LP? */
393  	   SCIP_Bool             trysolfromcover;    /**< Try to construct a feasible solution from a cover? */
394  	   SCIP_Bool             upgradelinear;      /**< Try to upgrade linear constraints to indicator constraints? */
395  	   char                  normtype;           /**< norm type for cut computation */
396  	   /* parameters that should not be changed after problem stage: */
397  	   SCIP_Bool             sepaalternativelp;  /**< Separate using the alternative LP? */
398  	   SCIP_Bool             sepaalternativelp_; /**< used to store the sepaalternativelp parameter */
399  	   SCIP_Bool             nolinconscont;      /**< decompose problem - do not generate linear constraint if all variables are continuous */
400  	   SCIP_Bool             nolinconscont_;     /**< used to store the nolinconscont parameter */
401  	   SCIP_Bool             forcerestart;       /**< Force restart if absolute gap is 1 or enough binary variables have been fixed? */
402  	   SCIP_Bool             forcerestart_;      /**< used to store the forcerestart parameter */
403  	};
404  	
405  	
406  	/** indicator conflict handler data */
407  	struct SCIP_ConflicthdlrData
408  	{
409  	   SCIP_CONSHDLR*        conshdlr;           /**< indicator constraint handler */
410  	   SCIP_CONSHDLRDATA*    conshdlrdata;       /**< indicator constraint handler data */
411  	};
412  	
413  	
414  	/** type of enforcing/separation call */
415  	enum SCIP_enfosepatype
416  	{
417  	   SCIP_TYPE_ENFOLP      = 0,                /**< enforce LP */
418  	   SCIP_TYPE_ENFOPS      = 1,                /**< enforce pseudo solution */
419  	   SCIP_TYPE_ENFORELAX   = 2,                /**< enforce relaxation solution */
420  	   SCIP_TYPE_SEPALP      = 3,                /**< separate LP */
421  	   SCIP_TYPE_SEPARELAX   = 4,                /**< separate relaxation solution */
422  	   SCIP_TYPE_SEPASOL     = 5                 /**< separate relaxation solution */
423  	};
424  	typedef enum SCIP_enfosepatype SCIP_ENFOSEPATYPE;
425  	
426  	
427  	/* macro for parameters */
428  	#define SCIP_CALL_PARAM(x) /*lint -e527 */ do                                                   \
429  	{                                                                                               \
430  	   SCIP_RETCODE _restat_;                                                                       \
431  	   if ( (_restat_ = (x)) != SCIP_OKAY && (_restat_ != SCIP_PARAMETERUNKNOWN) )                  \
432  	   {                                                                                            \
433  	      SCIPerrorMessage("[%s:%d] Error <%d> in function call\n", __FILE__, __LINE__, _restat_);  \
434  	      SCIPABORT();                                                                              \
435  	      return _restat_;                                                                          \
436  	   }                                                                                            \
437  	}                                                                                               \
438  	while ( FALSE )
439  	
440  	
441  	/* ---------------- Callback methods of event handlers ---------------- */
442  	
443  	/** execute the event handler for getting variable bound changes
444  	 *
445  	 *  We update the number of variables fixed to be nonzero.
446  	 */
447  	static
448  	SCIP_DECL_EVENTEXEC(eventExecIndicatorBound)
449  	{
450  	   SCIP_EVENTTYPE eventtype;
451  	   SCIP_CONSDATA* consdata;
452  	   SCIP_Real oldbound;
453  	   SCIP_Real newbound;
454  	
455  	   assert( eventhdlr != NULL );
456  	   assert( eventdata != NULL );
457  	   assert( strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_BOUND_NAME) == 0 );
458  	   assert( event != NULL );
459  	
460  	   consdata = (SCIP_CONSDATA*)eventdata;
461  	   assert( consdata != NULL );
462  	   assert( 0 <= consdata->nfixednonzero && consdata->nfixednonzero <= 2 );
463  	   assert( consdata->linconsactive );
464  	
465  	   oldbound = SCIPeventGetOldbound(event);
466  	   newbound = SCIPeventGetNewbound(event);
467  	
468  	   eventtype = SCIPeventGetType(event);
469  	   switch ( eventtype )
470  	   {
471  	   case SCIP_EVENTTYPE_LBTIGHTENED:
472  	      /* if variable is now fixed to be positive */
473  	      if ( ! SCIPisFeasPositive(scip, oldbound) && SCIPisFeasPositive(scip, newbound) )
474  	         ++(consdata->nfixednonzero);
475  	#ifdef SCIP_MORE_DEBUG
476  	      SCIPdebugMsg(scip, "Changed lower bound of variable <%s> from %g to %g (nfixednonzero: %d).\n",
477  	         SCIPvarGetName(SCIPeventGetVar(event)), oldbound, newbound, consdata->nfixednonzero);
478  	#endif
479  	      break;
480  	
481  	   case SCIP_EVENTTYPE_UBTIGHTENED:
482  	      /* if variable is now fixed to be negative */
483  	      if ( ! SCIPisFeasNegative(scip, oldbound) && SCIPisFeasNegative(scip, newbound) )
484  	         ++(consdata->nfixednonzero);
485  	#ifdef SCIP_MORE_DEBUG
486  	      SCIPdebugMsg(scip, "Changed upper bound of variable <%s> from %g to %g (nfixednonzero: %d).\n",
487  	         SCIPvarGetName(SCIPeventGetVar(event)), oldbound, newbound, consdata->nfixednonzero);
488  	#endif
489  	      break;
490  	
491  	   case SCIP_EVENTTYPE_LBRELAXED:
492  	      /* if variable is not fixed to be positive anymore */
493  	      if ( SCIPisFeasPositive(scip, oldbound) && ! SCIPisFeasPositive(scip, newbound) )
494  	         --(consdata->nfixednonzero);
495  	#ifdef SCIP_MORE_DEBUG
496  	      SCIPdebugMsg(scip, "Changed lower bound of variable <%s> from %g to %g (nfixednonzero: %d).\n",
497  	         SCIPvarGetName(SCIPeventGetVar(event)), oldbound, newbound, consdata->nfixednonzero);
498  	#endif
499  	      break;
500  	
501  	   case SCIP_EVENTTYPE_UBRELAXED:
502  	      /* if variable is not fixed to be negative anymore */
503  	      if ( SCIPisFeasNegative(scip, oldbound) && ! SCIPisFeasNegative(scip, newbound) )
504  	         --(consdata->nfixednonzero);
505  	#ifdef SCIP_MORE_DEBUG
506  	      SCIPdebugMsg(scip, "Changed upper bound of variable <%s> from %g to %g (nfixednonzero: %d).\n",
507  	         SCIPvarGetName(SCIPeventGetVar(event)), oldbound, newbound, consdata->nfixednonzero);
508  	#endif
509  	      break;
510  	
511  	   default:
512  	      SCIPerrorMessage("Invalid event type.\n");
513  	      SCIPABORT();
514  	      return SCIP_INVALIDDATA; /*lint !e527*/
515  	   }
516  	   assert( 0 <= consdata->nfixednonzero && consdata->nfixednonzero <= 2 );
517  	
518  	   return SCIP_OKAY;
519  	}
520  	
521  	
522  	/** exec the event handler for forcing a restart
523  	 *
524  	 *  There are two cases in which we perform a (user) restart:
525  	 *  - If we have a max FS instance, i.e., the objective is 1 for indicator variables and 0 otherwise,
526  	 *    we can force a restart if the gap is 1. In this case, the remaining work consists of proving
527  	 *    infeasibility of the non-fixed indicators.
528  	 *  - If a large fraction of the binary indicator variables have been globally fixed, it makes sense
529  	 *    to force a restart.
530  	 */
531  	static
532  	SCIP_DECL_EVENTEXEC(eventExecIndicatorRestart)
533  	{
534  	   SCIP_CONSHDLRDATA* conshdlrdata;
535  	   SCIP_EVENTTYPE eventtype;
536  	
537  	   assert( scip != NULL );
538  	   assert( eventhdlr != NULL );
539  	   assert( eventdata != NULL );
540  	   assert( strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_RESTART_NAME) == 0 );
541  	   assert( event != NULL );
542  	
543  	   conshdlrdata = (SCIP_CONSHDLRDATA*)eventdata;
544  	   assert( conshdlrdata != NULL );
545  	   assert( conshdlrdata->forcerestart );
546  	
547  	   eventtype = SCIPeventGetType(event);
548  	   switch ( eventtype )
549  	   {
550  	   case SCIP_EVENTTYPE_GUBCHANGED:
551  	   case SCIP_EVENTTYPE_GLBCHANGED:
552  	   {
553  	#ifndef NDEBUG
554  	      SCIP_Real oldbound;
555  	      SCIP_Real newbound;
556  	
557  	      assert( SCIPvarGetType(SCIPeventGetVar(event)) == SCIP_VARTYPE_BINARY );
558  	      oldbound = SCIPeventGetOldbound(event);
559  	      newbound = SCIPeventGetNewbound(event);
560  	      assert( SCIPisIntegral(scip, oldbound) );
561  	      assert( SCIPisIntegral(scip, newbound) );
562  	      assert( ! SCIPisEQ(scip, oldbound, newbound) );
563  	      assert( SCIPisZero(scip, oldbound) || SCIPisEQ(scip, oldbound, 1.0) );
564  	      assert( SCIPisZero(scip, newbound) || SCIPisEQ(scip, newbound, 1.0) );
565  	#endif
566  	
567  	      /* do not treat this case if we have performed a restart already */
568  	      if ( conshdlrdata->performedrestart )
569  	         return SCIP_OKAY;
570  	
571  	      /* variable is now fixed */
572  	      ++(conshdlrdata->nbinvarszero);
573  	      SCIPdebugMsg(scip, "Fixed variable <%s> (nbinvarszero: %d, total: %d).\n",
574  	         SCIPvarGetName(SCIPeventGetVar(event)), conshdlrdata->nbinvarszero, conshdlrdata->ninitconss);
575  	
576  	      if ( SCIPgetStage(scip) != SCIP_STAGE_SOLVING )
577  	         break;
578  	
579  	      /* if enough variables have been fixed */
580  	      if ( conshdlrdata->nbinvarszero > (int) ((SCIP_Real) conshdlrdata->ninitconss * conshdlrdata->restartfrac) )
581  	      {
582  	         SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL,
583  	            "Forcing restart, since %d binary variables among %d have been fixed.\n", conshdlrdata->nbinvarszero, conshdlrdata->ninitconss);
584  	         SCIP_CALL( SCIPrestartSolve(scip) );
585  	
586  	         /* drop event */
587  	         if ( conshdlrdata->objindicatoronly )
588  	         {
589  	            SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_BESTSOLFOUND, eventhdlr, (SCIP_EVENTDATA*) conshdlrdata, -1) );
590  	         }
591  	         conshdlrdata->performedrestart = TRUE;
592  	      }
593  	      break;
594  	   }
595  	
596  	   case SCIP_EVENTTYPE_BESTSOLFOUND:
597  	      assert( SCIPisIntegral(scip, conshdlrdata->minabsobj) );
598  	      assert( SCIPisGE(scip, conshdlrdata->minabsobj, 1.0 ) );
599  	
600  	      if ( SCIPgetStage(scip) != SCIP_STAGE_SOLVING )
601  	         break;
602  	
603  	      if ( ! conshdlrdata->objindicatoronly )
604  	         break;
605  	
606  	      /* if the absolute gap is equal to minabsobj */
607  	      if ( SCIPisEQ(scip, REALABS(SCIPgetPrimalbound(scip) - SCIPgetDualbound(scip)), conshdlrdata->minabsobj) )
608  	      {
609  	         SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "Forcing restart, since the absolute gap is %f.\n", conshdlrdata->minabsobj);
610  	         SCIP_CALL( SCIPrestartSolve(scip) );
611  	
612  	         /* use inference branching, since the objective is not meaningful */
613  	         if ( SCIPfindBranchrule(scip, "inference") != NULL && !SCIPisParamFixed(scip, "branching/inference/priority") )
614  	         {
615  	            SCIP_CALL( SCIPsetIntParam(scip, "branching/inference/priority", INT_MAX/4) );
616  	         }
617  	
618  	         /* drop event */
619  	         SCIP_CALL( SCIPdropEvent(scip, SCIP_EVENTTYPE_BESTSOLFOUND, eventhdlr, (SCIP_EVENTDATA*) conshdlrdata, -1) );
620  	         conshdlrdata->performedrestart = TRUE;
621  	      }
622  	      break;
623  	
624  	   default:
625  	      SCIPerrorMessage("invalid event type.\n");
626  	      SCIPABORT();
627  	      return SCIP_INVALIDDATA; /*lint !e527*/
628  	   }
629  	
630  	   return SCIP_OKAY;
631  	}
632  	
633  	
634  	/* ------------------------ conflict handler ---------------------------------*/
635  	
636  	/** destructor of conflict handler to free conflict handler data (called when SCIP is exiting) */
637  	static
638  	SCIP_DECL_CONFLICTFREE(conflictFreeIndicator)
639  	{
640  	   SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
641  	
642  	   assert( scip != NULL );
643  	   assert( conflicthdlr != NULL );
644  	   assert( strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0 );
645  	
646  	   conflicthdlrdata = SCIPconflicthdlrGetData(conflicthdlr);
647  	   SCIPfreeBlockMemory(scip, &conflicthdlrdata);
648  	
649  	   return SCIP_OKAY;
650  	}
651  	
652  	
653  	/** conflict processing method of conflict handler (called when conflict was found)
654  	 *
655  	 *  In this conflict handler we try to replace slack variables by binary indicator variables and
656  	 *  generate a logicor constraint if possible.
657  	 *
658  	 *  @todo Extend to integral case.
659  	 */
660  	static
661  	SCIP_DECL_CONFLICTEXEC(conflictExecIndicator)
662  	{  /*lint --e{715}*/
663  	   SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
664  	   SCIP_Bool haveslack;
665  	   SCIP_VAR* var;
666  	   int i;
667  	
668  	   assert( conflicthdlr != NULL );
669  	   assert( strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0 );
670  	   assert( bdchginfos != NULL || nbdchginfos == 0 );
671  	   assert( result != NULL );
672  	
673  	   /* don't process already resolved conflicts */
674  	   if ( resolved )
675  	   {
676  	      *result = SCIP_DIDNOTRUN;
677  	      return SCIP_OKAY;
678  	   }
679  	
680  	   SCIPdebugMsg(scip, "Indicator conflict handler.\n");
681  	
682  	   conflicthdlrdata = SCIPconflicthdlrGetData(conflicthdlr);
683  	   assert( conflicthdlrdata != NULL );
684  	
685  	   /* possibly skip conflict handler */
686  	   if ( ! ((SCIP_CONFLICTHDLRDATA*) conflicthdlrdata)->conshdlrdata->conflictsupgrade )
687  	      return SCIP_OKAY;
688  	
689  	   *result = SCIP_DIDNOTFIND;
690  	
691  	   /* check whether there seems to be one slack variable and all other variables are binary */
692  	   haveslack = FALSE;
693  	   for (i = 0; i < nbdchginfos; ++i)
694  	   {
695  	      assert( bdchginfos != NULL ); /* for flexelint */
696  	      assert( bdchginfos[i] != NULL );
697  	
698  	      var = SCIPbdchginfoGetVar(bdchginfos[i]);
699  	
700  	      /* quick check for slack variable that is implicitly integral or continuous */
701  	      if ( SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT || SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
702  	      {
703  	         /* check string */
704  	         if ( strstr(SCIPvarGetName(var), "indslack") != NULL )
705  	         {
706  	            /* make sure that the slack variable occurs with its lower bound */
707  	            if ( SCIPboundtypeOpposite(SCIPbdchginfoGetBoundtype(bdchginfos[i])) != SCIP_BOUNDTYPE_LOWER )
708  	               break;
709  	
710  	            /* make sure that the lower bound is 0 */
711  	            if ( ! SCIPisFeasZero(scip, SCIPbdchginfoGetNewbound(bdchginfos[i])) )
712  	               break;
713  	
714  	            haveslack = TRUE;
715  	            continue;
716  	         }
717  	      }
718  	
719  	      /* we only treat binary variables (other than slack variables) */
720  	      if ( ! SCIPvarIsBinary(var) )
721  	         break;
722  	   }
723  	
724  	   /* if we have found at least one slack variable and all other variables are binary */
725  	   if ( haveslack && i == nbdchginfos )
726  	   {
727  	      SCIP_CONS** conss;
728  	      SCIP_VAR** vars;
729  	      int nconss;
730  	      int j;
731  	
732  	      SCIPdebugMsg(scip, "Found conflict involving slack variables that can be remodelled.\n");
733  	
734  	      assert( conflicthdlrdata->conshdlr != NULL );
735  	      assert( strcmp(SCIPconshdlrGetName(conflicthdlrdata->conshdlr), CONSHDLR_NAME) == 0 );
736  	
737  	      nconss = SCIPconshdlrGetNConss(conflicthdlrdata->conshdlr);
738  	      conss = SCIPconshdlrGetConss(conflicthdlrdata->conshdlr);
739  	
740  	      /* create array of variables in conflict constraint */
741  	      SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
742  	      for (i = 0; i < nbdchginfos; ++i)
743  	      {
744  	         assert( bdchginfos != NULL ); /* for flexelint */
745  	         assert( bdchginfos[i] != NULL );
746  	
747  	         var = SCIPbdchginfoGetVar(bdchginfos[i]);
748  	
749  	         SCIPdebugMsg(scip, " <%s> %s %g\n", SCIPvarGetName(var), SCIPbdchginfoGetBoundtype(bdchginfos[i]) == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
750  	            SCIPbdchginfoGetNewbound(bdchginfos[i]));
751  	
752  	         /* quick check for slack variable that is implicitly integral or continuous */
753  	         if ( (SCIPvarGetType(var) == SCIP_VARTYPE_IMPLINT || SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS) && strstr(SCIPvarGetName(var), "indslack") != NULL )
754  	         {
755  	            SCIP_VAR* slackvar;
756  	
757  	            /* search for slack variable */
758  	            for (j = 0; j < nconss; ++j)
759  	            {
760  	               assert( conss[j] != NULL );
761  	               slackvar = SCIPgetSlackVarIndicator(conss[j]);
762  	               assert( slackvar != NULL );
763  	
764  	               /* check whether we found the variable */
765  	               if ( slackvar == var )
766  	               {
767  	                  /* replace slack variable by binary variable */
768  	                  var = SCIPgetBinaryVarIndicator(conss[j]);
769  	                  break;
770  	               }
771  	            }
772  	
773  	            /* check whether we found the slack variable */
774  	            if ( j >= nconss )
775  	            {
776  	               SCIPdebugMsg(scip, "Could not find slack variable <%s>.\n", SCIPvarGetName(var));
777  	               break;
778  	            }
779  	         }
780  	         else
781  	         {
782  	            /* if the variable is fixed to one in the conflict set, we have to use its negation */
783  	            if ( SCIPbdchginfoGetNewbound(bdchginfos[i]) > 0.5 )
784  	            {
785  	               SCIP_CALL( SCIPgetNegatedVar(scip, var, &var) );
786  	            }
787  	         }
788  	
789  	         vars[i] = var;
790  	      }
791  	
792  	      /* whether all slack variables have been found */
793  	      if ( i == nbdchginfos )
794  	      {
795  	         SCIP_CONS* cons;
796  	         char consname[SCIP_MAXSTRLEN];
797  	
798  	         SCIPdebugMsg(scip, "Generated logicor conflict constraint.\n");
799  	
800  	         /* create a logicor constraint out of the conflict set */
801  	         (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%d_%" SCIP_LONGINT_FORMAT, SCIPgetNRuns(scip), SCIPgetNConflictConssApplied(scip));
802  	         SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, consname, nbdchginfos, vars,
803  	               FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
804  	
805  	#ifdef SCIP_OUTPUT
806  	         SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
807  	         SCIPinfoMessage(scip, NULL, ";\n");
808  	#endif
809  	
810  	         /* add constraint to SCIP */
811  	         SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
812  	
813  	         *result = SCIP_CONSADDED;
814  	      }
815  	
816  	      /* free temporary memory */
817  	      SCIPfreeBufferArray(scip, &vars);
818  	   }
819  	
820  	   return SCIP_OKAY;
821  	}
822  	
823  	
824  	/* ------------------------ parameter handling ---------------------------------*/
825  	
826  	/** check whether we transfer a changed parameter to the given value
827  	 *
828  	 *  @see paramChangedIndicator()
829  	 */
830  	static
831  	SCIP_RETCODE checkTransferBoolParam(
832  	   SCIP*                 scip,               /**< SCIP data structure */
833  	   SCIP_PARAM*           param,              /**< parameter */
834  	   const char*           name,               /**< parameter name to check */
835  	   SCIP_Bool             newvalue,           /**< new value */
836  	   SCIP_Bool*            value               /**< old and possibly changed value of parameter */
837  	   )
838  	{
839  	   const char* paramname;
840  	
841  	   assert( scip != NULL );
842  	   assert( param != NULL );
843  	   assert( name != NULL );
844  	   assert( value != NULL );
845  	
846  	   if ( SCIPparamGetType(param) != SCIP_PARAMTYPE_BOOL )
847  	      return SCIP_OKAY;
848  	
849  	   if ( *value == newvalue )
850  	      return SCIP_OKAY;
851  	
852  	   paramname = SCIPparamGetName(param);
853  	   assert( paramname != NULL );
854  	
855  	   /* check whether the change parameter corresponds to our name to check */
856  	   if ( strcmp(paramname, name) == 0 )
857  	   {
858  	      /* check stage and possibly ignore parameter change */
859  	      if ( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM )
860  	      {
861  	         SCIPwarningMessage(scip, "Cannot change parameter <%s> stage %d - reset to old value %s.\n", name, SCIPgetStage(scip), *value ? "true" : "false");
862  	         /* Note that the following command will create a recursive call, but then *value == newvalue above. */
863  	         SCIP_CALL( SCIPchgBoolParam(scip, param, *value) );
864  	      }
865  	      else
866  	      {
867  	         /* otherwise copy value */
868  	         *value = newvalue;
869  	      }
870  	   }
871  	
872  	   return SCIP_OKAY;
873  	}
874  	
875  	
876  	/** called after a parameter has been changed */
877  	static
878  	SCIP_DECL_PARAMCHGD(paramChangedIndicator)
879  	{
880  	   SCIP_CONSHDLR* conshdlr;
881  	   SCIP_CONSHDLRDATA* conshdlrdata;
882  	
883  	   assert( scip != NULL );
884  	   assert( param != NULL );
885  	
886  	   /* get indicator constraint handler */
887  	   conshdlr = SCIPfindConshdlr(scip, "indicator");
888  	   assert( conshdlr != NULL );
889  	
890  	   /* get constraint handler data */
891  	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
892  	   assert( conshdlrdata != NULL );
893  	
894  	   SCIP_CALL( checkTransferBoolParam(scip, param, "constraints/indicator/sepaalternativelp", conshdlrdata->sepaalternativelp_, &conshdlrdata->sepaalternativelp) );
895  	   SCIP_CALL( checkTransferBoolParam(scip, param, "constraints/indicator/forcerestart", conshdlrdata->forcerestart_, &conshdlrdata->forcerestart) );
896  	   SCIP_CALL( checkTransferBoolParam(scip, param, "constraints/indicator/nolinconscont", conshdlrdata->nolinconscont_, &conshdlrdata->nolinconscont) );
897  	
898  	   return SCIP_OKAY;
899  	}
900  	
901  	
902  	/* ------------------------ debugging routines ---------------------------------*/
903  	
904  	#ifdef SCIP_ENABLE_IISCHECK
905  	/** Check that indicator constraints corresponding to nonnegative entries in @a vector are infeasible in original problem
906  	 *
907  	 *  @note This function will probably fail if the has been presolved by the cons_linear presolver. To make it complete
908  	 *  we would have to substitute active variables.
909  	 */
910  	static
911  	SCIP_RETCODE checkIIS(
912  	   SCIP*                 scip,               /**< SCIP pointer */
913  	   int                   nconss,             /**< number of constraints */
914  	   SCIP_CONS**           conss,              /**< indicator constraints */
915  	   SCIP_Real*            vector              /**< vector */
916  	   )
917  	{
918  	   SCIP_CONSHDLRDATA* conshdlrdata;
919  	   SCIP_CONSHDLR* conshdlr;
920  	   SCIP_HASHMAP* varhash;   /* hash map from variable to column index in auxiliary LP */
921  	   SCIP_LPI* lp;
922  	   int nvars = 0;
923  	   int c;
924  	
925  	   assert( scip != NULL );
926  	   assert( vector != NULL );
927  	
928  	   SCIPdebugMsg(scip, "Checking IIS ...\n");
929  	
930  	   /* now check indicator constraints */
931  	   conshdlr = SCIPfindConshdlr(scip, "indicator");
932  	   assert( conshdlr != NULL );
933  	
934  	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
935  	   assert( conshdlrdata != NULL );
936  	
937  	   conss = SCIPconshdlrGetConss(conshdlr);
938  	   nconss = SCIPconshdlrGetNConss(conshdlr);
939  	
940  	   /* create LP */
941  	   SCIP_CALL( SCIPlpiCreate(&lp, SCIPgetMessagehdlr(scip), "checkLP", SCIP_OBJSEN_MINIMIZE) );
942  	
943  	   /* set up hash map */
944  	   SCIP_CALL( SCIPhashmapCreate(&varhash, SCIPblkmem(scip), SCIPgetNVars(scip)) );
945  	
946  	   /* loop through indicator constraints */
947  	   for (c = 0; c < nconss; ++c)
948  	   {
949  	      SCIP_CONSDATA* consdata;
950  	      consdata = SCIPconsGetData(conss[c]);
951  	      assert( consdata != NULL );
952  	
953  	      /* check whether constraint should be included */
954  	      if ( consdata->colindex >= 0 && (! SCIPisFeasZero(scip, vector[consdata->colindex]) || ! SCIPconsIsEnabled(conss[c])) )
955  	      {
956  	         SCIP_CONS* lincons;
957  	         SCIP_VAR** linvars;
958  	         SCIP_Real* linvals;
959  	         SCIP_Real linrhs;
960  	         SCIP_Real linlhs;
961  	         SCIP_VAR* slackvar;
962  	         int nlinvars;
963  	         SCIP_Real sign = 1.0;
964  	         int matbeg;
965  	         int* matind;
966  	         SCIP_Real* matval;
967  	         SCIP_VAR** newvars;
968  	         int nnewvars;
969  	         SCIP_Real lhs;
970  	         SCIP_Real rhs;
971  	         int cnt;
972  	         int v;
973  	
974  	         lincons = consdata->lincons;
975  	         assert( lincons != NULL );
976  	         assert( ! SCIPconsIsEnabled(conss[c]) || SCIPconsIsActive(lincons) );
977  	         assert( ! SCIPconsIsEnabled(conss[c]) || SCIPconsIsEnabled(lincons) );
978  	
979  	         slackvar = consdata->slackvar;
980  	         assert( slackvar != NULL );
981  	
982  	         /* if the slack variable is aggregated (multi-aggregation should not happen) */
983  	         assert( SCIPvarGetStatus(slackvar) != SCIP_VARSTATUS_MULTAGGR );
984  	         if ( SCIPvarGetStatus(slackvar) == SCIP_VARSTATUS_AGGREGATED )
985  	         {
986  	            SCIP_VAR* var;
987  	            SCIP_Real scalar = 1.0;
988  	            SCIP_Real constant = 0.0;
989  	
990  	            var = slackvar;
991  	
992  	            SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
993  	            assert( ! SCIPisZero(scip, scalar) );
994  	
995  	            /*  SCIPdebugMsg(scip, "slack variable aggregated (scalar: %f, constant: %f)\n", scalar, constant); */
996  	
997  	            /* otherwise construct a linear constraint */
998  	            SCIP_CALL( SCIPallocBufferArray(scip, &linvars, 1) );
999  	            SCIP_CALL( SCIPallocBufferArray(scip, &linvals, 1) );
1000 	            linvars[0] = var;
1001 	            linvals[0] = scalar;
1002 	            nlinvars = 1;
1003 	            linlhs = -SCIPinfinity(scip);
1004 	            linrhs = constant;
1005 	         }
1006 	         else
1007 	         {
1008 	            /* in this case, the linear constraint is directly usable */
1009 	            linvars = SCIPgetVarsLinear(scip, lincons);
1010 	            linvals = SCIPgetValsLinear(scip, lincons);
1011 	            nlinvars = SCIPgetNVarsLinear(scip, lincons);
1012 	            linlhs = SCIPgetLhsLinear(scip, lincons);
1013 	            linrhs = SCIPgetRhsLinear(scip, lincons);
1014 	         }
1015 	
1016 	         /* adapt rhs of linear constraint */
1017 	         assert( SCIPisInfinity(scip, -linlhs) || SCIPisInfinity(scip, linrhs) );
1018 	         if ( SCIPisInfinity(scip, linrhs) )
1019 	         {
1020 	            linrhs = -linlhs;
1021 	            assert( linrhs > -SCIPinfinity(scip) );
1022 	            sign = -1.0;
1023 	         }
1024 	
1025 	         SCIP_CALL( SCIPallocBufferArray(scip, &matind, 4*nlinvars) );
1026 	         SCIP_CALL( SCIPallocBufferArray(scip, &matval, 4*nlinvars) );
1027 	         SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nlinvars) );
1028 	
1029 	         /* set up row */
1030 	         nnewvars = 0;
1031 	         for (v = 0; v < nlinvars; ++v)
1032 	         {
1033 	            SCIP_VAR* var;
1034 	            var = linvars[v];
1035 	            assert( var != NULL );
1036 	
1037 	            /* skip slack variable */
1038 	            if ( var == slackvar )
1039 	               continue;
1040 	
1041 	            /* if variable is new */
1042 	            if ( ! SCIPhashmapExists(varhash, var) )
1043 	            {
1044 	               /* add variable in map */
1045 	               SCIP_CALL( SCIPhashmapInsertInt(varhash, var, nvars) );
1046 	               assert( nvars == SCIPhashmapGetImageInt(varhash, var) );
1047 	               /* SCIPdebugMsg(scip, "Inserted variable <%s> into hashmap (%d).\n", SCIPvarGetName(var), nvars); */
1048 	               nvars++;
1049 	
1050 	               /* store new variables */
1051 	               newvars[nnewvars++] = var;
1052 	            }
1053 	            assert( SCIPhashmapExists(varhash, var) );
1054 	         }
1055 	
1056 	         /* add new columns */
1057 	         if ( nnewvars > 0 )
1058 	         {
1059 	            SCIP_Real* lb;
1060 	            SCIP_Real* ub;
1061 	            SCIP_Real* obj;
1062 	            char** colnames;
1063 	
1064 	            SCIP_CALL( SCIPallocBufferArray(scip, &lb, nnewvars) );
1065 	            SCIP_CALL( SCIPallocBufferArray(scip, &ub, nnewvars) );
1066 	            SCIP_CALL( SCIPallocBufferArray(scip, &obj, nnewvars) );
1067 	            SCIP_CALL( SCIPallocBufferArray(scip, &colnames, nnewvars) );
1068 	
1069 	            for (v = 0; v < nnewvars; ++v)
1070 	            {
1071 	               SCIP_VAR* var;
1072 	               var = newvars[v];
1073 	               obj[v] = 0.0;
1074 	               lb[v] = SCIPvarGetLbLocal(var);
1075 	               ub[v] = SCIPvarGetUbLocal(var);
1076 	               SCIP_CALL( SCIPallocBufferArray(scip, &(colnames[v]), SCIP_MAXSTRLEN) ); /*lint !e866*/
1077 	               (void) SCIPsnprintf(colnames[v], SCIP_MAXSTRLEN, "%s", SCIPvarGetName(var));
1078 	            }
1079 	
1080 	            /* now add columns */
1081 	            SCIP_CALL( SCIPlpiAddCols(lp, nnewvars, obj, lb, ub, colnames, 0, NULL, NULL, NULL) );
1082 	
1083 	            for (v = nnewvars - 1; v >= 0; --v)
1084 	            {
1085 	               SCIPfreeBufferArray(scip, &(colnames[v]));
1086 	            }
1087 	            SCIPfreeBufferArray(scip, &colnames);
1088 	            SCIPfreeBufferArray(scip, &obj);
1089 	            SCIPfreeBufferArray(scip, &ub);
1090 	            SCIPfreeBufferArray(scip, &lb);
1091 	         }
1092 	
1093 	         /* set up row */
1094 	         cnt = 0;
1095 	         for (v = 0; v < nlinvars; ++v)
1096 	         {
1097 	            SCIP_VAR* var;
1098 	            var = linvars[v];
1099 	            assert( var != NULL );
1100 	
1101 	            /* skip slack variable */
1102 	            if ( var == slackvar )
1103 	               continue;
1104 	
1105 	            assert( SCIPhashmapExists(varhash, var) );
1106 	            matind[cnt] = SCIPhashmapGetImageInt(varhash, var);
1107 	            matval[cnt] = sign * linvals[v];
1108 	            ++cnt;
1109 	         }
1110 	
1111 	         lhs = -SCIPlpiInfinity(lp);
1112 	         rhs = linrhs;
1113 	
1114 	         /* add new row */
1115 	         matbeg = 0;
1116 	         SCIP_CALL( SCIPlpiAddRows(lp, 1, &lhs, &rhs, NULL, cnt, &matbeg, matind, matval) );
1117 	
1118 	         SCIPfreeBufferArray(scip, &matind);
1119 	         SCIPfreeBufferArray(scip, &matval);
1120 	         SCIPfreeBufferArray(scip, &newvars);
1121 	
1122 	         assert( slackvar != NULL );
1123 	         if ( SCIPvarGetStatus(slackvar) == SCIP_VARSTATUS_AGGREGATED )
1124 	         {
1125 	            SCIPfreeBufferArray(scip, &linvals);
1126 	            SCIPfreeBufferArray(scip, &linvars);
1127 	         }
1128 	      }
1129 	   }
1130 	
1131 	   /* possibly handle additional linear constraints */
1132 	   if ( conshdlrdata->useotherconss )
1133 	   {
1134 	      /* get all linear constraints */
1135 	      conss = SCIPgetConss(scip);
1136 	      nconss = SCIPgetNConss(scip);
1137 	
1138 	      /* loop through constraints */
1139 	      for (c = 0; c < nconss; ++c)
1140 	      {
1141 	         SCIP_CONS* cons;
1142 	         SCIP_VAR** linvars;
1143 	         SCIP_Real* linvals;
1144 	         SCIP_Real linrhs;
1145 	         SCIP_Real linlhs;
1146 	         SCIP_Real* matval;
1147 	         SCIP_VAR** newvars;
1148 	         int nnewvars = 0;
1149 	         int* matind;
1150 	         int nlinvars;
1151 	         int matbeg = 0;
1152 	         int cnt = 0;
1153 	         int v;
1154 	
1155 	         cons = conss[c];
1156 	         assert( cons != NULL );
1157 	
1158 	         /* avoid non-active, local constraints */
1159 	         if ( ! SCIPconsIsEnabled(cons) || ! SCIPconsIsActive(cons) || SCIPconsIsLocal(cons) )
1160 	            continue;
1161 	
1162 	         /* check type of constraint (only take linear constraints) */
1163 	         if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "linear") != 0 )
1164 	            continue;
1165 	
1166 	         /* avoid adding linear constraints that correspond to indicator constraints */
1167 	         if ( strncmp(SCIPconsGetName(cons), "indlin", 6) == 0 )
1168 	            continue;
1169 	
1170 	         /* get data of linear constraint */
1171 	         linvars = SCIPgetVarsLinear(scip, cons);
1172 	         linvals = SCIPgetValsLinear(scip, cons);
1173 	         nlinvars = SCIPgetNVarsLinear(scip, cons);
1174 	         linlhs = SCIPgetLhsLinear(scip, cons);
1175 	         linrhs = SCIPgetRhsLinear(scip, cons);
1176 	
1177 	         /* reserve space */
1178 	         SCIP_CALL( SCIPallocBufferArray(scip, &matind, 4*nlinvars) );
1179 	         SCIP_CALL( SCIPallocBufferArray(scip, &matval, 4*nlinvars) );
1180 	         SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nlinvars) );
1181 	
1182 	         /* collect possibly new variables */
1183 	         for (v = 0; v < nlinvars; ++v)
1184 	         {
1185 	            SCIP_VAR* var;
1186 	            var = linvars[v];
1187 	            assert( var != NULL );
1188 	
1189 	            /* if variable is new */
1190 	            if ( ! SCIPhashmapExists(varhash, var) )
1191 	            {
1192 	               /* add variable in map */
1193 	               SCIP_CALL( SCIPhashmapInsertInt(varhash, var, nvars) );
1194 	               assert( nvars == SCIPhashmapGetImageInt(varhash, var) );
1195 	               /* SCIPdebugMsg(scip, "Inserted variable <%s> into hashmap (%d).\n", SCIPvarGetName(var), nvars); */
1196 	               nvars++;
1197 	
1198 	               /* store new variables */
1199 	               newvars[nnewvars++] = var;
1200 	            }
1201 	            assert( SCIPhashmapExists(varhash, var) );
1202 	         }
1203 	
1204 	         /* add new columns */
1205 	         if ( nnewvars > 0 )
1206 	         {
1207 	            SCIP_Real* lb;
1208 	            SCIP_Real* ub;
1209 	            SCIP_Real* obj;
1210 	            char** colnames;
1211 	
1212 	            SCIP_CALL( SCIPallocBufferArray(scip, &lb, nnewvars) );
1213 	            SCIP_CALL( SCIPallocBufferArray(scip, &ub, nnewvars) );
1214 	            SCIP_CALL( SCIPallocBufferArray(scip, &obj, nnewvars) );
1215 	            SCIP_CALL( SCIPallocBufferArray(scip, &colnames, nnewvars) );
1216 	
1217 	            for (v = 0; v < nnewvars; ++v)
1218 	            {
1219 	               SCIP_VAR* var;
1220 	               var = newvars[v];
1221 	               obj[v] = 0.0;
1222 	               lb[v] = SCIPvarGetLbLocal(var);
1223 	               ub[v] = SCIPvarGetUbLocal(var);
1224 	               SCIP_CALL( SCIPallocBufferArray(scip, &(colnames[v]), SCIP_MAXSTRLEN) ); /*lint !e866*/
1225 	               (void) SCIPsnprintf(colnames[v], SCIP_MAXSTRLEN, "%s", SCIPvarGetName(var));
1226 	            }
1227 	
1228 	            /* now add columns */
1229 	            SCIP_CALL( SCIPlpiAddCols(lp, nnewvars, obj, lb, ub, colnames, 0, NULL, NULL, NULL) );
1230 	
1231 	            for (v = nnewvars - 1; v >= 0; --v)
1232 	            {
1233 	               SCIPfreeBufferArray(scip, &(colnames[v]));
1234 	            }
1235 	            SCIPfreeBufferArray(scip, &colnames);
1236 	            SCIPfreeBufferArray(scip, &obj);
1237 	            SCIPfreeBufferArray(scip, &ub);
1238 	            SCIPfreeBufferArray(scip, &lb);
1239 	         }
1240 	
1241 	         /* set up row */
1242 	         for (v = 0; v < nlinvars; ++v)
1243 	         {
1244 	            SCIP_VAR* var;
1245 	            var = linvars[v];
1246 	            assert( var != NULL );
1247 	
1248 	            assert( SCIPhashmapExists(varhash, var) );
1249 	            matind[cnt] = SCIPhashmapGetImageInt(varhash, var);
1250 	            matval[cnt] = linvals[v];
1251 	            ++cnt;
1252 	         }
1253 	
1254 	         /* add new row */
1255 	         SCIP_CALL( SCIPlpiAddRows(lp, 1, &linlhs, &linrhs, NULL, cnt, &matbeg, matind, matval) );
1256 	
1257 	         SCIPfreeBufferArray(scip, &matind);
1258 	         SCIPfreeBufferArray(scip, &matval);
1259 	         SCIPfreeBufferArray(scip, &newvars);
1260 	      }
1261 	   }
1262 	
1263 	   /* solve LP and check status */
1264 	   SCIP_CALL( SCIPlpiSolvePrimal(lp) );
1265 	
1266 	   if ( ! SCIPlpiIsPrimalInfeasible(lp) )
1267 	   {
1268 	      SCIPerrorMessage("Detected IIS is not infeasible in original problem!\n");
1269 	
1270 	      SCIP_CALL( SCIPlpiWriteLP(lp, "check.lp") );
1271 	      SCIP_CALL( SCIPlpiWriteLP(conshdlrdata->altlp, "altdebug.lp") );
1272 	      SCIPABORT();
1273 	      return SCIP_ERROR; /*lint !e527*/
1274 	   }
1275 	   SCIPdebugMsg(scip, "Check successful!\n");
1276 	
1277 	   SCIPhashmapFree(&varhash);
1278 	   SCIP_CALL( SCIPlpiFree(&lp) );
1279 	
1280 	   return SCIP_OKAY;
1281 	}
1282 	#endif
1283 	
1284 	
1285 	/* ------------------------ auxiliary operations -------------------------------*/
1286 	
1287 	/** return objective contribution of variable
1288 	 *
1289 	 *  Special treatment of negated variables: return negative of objective of original
1290 	 *  variable. SCIPvarGetObj() would return 0 in these cases.
1291 	 */
1292 	static
1293 	SCIP_Real varGetObjDelta(
1294 	   SCIP_VAR*             var                 /**< variable */
1295 	   )
1296 	{
1297 	   if ( SCIPvarIsBinary(var) && SCIPvarIsNegated(var) )
1298 	   {
1299 	      assert( SCIPvarGetNegatedVar(var) != NULL );
1300 	      return -SCIPvarGetObj(SCIPvarGetNegatedVar(var));
1301 	   }
1302 	   else if ( SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED )
1303 	   {
1304 	      assert( SCIPvarGetAggrVar(var) != NULL );
1305 	      return SCIPvarGetAggrScalar(var) * SCIPvarGetObj(SCIPvarGetAggrVar(var));
1306 	   }
1307 	
1308 	   return SCIPvarGetObj(var);
1309 	}
1310 	
1311 	
1312 	/** ensures that the addlincons array can store at least num entries */
1313 	static
1314 	SCIP_RETCODE consdataEnsureAddLinConsSize(
1315 	   SCIP*                 scip,               /**< SCIP data structure */
1316 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
1317 	   int                   num                 /**< minimum number of entries to store */
1318 	   )
1319 	{
1320 	   SCIP_CONSHDLRDATA* conshdlrdata;
1321 	
1322 	   assert( scip != NULL );
1323 	   assert( conshdlr != NULL );
1324 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1325 	
1326 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
1327 	   assert( conshdlrdata != NULL );
1328 	   assert( conshdlrdata->naddlincons <= conshdlrdata->maxaddlincons );
1329 	
1330 	   if ( num > conshdlrdata->maxaddlincons )
1331 	   {
1332 	      int newsize;
1333 	
1334 	      newsize = SCIPcalcMemGrowSize(scip, num);
1335 	      SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->addlincons, conshdlrdata->maxaddlincons, newsize) );
1336 	      conshdlrdata->maxaddlincons = newsize;
1337 	   }
1338 	   assert( num <= conshdlrdata->maxaddlincons );
1339 	
1340 	   return SCIP_OKAY;
1341 	}
1342 	
1343 	
1344 	/* ------------------------ operations on the alternative LP -------------------*/
1345 	
1346 	/** initialize alternative LP
1347 	 *
1348 	 *  The alternative system is organized as follows:
1349 	 *  - The first row corresponds to the right hand side of the original system.
1350 	 *  - The next nconss constraints correspond to the slack variables.
1351 	 *  - The rows after that correspond to the original variables.
1352 	 */
1353 	static
1354 	SCIP_RETCODE initAlternativeLP(
1355 	   SCIP*                 scip,               /**< SCIP pointer */
1356 	   SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
1357 	   )
1358 	{
1359 	   SCIP_CONSHDLRDATA* conshdlrdata;
1360 	   SCIP_Real lhs = -1.0;
1361 	   SCIP_Real rhs = -1.0;
1362 	
1363 	   assert( scip != NULL );
1364 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1365 	
1366 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
1367 	   assert( conshdlrdata != NULL );
1368 	   assert( conshdlrdata->altlp == NULL );
1369 	   assert( conshdlrdata->varhash == NULL );
1370 	   assert( conshdlrdata->lbhash == NULL );
1371 	   assert( conshdlrdata->ubhash == NULL );
1372 	   assert( conshdlrdata->slackhash != NULL );
1373 	
1374 	   /* create hash map of variables */
1375 	   SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->varhash, SCIPblkmem(scip), SCIPgetNVars(scip)) );
1376 	   SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->lbhash, SCIPblkmem(scip), SCIPgetNVars(scip)) );
1377 	   SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->ubhash, SCIPblkmem(scip), SCIPgetNVars(scip)) );
1378 	
1379 	   /* create alternative LP */
1380 	   SCIP_CALL( SCIPlpiCreate(&conshdlrdata->altlp, SCIPgetMessagehdlr(scip), "altlp", SCIP_OBJSEN_MINIMIZE) );
1381 	
1382 	   /* add first row */
1383 	   SCIP_CALL( SCIPlpiAddRows(conshdlrdata->altlp, 1, &lhs, &rhs, NULL, 0, NULL, NULL, NULL) );
1384 	   conshdlrdata->nrows = 1;
1385 	
1386 	   /* set parameters */
1387 	   SCIP_CALL_PARAM( SCIPlpiSetIntpar(conshdlrdata->altlp, SCIP_LPPAR_FROMSCRATCH, FALSE) );
1388 	   SCIP_CALL_PARAM( SCIPlpiSetIntpar(conshdlrdata->altlp, SCIP_LPPAR_PRESOLVING, TRUE) );
1389 	   SCIP_CALL_PARAM( SCIPlpiSetIntpar(conshdlrdata->altlp, SCIP_LPPAR_SCALING, 1) );
1390 	   SCIP_CALL_PARAM( SCIPlpiSetIntpar(conshdlrdata->altlp, SCIP_LPPAR_FASTMIP, FALSE) );
1391 	
1392 	   SCIPdebugMsg(scip, "Initialized alternative LP.\n");
1393 	
1394 	   /* uncomment the following for debugging */
1395 	   /* SCIP_CALL_PARAM( SCIPlpiSetIntpar(conshdlrdata->altlp, SCIP_LPPAR_LPINFO, TRUE) ); */
1396 	
1397 	   return SCIP_OKAY;
1398 	}
1399 	
1400 	
1401 	/** check whether the bounds in given (alternative) LP are set correctly (for debugging) */
1402 	#ifndef NDEBUG
1403 	static
1404 	SCIP_RETCODE checkLPBoundsClean(
1405 	   SCIP*                 scip,               /**< SCIP pointer */
1406 	   SCIP_LPI*             lp,                 /**< LP for which bounds should be checked */
1407 	   int                   nconss,             /**< number of constraints */
1408 	   SCIP_CONS**           conss               /**< constraints */
1409 	   )
1410 	{
1411 	   SCIP_Real* lb;
1412 	   SCIP_Real* ub;
1413 	   SCIP_Bool* covered;
1414 	   int nCols;
1415 	   int j;
1416 	
1417 	   assert( scip != NULL );
1418 	   assert( lp != NULL );
1419 	
1420 	   SCIP_CALL( SCIPlpiGetNCols(lp, &nCols) );
1421 	
1422 	   SCIP_CALL( SCIPallocBufferArray(scip, &lb, nCols) );
1423 	   SCIP_CALL( SCIPallocBufferArray(scip, &ub, nCols) );
1424 	   SCIP_CALL( SCIPallocBufferArray(scip, &covered, nCols) );
1425 	
1426 	   for (j = 0; j < nCols; ++j)
1427 	      covered[j] = FALSE;
1428 	
1429 	   /* check columns used by constraints */
1430 	   SCIP_CALL( SCIPlpiGetBounds(lp, 0, nCols-1, lb, ub) );
1431 	   for (j = 0; j < nconss; ++j)
1432 	   {
1433 	      SCIP_CONSDATA* consdata;
1434 	      int ind;
1435 	
1436 	      assert( conss[j] != NULL );
1437 	      consdata = SCIPconsGetData(conss[j]);
1438 	      assert( consdata != NULL );
1439 	      ind = consdata->colindex;
1440 	
1441 	      if ( ind >= 0 )
1442 	      {
1443 	         assert( ind < nCols );
1444 	         covered[ind] = TRUE;
1445 	         if ( ! SCIPisFeasZero(scip, lb[ind]) || ! SCIPlpiIsInfinity(lp, ub[ind]) )
1446 	         {
1447 	            SCIPABORT();
1448 	         }
1449 	      }
1450 	   }
1451 	
1452 	   /* check other columns */
1453 	   for (j = 0; j < nCols; ++j)
1454 	   {
1455 	      if (! covered[j] )
1456 	      {
1457 	         /* some columns can be fixed to 0, since they correspond to disabled constraints */
1458 	         if ( ( ! SCIPlpiIsInfinity(lp, -lb[j]) && ! SCIPisFeasZero(scip, lb[j])) || (! SCIPlpiIsInfinity(lp, ub[j]) && ! SCIPisFeasZero(scip, ub[j])) )
1459 	         {
1460 	            SCIPABORT();
1461 	         }
1462 	      }
1463 	   }
1464 	
1465 	   SCIPfreeBufferArray(scip, &covered);
1466 	   SCIPfreeBufferArray(scip, &lb);
1467 	   SCIPfreeBufferArray(scip, &ub);
1468 	
1469 	   return SCIP_OKAY;
1470 	}
1471 	#endif
1472 	
1473 	
1474 	/** set the alternative system objective function
1475 	 *
1476 	 *  We assume that the objective function coefficients of the variables other than the binary
1477 	 *  indicators are always 0 and hence do not have to be changed.
1478 	 *
1479 	 *  We already use the tranformation \f$y' = 1 - y\f$.
1480 	 */
1481 	static
1482 	SCIP_RETCODE setAltLPObj(
1483 	   SCIP*                 scip,               /**< SCIP pointer */
1484 	   SCIP_LPI*             lp,                 /**< alternative LP */
1485 	   SCIP_SOL*             sol,                /**< solution to be dealt with */
1486 	   int                   nconss,             /**< number of constraints */
1487 	   SCIP_CONS**           conss               /**< indicator constraints */
1488 	   )
1489 	{
1490 	   int j;
1491 	   SCIP_Real* obj = NULL;
1492 	   int* indices = NULL;
1493 	   int cnt = 0;
1494 	
1495 	   assert( scip != NULL );
1496 	   assert( lp != NULL );
1497 	   assert( conss != NULL );
1498 	
1499 	   SCIP_CALL( SCIPallocBufferArray(scip, &obj, nconss) );
1500 	   SCIP_CALL( SCIPallocBufferArray(scip, &indices, nconss) );
1501 	
1502 	   for (j = 0; j < nconss; ++j)
1503 	   {
1504 	      SCIP_CONSDATA* consdata;
1505 	
1506 	      assert( conss[j] != NULL );
1507 	      consdata = SCIPconsGetData(conss[j]);
1508 	      assert( consdata != NULL );
1509 	
1510 	      if ( consdata->colindex >= 0 )
1511 	      {
1512 	         SCIP_Real val = SCIPgetSolVal(scip, sol, consdata->binvar);
1513 	         if ( SCIPisFeasEQ(scip, val, 1.0) )
1514 	            obj[cnt] = OBJEPSILON;      /* set objective to some small number to get small IISs */
1515 	         else
1516 	            obj[cnt] = 1.0 - val;
1517 	         indices[cnt++] = consdata->colindex;
1518 	      }
1519 	   }
1520 	
1521 	   if ( cnt > 0 )
1522 	   {
1523 	      SCIP_CALL( SCIPlpiChgObj(lp, cnt, indices, obj) );
1524 	   }
1525 	
1526 	   SCIPfreeBufferArray(scip, &indices);
1527 	   SCIPfreeBufferArray(scip, &obj);
1528 	
1529 	   return SCIP_OKAY;
1530 	}
1531 	
1532 	
1533 	/** set the alternative system objective function to some small value */
1534 	static
1535 	SCIP_RETCODE setAltLPObjZero(
1536 	   SCIP*                 scip,               /**< SCIP pointer */
1537 	   SCIP_LPI*             lp,                 /**< alternative LP */
1538 	   int                   nconss,             /**< number of constraints */
1539 	   SCIP_CONS**           conss               /**< indicator constraints */
1540 	   )
1541 	{
1542 	   int j;
1543 	   SCIP_Real* obj = NULL;
1544 	   int* indices = NULL;
1545 	   int cnt = 0;
1546 	
1547 	   assert( scip != NULL );
1548 	   assert( lp != NULL );
1549 	   assert( conss != NULL );
1550 	
1551 	   SCIP_CALL( SCIPallocBufferArray(scip, &obj, nconss) );
1552 	   SCIP_CALL( SCIPallocBufferArray(scip, &indices, nconss) );
1553 	
1554 	   for (j = 0; j < nconss; ++j)
1555 	   {
1556 	      SCIP_CONSDATA* consdata;
1557 	
1558 	      assert( conss[j] != NULL );
1559 	      consdata = SCIPconsGetData(conss[j]);
1560 	      assert( consdata != NULL );
1561 	
1562 	      if ( consdata->colindex >= 0 )
1563 	      {
1564 	         obj[cnt] = OBJEPSILON;
1565 	         indices[cnt++] = consdata->colindex;
1566 	      }
1567 	   }
1568 	
1569 	   if ( cnt > 0 )
1570 	   {
1571 	      SCIP_CALL( SCIPlpiChgObj(lp, cnt, indices, obj) );
1572 	   }
1573 	
1574 	   SCIPfreeBufferArray(scip, &indices);
1575 	   SCIPfreeBufferArray(scip, &obj);
1576 	
1577 	   return SCIP_OKAY;
1578 	}
1579 	
1580 	
1581 	/** fix variable given by @a S to 0 */
1582 	static
1583 	SCIP_RETCODE fixAltLPVariables(
1584 	   SCIP*                 scip,               /**< SCIP pointer */
1585 	   SCIP_LPI*             lp,                 /**< alternative LP */
1586 	   int                   nconss,             /**< number of constraints */
1587 	   SCIP_CONS**           conss,              /**< indicator constraints */
1588 	   SCIP_Bool*            S                   /**< bitset of variables */
1589 	   )
1590 	{
1591 	   SCIP_Real* lb = NULL;
1592 	   SCIP_Real* ub = NULL;
1593 	   int* indices = NULL;
1594 	   int cnt = 0;
1595 	   int j;
1596 	
1597 	   assert( scip != NULL );
1598 	   assert( lp != NULL );
1599 	   assert( conss != NULL );
1600 	
1601 	   SCIP_CALL( SCIPallocBufferArray(scip, &lb, nconss) );
1602 	   SCIP_CALL( SCIPallocBufferArray(scip, &ub, nconss) );
1603 	   SCIP_CALL( SCIPallocBufferArray(scip, &indices, nconss) );
1604 	
1605 	   /* collect bounds to be changed */
1606 	   for (j = 0; j < nconss; ++j)
1607 	   {
1608 	      SCIP_CONSDATA* consdata;
1609 	
1610 	      assert( conss[j] != NULL );
1611 	      consdata = SCIPconsGetData(conss[j]);
1612 	      assert( consdata != NULL );
1613 	
1614 	      if ( consdata->colindex >= 0 )
1615 	      {
1616 	         if ( S[j] )
1617 	         {
1618 	            indices[cnt] = consdata->colindex;
1619 	            lb[cnt] = 0.0;
1620 	            ub[cnt] = 0.0;
1621 	            ++cnt;
1622 	         }
1623 	      }
1624 	   }
1625 	
1626 	   /* change bounds */
1627 	   if ( cnt > 0 )
1628 	   {
1629 	      SCIP_CALL( SCIPlpiChgBounds(lp, cnt, indices, lb, ub) );
1630 	   }
1631 	
1632 	   SCIPfreeBufferArray(scip, &indices);
1633 	   SCIPfreeBufferArray(scip, &ub);
1634 	   SCIPfreeBufferArray(scip, &lb);
1635 	
1636 	   return SCIP_OKAY;
1637 	}
1638 	
1639 	
1640 	/** fix variable @a ind to 0 */
1641 	static
1642 	SCIP_RETCODE fixAltLPVariable(
1643 	   SCIP_LPI*             lp,                 /**< alternative LP */
1644 	   int                   ind                 /**< variable that should be fixed to 0 */
1645 	   )
1646 	{
1647 	   SCIP_Real lb = 0.0;
1648 	   SCIP_Real ub = 0.0;
1649 	
1650 	   /* change bounds */
1651 	   SCIP_CALL( SCIPlpiChgBounds(lp, 1, &ind, &lb, &ub) );
1652 	
1653 	   return SCIP_OKAY;
1654 	}
1655 	
1656 	
1657 	/** unfix variable @a ind to 0 */
1658 	static
1659 	SCIP_RETCODE unfixAltLPVariable(
1660 	   SCIP_LPI*             lp,                 /**< alternative LP */
1661 	   int                   ind                 /**< variable that should be fixed to 0 */
1662 	   )
1663 	{
1664 	   SCIP_Real lb = 0.0;
1665 	   SCIP_Real ub = SCIPlpiInfinity(lp);
1666 	
1667 	   /* change bounds */
1668 	   SCIP_CALL( SCIPlpiChgBounds(lp, 1, &ind, &lb, &ub) );
1669 	
1670 	   return SCIP_OKAY;
1671 	}
1672 	
1673 	/** unfix variable given by @a S to 0 */
1674 	static
1675 	SCIP_RETCODE unfixAltLPVariables(
1676 	   SCIP*                 scip,               /**< SCIP pointer */
1677 	   SCIP_LPI*             lp,                 /**< alternative LP */
1678 	   int                   nconss,             /**< number of constraints */
1679 	   SCIP_CONS**           conss,              /**< indicator constraints */
1680 	   SCIP_Bool*            S                   /**< bitset of variables */
1681 	   )
1682 	{
1683 	   SCIP_Real* lb = NULL;
1684 	   SCIP_Real* ub = NULL;
1685 	   int* indices = NULL;
1686 	   int cnt = 0;
1687 	   int j;
1688 	
1689 	   assert( scip != NULL );
1690 	   assert( lp != NULL );
1691 	   assert( conss != NULL );
1692 	
1693 	   SCIP_CALL( SCIPallocBufferArray(scip, &lb, nconss) );
1694 	   SCIP_CALL( SCIPallocBufferArray(scip, &ub, nconss) );
1695 	   SCIP_CALL( SCIPallocBufferArray(scip, &indices, nconss) );
1696 	
1697 	   /* collect bounds to be changed */
1698 	   for (j = 0; j < nconss; ++j)
1699 	   {
1700 	      if ( S[j] )
1701 	      {
1702 	         SCIP_CONSDATA* consdata;
1703 	
1704 	         assert( conss[j] != NULL );
1705 	         consdata = SCIPconsGetData(conss[j]);
1706 	         assert( consdata != NULL );
1707 	
1708 	         if ( consdata->colindex >= 0 )
1709 	         {
1710 	            indices[cnt] = consdata->colindex;
1711 	            lb[cnt] = 0.0;
1712 	            ub[cnt] = SCIPlpiInfinity(lp);
1713 	            ++cnt;
1714 	         }
1715 	      }
1716 	   }
1717 	
1718 	   /* change bounds */
1719 	   if ( cnt > 0 )
1720 	   {
1721 	      SCIP_CALL( SCIPlpiChgBounds(lp, cnt, indices, lb, ub) );
1722 	   }
1723 	
1724 	   SCIPfreeBufferArray(scip, &indices);
1725 	   SCIPfreeBufferArray(scip, &ub);
1726 	   SCIPfreeBufferArray(scip, &lb);
1727 	
1728 	   return SCIP_OKAY;
1729 	}
1730 	
1731 	
1732 	/** update bounds in first row to the current ones */
1733 	static
1734 	SCIP_RETCODE updateFirstRow(
1735 	   SCIP*                 scip,               /**< SCIP pointer */
1736 	   SCIP_CONSHDLRDATA*    conshdlrdata        /**< constraint handler */
1737 	   )
1738 	{
1739 	   SCIP_HASHMAP* lbhash;
1740 	   SCIP_HASHMAP* ubhash;
1741 	   SCIP_VAR** vars;
1742 	   SCIP_LPI* altlp;
1743 	   int nvars;
1744 	   int cnt;
1745 	   int v;
1746 	
1747 	   assert( scip != NULL );
1748 	   assert( conshdlrdata != NULL );
1749 	
1750 	   altlp = conshdlrdata->altlp;
1751 	   lbhash = conshdlrdata->lbhash;
1752 	   ubhash = conshdlrdata->ubhash;
1753 	   assert( lbhash != NULL && ubhash != NULL );
1754 	
1755 	   /* check all variables */
1756 	   vars = SCIPgetVars(scip);
1757 	   nvars = SCIPgetNVars(scip);
1758 	   cnt = 0;
1759 	
1760 	   for (v = 0; v < nvars; ++v)
1761 	   {
1762 	      SCIP_VAR* var;
1763 	      var = vars[v];
1764 	      if ( SCIPhashmapExists(lbhash, var) )
1765 	      {
1766 	         int col;
1767 	
1768 	         col = SCIPhashmapGetImageInt(lbhash, var);
1769 	         SCIP_CALL( SCIPlpiChgCoef(altlp, 0, col, -SCIPvarGetLbLocal(var)) );
1770 	         if ( ! SCIPisEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetLbGlobal(var)) )
1771 	            ++cnt;
1772 	      }
1773 	      if ( SCIPhashmapExists(ubhash, var) )
1774 	      {
1775 	         int col;
1776 	
1777 	         col = SCIPhashmapGetImageInt(ubhash, var);
1778 	         SCIP_CALL( SCIPlpiChgCoef(altlp, 0, col, SCIPvarGetUbLocal(var)) );
1779 	         if ( ! SCIPisEQ(scip, SCIPvarGetUbLocal(var), SCIPvarGetUbGlobal(var)) )
1780 	            ++cnt;
1781 	      }
1782 	   }
1783 	   if ( cnt > 10 )
1784 	   {
1785 	      /* possible force a rescaling: */
1786 	      conshdlrdata->scaled = FALSE;
1787 	
1788 	      /* SCIP_CALL( SCIPlpiWriteLP(altlp, "altChg.lp") ); */
1789 	      SCIPdebugMsg(scip, "Updated bounds of original variables: %d.\n", cnt);
1790 	   }
1791 	
1792 	   return SCIP_OKAY;
1793 	}
1794 	
1795 	
1796 	/** update bounds in first row to the global bounds */
1797 	static
1798 	SCIP_RETCODE updateFirstRowGlobal(
1799 	   SCIP*                 scip,               /**< SCIP pointer */
1800 	   SCIP_CONSHDLRDATA*    conshdlrdata        /**< constraint handler */
1801 	   )
1802 	{
1803 	   SCIP_HASHMAP* lbhash;
1804 	   SCIP_HASHMAP* ubhash;
1805 	   SCIP_VAR** vars;
1806 	   SCIP_LPI* altlp;
1807 	   int nvars;
1808 	   int cnt;
1809 	   int v;
1810 	
1811 	   assert( scip != NULL );
1812 	   assert( conshdlrdata != NULL );
1813 	
1814 	   altlp = conshdlrdata->altlp;
1815 	   lbhash = conshdlrdata->lbhash;
1816 	   ubhash = conshdlrdata->ubhash;
1817 	   assert( lbhash != NULL && ubhash != NULL );
1818 	
1819 	   /* check all variables */
1820 	   vars = SCIPgetVars(scip);
1821 	   nvars = SCIPgetNVars(scip);
1822 	   cnt = 0;
1823 	
1824 	   for (v = 0; v < nvars; ++v)
1825 	   {
1826 	      SCIP_VAR* var;
1827 	      int col;
1828 	
1829 	      var = vars[v];
1830 	      if ( SCIPhashmapExists(lbhash, var) )
1831 	      {
1832 	         col = SCIPhashmapGetImageInt(lbhash, var);
1833 	         SCIP_CALL( SCIPlpiChgCoef(altlp, 0, col, -SCIPvarGetLbGlobal(var)) );
1834 	         ++cnt;
1835 	      }
1836 	      if ( SCIPhashmapExists(ubhash, var) )
1837 	      {
1838 	         col = SCIPhashmapGetImageInt(ubhash, var);
1839 	         SCIP_CALL( SCIPlpiChgCoef(altlp, 0, col, SCIPvarGetUbGlobal(var)) );
1840 	         ++cnt;
1841 	      }
1842 	   }
1843 	
1844 	   if ( cnt > 0 )
1845 	   {
1846 	      /* SCIP_CALL( SCIPlpiWriteLP(altlp, "altChg.lp") ); */
1847 	      SCIPdebugMsg(scip, "Updated bounds of original variables: %d.\n", cnt);
1848 	   }
1849 	
1850 	   /* possible force a rescaling: */
1851 	   /* conshdlrdata->scaled = FALSE; */
1852 	
1853 	   return SCIP_OKAY;
1854 	}
1855 	
1856 	
1857 	/** check whether IIS defined by @a vector corresponds to a local cut */
1858 	static
1859 	SCIP_RETCODE checkIISlocal(
1860 	   SCIP*                 scip,               /**< SCIP pointer */
1861 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler */
1862 	   SCIP_Real*            vector,             /**< solution to alternative LP defining IIS */
1863 	   SCIP_Bool*            isLocal             /**< whether the IIS uses local bounds different from the global ones */
1864 	   )
1865 	{
1866 	   SCIP_HASHMAP* lbhash;
1867 	   SCIP_HASHMAP* ubhash;
1868 	   SCIP_VAR** vars;
1869 	#ifndef NDEBUG
1870 	   int nCols;
1871 	#endif
1872 	   int nvars;
1873 	   int v;
1874 	
1875 	   assert( scip != NULL );
1876 	   assert( conshdlrdata != NULL );
1877 	   assert( vector != NULL );
1878 	   assert( isLocal != NULL );
1879 	
1880 	   *isLocal = FALSE;
1881 	
1882 	#ifndef NDEBUG
1883 	   SCIP_CALL( SCIPlpiGetNCols(conshdlrdata->altlp, &nCols) );
1884 	#endif
1885 	
1886 	   lbhash = conshdlrdata->lbhash;
1887 	   ubhash = conshdlrdata->ubhash;
1888 	   assert( lbhash != NULL && ubhash != NULL );
1889 	
1890 	   /* get all variables */
1891 	   vars = SCIPgetVars(scip);
1892 	   nvars = SCIPgetNVars(scip);
1893 	
1894 	   /* check all variables */
1895 	   for (v = 0; v < nvars; ++v)
1896 	   {
1897 	      SCIP_VAR* var;
1898 	      var = vars[v];
1899 	
1900 	      /* if local bound is different from global bound */
1901 	      if ( ! SCIPisEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetLbGlobal(var)) )
1902 	      {
1903 	         /* check whether the variable corresponding to the lower bounds has been used */
1904 	         if ( SCIPhashmapExists(lbhash, var) )
1905 	         {
1906 	            int col;
1907 	
1908 	            col = SCIPhashmapGetImageInt(lbhash, var);
1909 	            assert( 0 <= col && col < nCols );
1910 	            if ( ! SCIPisFeasZero(scip, vector[col]) )
1911 	            {
1912 	               *isLocal = TRUE;
1913 	               return SCIP_OKAY;
1914 	            }
1915 	         }
1916 	      }
1917 	
1918 	      /* if local bound is different from global bound */
1919 	      if ( ! SCIPisEQ(scip, SCIPvarGetUbLocal(var), SCIPvarGetUbGlobal(var)) )
1920 	      {
1921 	         /* check whether the variable corresponding to the upper bounds has been used */
1922 	         if ( SCIPhashmapExists(ubhash, var) )
1923 	         {
1924 	            int col;
1925 	
1926 	            col = SCIPhashmapGetImageInt(ubhash, var);
1927 	            assert( 0 <= col && col < nCols );
1928 	            if ( ! SCIPisFeasZero(scip, vector[col]) )
1929 	            {
1930 	               *isLocal = TRUE;
1931 	               return SCIP_OKAY;
1932 	            }
1933 	         }
1934 	      }
1935 	   }
1936 	
1937 	   return SCIP_OKAY;
1938 	}
1939 	
1940 	
1941 	/** compute scaling for first row
1942 	 *
1943 	 *  If the coefficients in the first row are large, a right hand side of -1 might not be
1944 	 *  adequate. Here, we replace the right hand side by the sum of the coefficients divided by the
1945 	 *  number of nonzeros.
1946 	 */
1947 	static
1948 	SCIP_RETCODE scaleFirstRow(
1949 	   SCIP*                 scip,               /**< SCIP pointer */
1950 	   SCIP_CONSHDLRDATA*    conshdlrdata        /**< constraint handler */
1951 	   )
1952 	{
1953 	   assert( scip != NULL );
1954 	   assert( conshdlrdata != NULL );
1955 	
1956 	   if ( ! conshdlrdata->scaled )
1957 	   {
1958 	      SCIP_Real* val;
1959 	      SCIP_LPI* altlp;
1960 	      int* ind;
1961 	      SCIP_Real sum = 0.0;
1962 	      int beg[1];
1963 	      int nCols;
1964 	      int cnt;
1965 	      int j;
1966 	
1967 	      altlp = conshdlrdata->altlp;
1968 	      SCIP_CALL( SCIPlpiGetNCols(altlp, &nCols) );
1969 	      SCIP_CALL( SCIPallocBufferArray(scip, &ind, nCols) );
1970 	      SCIP_CALL( SCIPallocBufferArray(scip, &val, nCols) );
1971 	
1972 	      SCIP_CALL( SCIPlpiGetRows(altlp, 0, 0, NULL, NULL, &cnt, beg, ind, val) );
1973 	
1974 	      if ( cnt > 0 )
1975 	      {
1976 	         /* compute sum */
1977 	         for (j = 0; j < cnt; ++j)
1978 	            sum += REALABS(val[j]);
1979 	
1980 	         /* set rhs */
1981 	         sum = - REALABS(sum) / ((double) cnt);
1982 	         j = 0;
1983 	         SCIP_CALL( SCIPlpiChgSides(altlp, 1, &j, &sum, &sum) );
1984 	      }
1985 	
1986 	      SCIPfreeBufferArray(scip, &val);
1987 	      SCIPfreeBufferArray(scip, &ind);
1988 	
1989 	      conshdlrdata->scaled = TRUE;
1990 	   }
1991 	
1992 	   return SCIP_OKAY;
1993 	}
1994 	
1995 	
1996 	/** add column to alternative LP
1997 	 *
1998 	 *  See the description at the top of the file for more information.
1999 	 */
2000 	static
2001 	SCIP_RETCODE addAltLPColumn(
2002 	   SCIP*                 scip,               /**< SCIP pointer */
2003 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2004 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< data of constraint handler */
2005 	   SCIP_VAR*             slackvar,           /**< slack variable or NULL */
2006 	   int                   nvars,              /**< number of variables in column */
2007 	   SCIP_VAR**            vars,               /**< variables for column */
2008 	   SCIP_Real*            vals,               /**< values for column */
2009 	   SCIP_Real             rhscoef,            /**< coefficient for first row */
2010 	   SCIP_Real             objcoef,            /**< objective in alternative LP */
2011 	   SCIP_Real             sign,               /**< sign (+1,-1) for column */
2012 	   SCIP_Bool             colfree,            /**< whether column should be free, e.g., for equations */
2013 	   int*                  colindex            /**< index of new column (return value) */
2014 	   )
2015 	{
2016 	   SCIP_VAR** newvars;
2017 	   SCIP_Real val;
2018 	   SCIP_Real* matval;
2019 	   SCIP_Bool* newrowsslack;
2020 	   SCIP_Real* obj;
2021 	   SCIP_Real* lb;
2022 	   SCIP_Real* ub;
2023 	   int* matbeg;
2024 	   int* matind;
2025 	   int nnewvars = 0;
2026 	   int nnewcols = 0;
2027 	   int nnewrows = 0;
2028 	   int ncols = 0;
2029 	   int cnt = 0;
2030 	   int v;
2031 	
2032 	   assert( scip != NULL );
2033 	   assert( conshdlrdata != NULL );
2034 	   assert( vars != NULL || nvars == 0 );
2035 	   assert( vals != NULL || nvars == 0 );
2036 	   assert( ! SCIPisInfinity(scip, rhscoef) && ! SCIPisInfinity(scip, -rhscoef) );
2037 	   assert( SCIPisEQ(scip, sign, 1.0) || SCIPisEQ(scip, sign, -1.0) );
2038 	   assert( colindex != NULL );
2039 	
2040 	   *colindex = -1;
2041 	
2042 	   if ( conshdlrdata->altlp == NULL )
2043 	   {
2044 	      SCIP_CALL( initAlternativeLP(scip, conshdlr) );
2045 	   }
2046 	   assert( conshdlrdata->altlp != NULL );
2047 	   assert( conshdlrdata->varhash != NULL );
2048 	   assert( conshdlrdata->lbhash != NULL );
2049 	   assert( conshdlrdata->ubhash != NULL );
2050 	   assert( conshdlrdata->slackhash != NULL );
2051 	
2052 	#ifndef NDEBUG
2053 	   {
2054 	      int nrows;
2055 	      SCIP_CALL( SCIPlpiGetNRows(conshdlrdata->altlp, &nrows) );
2056 	      assert( nrows == conshdlrdata->nrows );
2057 	   }
2058 	#endif
2059 	
2060 	   /* set up data for construction */
2061 	   SCIP_CALL( SCIPallocBufferArray(scip, &matbeg, nvars) );
2062 	   SCIP_CALL( SCIPallocBufferArray(scip, &matind, 4 * nvars) );
2063 	   SCIP_CALL( SCIPallocBufferArray(scip, &matval, 4 * nvars) );
2064 	   SCIP_CALL( SCIPallocBufferArray(scip, &obj, 2 * nvars) );
2065 	   SCIP_CALL( SCIPallocBufferArray(scip, &lb, 2 * nvars) );
2066 	   SCIP_CALL( SCIPallocBufferArray(scip, &ub, 2 * nvars) );
2067 	   SCIP_CALL( SCIPallocBufferArray(scip, &newvars, nvars) );
2068 	   SCIP_CALL( SCIPallocBufferArray(scip, &newrowsslack, 2 * nvars) );
2069 	
2070 	   /* store index of column in constraint */
2071 	   /* coverity[var_deref_model] */
2072 	   SCIP_CALL( SCIPlpiGetNCols(conshdlrdata->altlp, &ncols) );
2073 	   *colindex = ncols;
2074 	
2075 	   /* handle first row */
2076 	   if ( ! SCIPisFeasZero(scip, rhscoef) )
2077 	   {
2078 	      matind[cnt] = 0;
2079 	      matval[cnt++] = sign * rhscoef;
2080 	   }
2081 	
2082 	   /* set up column (recognize new original variables) */
2083 	   for (v = 0; v < nvars; ++v)
2084 	   {
2085 	      SCIP_VAR* var;
2086 	
2087 	      var = vars[v];
2088 	      assert( var != NULL );
2089 	
2090 	      /* if variable is a slack variable */
2091 	      if ( SCIPhashmapExists(conshdlrdata->slackhash, var) )
2092 	      {
2093 	         /* to avoid trivial rows: only add row corresponding to slack variable if it appears outside its own constraint */
2094 	         if ( var != slackvar )
2095 	         {
2096 	            int ind;
2097 	
2098 	            ind = SCIPhashmapGetImageInt(conshdlrdata->slackhash, var);
2099 	
2100 	            if ( ind < INT_MAX )
2101 	               matind[cnt] = ind;
2102 	            else
2103 	            {
2104 	               /* correct number of variable already in map/array and remember to add a new row */
2105 	               SCIP_CALL( SCIPhashmapSetImageInt(conshdlrdata->slackhash, var, conshdlrdata->nrows) );
2106 	               assert( conshdlrdata->nrows == SCIPhashmapGetImageInt(conshdlrdata->slackhash, var) );
2107 	               SCIPdebugMsg(scip, "Inserted slack variable <%s> into hashmap (row: %d).\n", SCIPvarGetName(var), conshdlrdata->nrows);
2108 	               matind[cnt] = (conshdlrdata->nrows)++;
2109 	
2110 	               /* store new variables */
2111 	               newrowsslack[nnewrows++] = TRUE;
2112 	            }
2113 	            assert( conshdlrdata->nrows >= SCIPhashmapGetImageInt(conshdlrdata->slackhash, var) );
2114 	            matval[cnt++] = sign * vals[v];
2115 	         }
2116 	      }
2117 	      else
2118 	      {
2119 	         /* if variable exists */
2120 	         if ( SCIPhashmapExists(conshdlrdata->varhash, var) )
2121 	            matind[cnt] = SCIPhashmapGetImageInt(conshdlrdata->varhash, var);
2122 	         else
2123 	         {
2124 	            /* add variable in map and array and remember to add a new row */
2125 	            SCIP_CALL( SCIPhashmapInsertInt(conshdlrdata->varhash, var, conshdlrdata->nrows) );
2126 	            assert( conshdlrdata->nrows == SCIPhashmapGetImageInt(conshdlrdata->varhash, var) );
2127 	            SCIPdebugMsg(scip, "Inserted variable <%s> into hashmap (row: %d).\n", SCIPvarGetName(var), conshdlrdata->nrows);
2128 	            matind[cnt] = (conshdlrdata->nrows)++;
2129 	
2130 	            /* store new variables */
2131 	            newrowsslack[nnewrows++] = FALSE;
2132 	            newvars[nnewvars++] = var;
2133 	         }
2134 	         assert( SCIPhashmapExists(conshdlrdata->varhash, var) );
2135 	         matval[cnt++] = sign * vals[v];
2136 	      }
2137 	   }
2138 	
2139 	   /* add new rows */
2140 	   if ( nnewrows > 0 )
2141 	   {
2142 	      SCIP_Real* lhs;
2143 	      SCIP_Real* rhs;
2144 	      int i;
2145 	
2146 	      SCIP_CALL( SCIPallocBufferArray(scip, &lhs, nnewrows) );
2147 	      SCIP_CALL( SCIPallocBufferArray(scip, &rhs, nnewrows) );
2148 	      for (i = 0; i < nnewrows; ++i)
2149 	      {
2150 	         if ( newrowsslack[i] )
2151 	            lhs[i] = -SCIPlpiInfinity(conshdlrdata->altlp);
2152 	         else
2153 	            lhs[i] = 0.0;
2154 	         rhs[i] = 0.0;
2155 	      }
2156 	      /* add new rows */
2157 	      SCIP_CALL( SCIPlpiAddRows(conshdlrdata->altlp, nnewrows, lhs, rhs, NULL, 0, NULL, NULL, NULL) );
2158 	
2159 	      SCIPfreeBufferArray(scip, &lhs);
2160 	      SCIPfreeBufferArray(scip, &rhs);
2161 	   }
2162 	
2163 	   /* now add column */
2164 	   obj[0] = objcoef;
2165 	   if ( colfree )
2166 	   {
2167 	      /* create a free variable -> should only happen for additional linear constraints */
2168 	      assert( slackvar == NULL );
2169 	      lb[0] = -SCIPlpiInfinity(conshdlrdata->altlp);
2170 	   }
2171 	   else
2172 	      lb[0] = 0.0;
2173 	   ub[0] = SCIPlpiInfinity(conshdlrdata->altlp);
2174 	   matbeg[0] = 0;
2175 	
2176 	   SCIP_CALL( SCIPlpiAddCols(conshdlrdata->altlp, 1, obj, lb, ub, NULL, cnt, matbeg, matind, matval) );
2177 	
2178 	   /* add columns corresponding to bounds of original variables - no bounds needed for slack vars */
2179 	   cnt = 0;
2180 	   for (v = 0; v < nnewvars; ++v)
2181 	   {
2182 	      SCIP_VAR* var = newvars[v];
2183 	      assert( var != NULL );
2184 	
2185 	      /* if the lower bound is finite */
2186 	      val  = SCIPvarGetLbGlobal(var);
2187 	      if ( ! SCIPisInfinity(scip, -val) )
2188 	      {
2189 	         matbeg[nnewcols] = cnt;
2190 	         if ( ! SCIPisZero(scip, val) )
2191 	         {
2192 	            matind[cnt] = 0;
2193 	            matval[cnt++] = -val;
2194 	         }
2195 	         assert( SCIPhashmapExists(conshdlrdata->varhash, var) );
2196 	
2197 	         matind[cnt] = SCIPhashmapGetImageInt(conshdlrdata->varhash, var);
2198 	         matval[cnt++] = -1.0;
2199 	         obj[nnewcols] = 0.0;
2200 	         lb[nnewcols] = 0.0;
2201 	         ub[nnewcols] = SCIPlpiInfinity(conshdlrdata->altlp);
2202 	         ++conshdlrdata->nlbbounds;
2203 	
2204 	         SCIP_CALL( SCIPhashmapInsertInt(conshdlrdata->lbhash, var, ncols + 1 + nnewcols) );
2205 	         assert( SCIPhashmapExists(conshdlrdata->lbhash, var) );
2206 	         SCIPdebugMsg(scip, "Added column for lower bound (%f) of variable <%s> to alternative polyhedron (col: %d).\n",
2207 	            val, SCIPvarGetName(var), ncols + 1 + nnewcols);
2208 	         ++nnewcols;
2209 	      }
2210 	
2211 	      /* if the upper bound is finite */
2212 	      val = SCIPvarGetUbGlobal(var);
2213 	      if ( ! SCIPisInfinity(scip, val) )
2214 	      {
2215 	         matbeg[nnewcols] = cnt;
2216 	         if ( ! SCIPisZero(scip, val) )
2217 	         {
2218 	            matind[cnt] = 0;
2219 	            matval[cnt++] = val;
2220 	         }
2221 	         assert( SCIPhashmapExists(conshdlrdata->varhash, var) );
2222 	
2223 	         matind[cnt] = SCIPhashmapGetImageInt(conshdlrdata->varhash, var);
2224 	         matval[cnt++] = 1.0;
2225 	         obj[nnewcols] = 0.0;
2226 	         lb[nnewcols] = 0.0;
2227 	         ub[nnewcols] = SCIPlpiInfinity(conshdlrdata->altlp);
2228 	         ++conshdlrdata->nubbounds;
2229 	
2230 	         SCIP_CALL( SCIPhashmapInsertInt(conshdlrdata->ubhash, var, ncols + 1 + nnewcols) );
2231 	         assert( SCIPhashmapExists(conshdlrdata->ubhash, var) );
2232 	         SCIPdebugMsg(scip, "Added column for upper bound (%f) of variable <%s> to alternative polyhedron (col: %d).\n",
2233 	            val, SCIPvarGetName(var), ncols + 1 + nnewcols);
2234 	         ++nnewcols;
2235 	      }
2236 	   }
2237 	
2238 	   /* add columns if necessary */
2239 	   if ( nnewcols > 0 )
2240 	   {
2241 	      SCIP_CALL( SCIPlpiAddCols(conshdlrdata->altlp, nnewcols, obj, lb, ub, NULL, cnt, matbeg, matind, matval) );
2242 	   }
2243 	
2244 	#ifndef NDEBUG
2245 	   SCIP_CALL( SCIPlpiGetNCols(conshdlrdata->altlp, &cnt) );
2246 	   assert( cnt == ncols + nnewcols + 1 );
2247 	#endif
2248 	
2249 	   SCIPfreeBufferArray(scip, &ub);
2250 	   SCIPfreeBufferArray(scip, &lb);
2251 	   SCIPfreeBufferArray(scip, &obj);
2252 	   SCIPfreeBufferArray(scip, &matind);
2253 	   SCIPfreeBufferArray(scip, &matval);
2254 	   SCIPfreeBufferArray(scip, &matbeg);
2255 	   SCIPfreeBufferArray(scip, &newvars);
2256 	   SCIPfreeBufferArray(scip, &newrowsslack);
2257 	
2258 	   conshdlrdata->scaled = FALSE;
2259 	
2260 	#ifdef SCIP_OUTPUT
2261 	   SCIP_CALL( SCIPlpiWriteLP(conshdlrdata->altlp, "alt.lp") );
2262 	#endif
2263 	
2264 	   return SCIP_OKAY;
2265 	}
2266 	
2267 	
2268 	/** add column corresponding to constraint to alternative LP
2269 	 *
2270 	 *  See the description at the top of the file for more information.
2271 	 */
2272 	static
2273 	SCIP_RETCODE addAltLPConstraint(
2274 	   SCIP*                 scip,               /**< SCIP pointer */
2275 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2276 	   SCIP_CONS*            lincons,            /**< linear constraint */
2277 	   SCIP_VAR*             slackvar,           /**< slack variable or NULL */
2278 	   SCIP_Real             objcoef,            /**< objective coefficient */
2279 	   int*                  colindex            /**< index of new column */
2280 	   )
2281 	{
2282 	   SCIP_CONSHDLRDATA* conshdlrdata;
2283 	   SCIP_VAR** linvars;
2284 	   SCIP_Real* linvals;
2285 	   SCIP_Real linrhs;
2286 	   SCIP_Real linlhs;
2287 	   int nlinvars;
2288 	
2289 	   assert( scip != NULL );
2290 	   assert( conshdlr != NULL );
2291 	   assert( lincons != NULL );
2292 	   assert( colindex != NULL );
2293 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2294 	
2295 	   *colindex = -1;
2296 	
2297 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
2298 	   assert( conshdlrdata != NULL );
2299 	
2300 	   /* if the slack variable is aggregated (multi-aggregation should not happen) */
2301 	   assert( slackvar == NULL || SCIPvarGetStatus(slackvar) != SCIP_VARSTATUS_MULTAGGR );
2302 	   if ( slackvar != NULL && SCIPvarGetStatus(slackvar) == SCIP_VARSTATUS_AGGREGATED )
2303 	   {
2304 	      SCIP_VAR* var;
2305 	      SCIP_Real scalar = 1.0;
2306 	      SCIP_Real constant = 0.0;
2307 	
2308 	      var = slackvar;
2309 	
2310 	      SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
2311 	
2312 	      SCIPdebugMsg(scip, "Slack variable is aggregated (scalar: %f, constant: %f).\n", scalar, constant);
2313 	
2314 	      /* if the slack variable is fixed */
2315 	      if ( SCIPisZero(scip, scalar) && ! SCIPconsIsActive(lincons) )
2316 	         return SCIP_OKAY;
2317 	
2318 	      /* otherwise construct a linear constraint */
2319 	      SCIP_CALL( SCIPallocBufferArray(scip, &linvars, 1) );
2320 	      SCIP_CALL( SCIPallocBufferArray(scip, &linvals, 1) );
2321 	      linvars[0] = var;
2322 	      linvals[0] = scalar;
2323 	      nlinvars = 1;
2324 	      linlhs = -SCIPinfinity(scip);
2325 	      linrhs = constant;
2326 	   }
2327 	   else
2328 	   {
2329 	      /* exit if linear constraint is not active */
2330 	      if ( ! SCIPconsIsActive(lincons) && slackvar != NULL )
2331 	         return SCIP_OKAY;
2332 	
2333 	      /* in this case, the linear constraint is directly usable */
2334 	      linvars = SCIPgetVarsLinear(scip, lincons);
2335 	      linvals = SCIPgetValsLinear(scip, lincons);
2336 	      nlinvars = SCIPgetNVarsLinear(scip, lincons);
2337 	      linlhs = SCIPgetLhsLinear(scip, lincons);
2338 	      linrhs = SCIPgetRhsLinear(scip, lincons);
2339 	   }
2340 	
2341 	   /* create column */
2342 	   if ( SCIPisEQ(scip, linlhs, linrhs) )
2343 	   {
2344 	      /* create free variable for equations (should only happen for additional linear constraints) */
2345 	      SCIP_CALL( addAltLPColumn(scip, conshdlr, conshdlrdata, slackvar, nlinvars, linvars, linvals, linrhs, objcoef, 1.0, TRUE, colindex) );
2346 	   }
2347 	   else if ( ! SCIPisInfinity(scip, linrhs) )
2348 	   {
2349 	      /* create column for rhs */
2350 	      SCIP_CALL( addAltLPColumn(scip, conshdlr, conshdlrdata, slackvar, nlinvars, linvars, linvals, linrhs, objcoef, 1.0, FALSE, colindex) );
2351 	   }
2352 	   else
2353 	   {
2354 	      /* create column for lhs */
2355 	      assert( ! SCIPisInfinity(scip, -linlhs) );
2356 	      SCIP_CALL( addAltLPColumn(scip, conshdlr, conshdlrdata, slackvar, nlinvars, linvars, linvals, linlhs, objcoef, -1.0, FALSE, colindex) );
2357 	   }
2358 	
2359 	   if ( slackvar != NULL && SCIPvarGetStatus(slackvar) == SCIP_VARSTATUS_AGGREGATED )
2360 	   {
2361 	      SCIPfreeBufferArray(scip, &linvals);
2362 	      SCIPfreeBufferArray(scip, &linvars);
2363 	   }
2364 	
2365 	   return SCIP_OKAY;
2366 	}
2367 	
2368 	
2369 	/** add column corresponding to row to alternative LP
2370 	 *
2371 	 *  See the description at the top of the file for more information.
2372 	 */
2373 	static
2374 	SCIP_RETCODE addAltLPRow(
2375 	   SCIP*                 scip,               /**< SCIP pointer */
2376 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2377 	   SCIP_ROW*             row,                /**< row to add */
2378 	   SCIP_Real             objcoef,            /**< objective coefficient */
2379 	   int*                  colindex            /**< index of new column */
2380 	   )
2381 	{
2382 	   SCIP_CONSHDLRDATA* conshdlrdata;
2383 	   SCIP_COL** rowcols;
2384 	   SCIP_Real* rowvals;
2385 	   SCIP_VAR** rowvars;
2386 	   SCIP_Real rowrhs;
2387 	   SCIP_Real rowlhs;
2388 	   int nrowcols;
2389 	   int j;
2390 	
2391 	   assert( scip != NULL );
2392 	   assert( conshdlr != NULL );
2393 	   assert( row != NULL );
2394 	   assert( colindex != NULL );
2395 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2396 	
2397 	   /* initialize data */
2398 	   *colindex = -1;
2399 	
2400 	   /* exit if row is not global */
2401 	   if ( SCIProwIsLocal(row) )
2402 	      return SCIP_OKAY;
2403 	
2404 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
2405 	   assert( conshdlrdata != NULL );
2406 	
2407 	   /* get row data */
2408 	   rowcols = SCIProwGetCols(row);
2409 	   rowvals = SCIProwGetVals(row);
2410 	   nrowcols = SCIProwGetNNonz(row);
2411 	   rowlhs = SCIProwGetLhs(row) - SCIProwGetConstant(row);
2412 	   rowrhs = SCIProwGetRhs(row) - SCIProwGetConstant(row);
2413 	
2414 	   SCIP_CALL( SCIPallocBufferArray(scip, &rowvars, nrowcols) );
2415 	   for (j = 0; j < nrowcols; ++j)
2416 	   {
2417 	      rowvars[j] = SCIPcolGetVar(rowcols[j]);
2418 	      assert( rowvars[j] != NULL );
2419 	   }
2420 	
2421 	   /* create column */
2422 	   if ( SCIPisEQ(scip, rowlhs, rowrhs) )
2423 	   {
2424 	      /* create free variable for equations (should only happen for additional linear constraints) */
2425 	      SCIP_CALL( addAltLPColumn(scip, conshdlr, conshdlrdata, NULL, nrowcols, rowvars, rowvals, rowrhs, objcoef, 1.0, TRUE, colindex) );
2426 	   }
2427 	   else if ( ! SCIPisInfinity(scip, rowrhs) )
2428 	   {
2429 	      /* create column for rhs */
2430 	      SCIP_CALL( addAltLPColumn(scip, conshdlr, conshdlrdata, NULL, nrowcols, rowvars, rowvals, rowrhs, objcoef, 1.0, FALSE, colindex) );
2431 	   }
2432 	   else
2433 	   {
2434 	      /* create column for lhs */
2435 	      assert( ! SCIPisInfinity(scip, -rowlhs) );
2436 	      SCIP_CALL( addAltLPColumn(scip, conshdlr, conshdlrdata, NULL, nrowcols, rowvars, rowvals, rowlhs, objcoef, -1.0, FALSE, colindex) );
2437 	   }
2438 	
2439 	   SCIPfreeBufferArray(scip, &rowvars);
2440 	
2441 	   return SCIP_OKAY;
2442 	}
2443 	
2444 	
2445 	/** try to add objective cut as column to alternative LP */
2446 	static
2447 	SCIP_RETCODE addObjcut(
2448 	   SCIP*                 scip,               /**< SCIP pointer */
2449 	   SCIP_CONSHDLR*        conshdlr            /**< constraint handler */
2450 	   )
2451 	{
2452 	   SCIP_CONSHDLRDATA* conshdlrdata;
2453 	   SCIP_VAR** objvars;
2454 	   SCIP_Real* objvals;
2455 	   SCIP_VAR** vars;
2456 	   int nobjvars = 0;
2457 	   int nvars;
2458 	   int v;
2459 	
2460 	   assert( scip != NULL );
2461 	   assert( conshdlr != NULL );
2462 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2463 	
2464 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
2465 	   assert( conshdlrdata != NULL );
2466 	
2467 	   /* skip procedure if already added */
2468 	   if ( conshdlrdata->objcutindex >= 0 )
2469 	      return SCIP_OKAY;
2470 	
2471 	   /* check whether we can add objective cut: all indicator variables have zero objective */
2472 	   if ( ! conshdlrdata->objothervarsonly )
2473 	      return SCIP_OKAY;
2474 	
2475 	   assert( ! SCIPisInfinity(scip, conshdlrdata->objupperbound) );
2476 	   SCIPdebugMsg(scip, "Add objective cut to alternative LP (obj. bound: %g).\n", conshdlrdata->objupperbound);
2477 	
2478 	   SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2479 	   SCIP_CALL( SCIPallocBufferArray(scip, &objvars, nvars) );
2480 	   SCIP_CALL( SCIPallocBufferArray(scip, &objvals, nvars) );
2481 	
2482 	   /* collect nonzeros */
2483 	   for (v = 0; v < nvars; ++v)
2484 	   {
2485 	      SCIP_VAR* var;
2486 	      SCIP_Real objval;
2487 	
2488 	      var = vars[v];
2489 	      assert( var != NULL );
2490 	      objval = SCIPvarGetObj(var);
2491 	
2492 	      /* skip variables with zero objective - this includes slack and indicator variables */
2493 	      if ( ! SCIPisZero(scip, objval) )
2494 	      {
2495 	         objvars[nobjvars] = var;
2496 	         objvals[nobjvars++] = objval;
2497 	      }
2498 	   }
2499 	
2500 	   /* create column (with rhs = upperbound, objective 0, and scaling factor 1.0) */
2501 	   SCIP_CALL( addAltLPColumn(scip, conshdlr, conshdlrdata, NULL, nobjvars, objvars, objvals, conshdlrdata->objupperbound, 0.0, 1.0, FALSE, &conshdlrdata->objcutindex) );
2502 	   assert( conshdlrdata->objcutindex >= 0 );
2503 	   conshdlrdata->objaltlpbound = conshdlrdata->objupperbound;
2504 	
2505 	   SCIPfreeBufferArray(scip, &objvals);
2506 	   SCIPfreeBufferArray(scip, &objvars);
2507 	
2508 	   return SCIP_OKAY;
2509 	}
2510 	
2511 	
2512 	/** delete column corresponding to constraint in alternative LP
2513 	 *
2514 	 *  We currently just fix the corresponding variable to 0.
2515 	 */
2516 	static
2517 	SCIP_RETCODE deleteAltLPConstraint(
2518 	   SCIP*                 scip,               /**< SCIP pointer */
2519 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2520 	   SCIP_CONS*            cons                /**< indicator constraint */
2521 	   )
2522 	{
2523 	   SCIP_CONSHDLRDATA* conshdlrdata;
2524 	
2525 	   assert( scip != NULL );
2526 	   assert( conshdlr != NULL );
2527 	   assert( cons != NULL );
2528 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2529 	
2530 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
2531 	   assert( conshdlrdata != NULL );
2532 	
2533 	   if ( conshdlrdata->altlp != NULL )
2534 	   {
2535 	      SCIP_CONSDATA* consdata;
2536 	
2537 	      consdata = SCIPconsGetData(cons);
2538 	      assert( consdata != NULL );
2539 	
2540 	      if ( consdata->colindex >= 0 )
2541 	      {
2542 	         SCIP_CALL( fixAltLPVariable(conshdlrdata->altlp, consdata->colindex) );
2543 	      }
2544 	      consdata->colindex = -1;
2545 	
2546 	      SCIPdebugMsg(scip, "Fixed variable for column %d (constraint: <%s>) from alternative LP to 0.\n", consdata->colindex, SCIPconsGetName(cons));
2547 	   }
2548 	   conshdlrdata->scaled = FALSE;
2549 	
2550 	   return SCIP_OKAY;
2551 	}
2552 	
2553 	
2554 	/** update upper bound in alternative LP */
2555 	static
2556 	SCIP_RETCODE updateObjUpperbound(
2557 	   SCIP*                 scip,               /**< SCIP pointer */
2558 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2559 	   SCIP_CONSHDLRDATA*    conshdlrdata        /**< constraint handler data */
2560 	   )
2561 	{
2562 	   SCIP_Real objbnd;
2563 	
2564 	   assert( scip != NULL );
2565 	   assert( conshdlrdata != NULL );
2566 	
2567 	   if ( ! conshdlrdata->useobjectivecut )
2568 	      return SCIP_OKAY;
2569 	
2570 	   if ( conshdlrdata->altlp == NULL )
2571 	      return SCIP_OKAY;
2572 	
2573 	   /* first check whether we can improve the upper bound */
2574 	   objbnd = SCIPgetUpperbound(scip);
2575 	   if ( ! SCIPisInfinity(scip, objbnd) )
2576 	   {
2577 	      if ( SCIPisObjIntegral(scip) )
2578 	         objbnd = SCIPfeasCeil(scip, objbnd) - (1.0 - SCIPcutoffbounddelta(scip));
2579 	      else
2580 	         objbnd -= SCIPcutoffbounddelta(scip);
2581 	
2582 	      if ( SCIPisLT(scip, objbnd, conshdlrdata->objupperbound) )
2583 	         conshdlrdata->objupperbound = objbnd;
2584 	   }
2585 	
2586 	   if ( SCIPisInfinity(scip, conshdlrdata->objupperbound) )
2587 	      return SCIP_OKAY;
2588 	
2589 	   /* if we can improve on the bound stored in the alternative LP */
2590 	   if ( SCIPisLT(scip, conshdlrdata->objupperbound, conshdlrdata->objaltlpbound) )
2591 	   {
2592 	      SCIPdebugMsg(scip, "Update objective bound to %g.\n", conshdlrdata->objupperbound);
2593 	
2594 	      /* possibly add column for objective cut */
2595 	      if ( conshdlrdata->objcutindex < 0 )
2596 	      {
2597 	         SCIP_CALL( addObjcut(scip, conshdlr) );
2598 	      }
2599 	      else
2600 	      {
2601 	#ifndef NDEBUG
2602 	         SCIP_Real oldbnd;
2603 	         SCIP_CALL( SCIPlpiGetCoef(conshdlrdata->altlp, 0, conshdlrdata->objcutindex, &oldbnd) );
2604 	         assert( SCIPisEQ(scip, oldbnd, conshdlrdata->objaltlpbound) );
2605 	#endif
2606 	
2607 	         /* update bound */
2608 	         SCIP_CALL( SCIPlpiChgCoef(conshdlrdata->altlp, 0, conshdlrdata->objcutindex, conshdlrdata->objupperbound) );
2609 	         conshdlrdata->objaltlpbound = conshdlrdata->objupperbound;
2610 	
2611 	#ifdef SCIP_OUTPUT
2612 	         SCIP_CALL( SCIPlpiWriteLP(conshdlrdata->altlp, "alt.lp") );
2613 	#endif
2614 	      }
2615 	   }
2616 	
2617 	   return SCIP_OKAY;
2618 	}
2619 	
2620 	
2621 	/** check whether the given LP is infeasible
2622 	 *
2623 	 *  If @a primal is false we assume that the problem is <em>dual feasible</em>, e.g., the problem
2624 	 *  was only changed by fixing bounds!
2625 	 *
2626 	 *  This is the workhorse for all methods that have to solve the alternative LP. We try in several
2627 	 *  ways to recover from possible stability problems.
2628 	 *
2629 	 *  @pre It is assumed that all parameters for the alternative LP are set.
2630 	 */
2631 	static
2632 	SCIP_RETCODE checkAltLPInfeasible(
2633 	   SCIP*                 scip,               /**< SCIP pointer */
2634 	   SCIP_LPI*             lp,                 /**< LP */
2635 	   SCIP_Real             maxcondition,       /**< maximal allowed condition of LP solution basis matrix */
2636 	   SCIP_Bool             primal,             /**< whether we are using the primal or dual simplex */
2637 	   SCIP_Bool*            infeasible,         /**< output: whether the LP is infeasible */
2638 	   SCIP_Bool*            error               /**< output: whether an error occurred */
2639 	   )
2640 	{
2641 	   SCIP_RETCODE retcode;
2642 	   SCIP_Real condition;
2643 	
2644 	   assert( scip != NULL );
2645 	   assert( lp != NULL );
2646 	   assert( infeasible != NULL );
2647 	   assert( error != NULL );
2648 	
2649 	   *error = FALSE;
2650 	
2651 	   /* solve LP */
2652 	   if ( primal )
2653 	      retcode = SCIPlpiSolvePrimal(lp);  /* use primal simplex */
2654 	   else
2655 	      retcode = SCIPlpiSolveDual(lp);    /* use dual simplex */
2656 	   if ( retcode == SCIP_LPERROR )
2657 	   {
2658 	      *error = TRUE;
2659 	      return SCIP_OKAY;
2660 	   }
2661 	   SCIP_CALL( retcode );
2662 	
2663 	   /* resolve if LP is not stable */
2664 	   if ( ! SCIPlpiIsStable(lp) )
2665 	   {
2666 	      SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_FROMSCRATCH, TRUE) );
2667 	      SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_PRESOLVING, FALSE) );
2668 	      SCIPwarningMessage(scip, "Numerical problems, retrying ...\n");
2669 	
2670 	      /* re-solve LP */
2671 	      if ( primal )
2672 	         retcode = SCIPlpiSolvePrimal(lp);  /* use primal simplex */
2673 	      else
2674 	         retcode = SCIPlpiSolveDual(lp);    /* use dual simplex */
2675 	
2676 	      /* reset parameters */
2677 	      SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_FROMSCRATCH, FALSE) );
2678 	      SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_PRESOLVING, TRUE) );
2679 	
2680 	      if ( retcode == SCIP_LPERROR )
2681 	      {
2682 	         *error = TRUE;
2683 	         return SCIP_OKAY;
2684 	      }
2685 	      SCIP_CALL( retcode );
2686 	   }
2687 	
2688 	   /* check whether we want to ignore the result, because the condition number is too large */
2689 	   if ( maxcondition > 0.0 )
2690 	   {
2691 	      /* check estimated condition number of basis matrix */
2692 	      SCIP_CALL( SCIPlpiGetRealSolQuality(lp, SCIP_LPSOLQUALITY_ESTIMCONDITION, &condition) );
2693 	      if ( condition != SCIP_INVALID && condition > maxcondition )  /*lint !e777*/
2694 	      {
2695 	         SCIPdebugMsg(scip, "Estimated condition number of basis matrix (%e) exceeds maximal allowance (%e).\n", condition, maxcondition);
2696 	
2697 	         *error = TRUE;
2698 	
2699 	         return SCIP_OKAY;
2700 	      }
2701 	      else if ( condition != SCIP_INVALID )  /*lint !e777*/
2702 	      {
2703 	         SCIPdebugMsg(scip, "Estimated condition number of basis matrix (%e) is below maximal allowance (%e).\n", condition, maxcondition);
2704 	      }
2705 	      else
2706 	      {
2707 	         SCIPdebugMsg(scip, "Estimated condition number of basis matrix not available.\n");
2708 	      }
2709 	   }
2710 	
2711 	   /* check whether we are in the paradoxical situation that
2712 	    * - the primal is not infeasible
2713 	    * - the primal is not unbounded
2714 	    * - the LP is not optimal
2715 	    * - we have a primal ray
2716 	    *
2717 	    * If we ran the dual simplex algorithm, then we run again with the primal simplex
2718 	    */
2719 	   if ( ! SCIPlpiIsPrimalInfeasible(lp) && ! SCIPlpiIsPrimalUnbounded(lp) &&
2720 	        ! SCIPlpiIsOptimal(lp) && SCIPlpiExistsPrimalRay(lp) && ! primal )
2721 	   {
2722 	      SCIPwarningMessage(scip, "The dual simplex produced a primal ray. Retrying with primal ...\n");
2723 	
2724 	      /* the following settings might be changed: */
2725 	      SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_FROMSCRATCH, TRUE) );
2726 	      SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_PRESOLVING, TRUE) );
2727 	      SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_SCALING, 1) );
2728 	
2729 	      SCIP_CALL( SCIPlpiSolvePrimal(lp) );   /* use primal simplex */
2730 	
2731 	      /* reset parameters */
2732 	      SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_FROMSCRATCH, FALSE) );
2733 	      SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_PRESOLVING, TRUE) );
2734 	      SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_SCALING, 1) );
2735 	   }
2736 	
2737 	   /* examine LP solution status */
2738 	   if ( SCIPlpiIsPrimalInfeasible(lp) )     /* the LP is provably infeasible */
2739 	   {
2740 	      assert( ! SCIPlpiIsPrimalUnbounded(lp) );   /* can't be unbounded or optimal */
2741 	      assert( ! SCIPlpiIsOptimal(lp) );           /* if it is infeasible! */
2742 	
2743 	      *infeasible = TRUE;                         /* LP is infeasible */
2744 	      return SCIP_OKAY;
2745 	   }
2746 	   else
2747 	   {
2748 	      /* By assumption the dual is feasible if the dual simplex is run, therefore
2749 	       * the status has to be primal unbounded or optimal. */
2750 	      if ( ! SCIPlpiIsPrimalUnbounded(lp) && ! SCIPlpiIsOptimal(lp) )
2751 	      {
2752 	         /* We have a status different from unbounded or optimal. This should not be the case ... */
2753 	         if (primal)
2754 	            SCIPwarningMessage(scip, "Primal simplex returned with unknown status: %d\n", SCIPlpiGetInternalStatus(lp));
2755 	         else
2756 	            SCIPwarningMessage(scip, "Dual simplex returned with unknown status: %d\n", SCIPlpiGetInternalStatus(lp));
2757 	
2758 	         /* SCIP_CALL( SCIPlpiWriteLP(lp, "debug.lp") ); */
2759 	         *error = TRUE;
2760 	         return SCIP_OKAY;
2761 	      }
2762 	   }
2763 	
2764 	   /* at this point we have a feasible solution */
2765 	   *infeasible = FALSE;
2766 	   return SCIP_OKAY;
2767 	}
2768 	
2769 	
2770 	/** tries to extend a given set of variables to a cover
2771 	 *
2772 	 *  At each step we include a variable which covers a new IIS. The corresponding IIS inequalities are added to the LP,
2773 	 *  if this not already happened.
2774 	 *
2775 	 *  @pre It is assumed that all parameters for the alternative LP are set and that the variables
2776 	 *  corresponding to @a S are fixed. Furthermore @c xVal_ should contain the current LP solution.
2777 	 */
2778 	static
2779 	SCIP_RETCODE extendToCover(
2780 	   SCIP*                 scip,               /**< SCIP pointer */
2781 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
2782 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
2783 	   SCIP_LPI*             lp,                 /**< LP */
2784 	   SCIP_SOL*             sol,                /**< solution to be separated */
2785 	   SCIP_ENFOSEPATYPE     enfosepatype,       /**< type of enforcing/separating type */
2786 	   SCIP_Bool             removable,          /**< whether cuts should be removable */
2787 	   SCIP_Bool             genlogicor,         /**< should logicor constraints be generated? */
2788 	   int                   nconss,             /**< number of constraints */
2789 	   SCIP_CONS**           conss,              /**< indicator constraints */
2790 	   SCIP_Bool*            S,                  /**< bitset of variables */
2791 	   int*                  size,               /**< size of S */
2792 	   SCIP_Real*            value,              /**< objective value of S */
2793 	   SCIP_Bool*            error,              /**< output: whether an error occurred */
2794 	   SCIP_Bool*            cutoff,             /**< whether we detected a cutoff by an infeasible inequality */
2795 	   int*                  nGen                /**< number of generated cuts */
2796 	   )
2797 	{
2798 	#ifdef SCIP_DEBUG
2799 	   char name[SCIP_MAXSTRLEN];
2800 	#endif
2801 	   SCIP_Real* primsol;
2802 	   int nnonviolated = 0;
2803 	   int step = 0;
2804 	   int nCols;
2805 	
2806 	   assert( scip != NULL );
2807 	   assert( lp != NULL );
2808 	   assert( conss != NULL );
2809 	   assert( S != NULL );
2810 	   assert( size != NULL );
2811 	   assert( value != NULL );
2812 	   assert( error != NULL );
2813 	   assert( cutoff != NULL );
2814 	   assert( nGen != NULL );
2815 	
2816 	   *error = FALSE;
2817 	   *cutoff = FALSE;
2818 	   *nGen = 0;
2819 	
2820 	   SCIP_CALL( SCIPlpiGetNCols(lp, &nCols) );
2821 	   SCIP_CALL( SCIPallocBufferArray(scip, &primsol, nCols) );
2822 	   assert( nconss <= nCols );
2823 	
2824 	   do
2825 	   {
2826 	      SCIP_Bool infeasible;
2827 	      SCIP_Real sum = 0.0;
2828 	      SCIP_Real candobj = -1.0;
2829 	      SCIP_Real candval = 2.0;
2830 	      SCIP_Real norm = 1.0;
2831 	      int sizeIIS = 0;
2832 	      int candidate = -1;
2833 	      int candindex = -1;
2834 	      int j;
2835 	
2836 	      if ( step == 0 )
2837 	      {
2838 	         /* the first LP is solved without warm start, after that we use a warmstart. */
2839 	         SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_FROMSCRATCH, TRUE) );
2840 	         SCIP_CALL( checkAltLPInfeasible(scip, lp, conshdlrdata->maxconditionaltlp, TRUE, &infeasible, error) );
2841 	         SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_FROMSCRATCH, FALSE) );
2842 	      }
2843 	      else
2844 	         SCIP_CALL( checkAltLPInfeasible(scip, lp, conshdlrdata->maxconditionaltlp, FALSE, &infeasible, error) );
2845 	
2846 	      if ( *error )
2847 	         break;
2848 	
2849 	      /* if the alternative polyhedron is infeasible, we found a cover */
2850 	      if ( infeasible )
2851 	      {
2852 	         /* Note: checking for a primal solution is done in extendToCover(). */
2853 	         SCIPdebugMsg(scip, "   size: %4d  produced possible cover with indicator variable objective value %f.\n", *size, *value);
2854 	
2855 	         /* we currently cannot call probing if there are cuts in the sepastore; @todo fix this */
2856 	         if ( conshdlrdata->trysolfromcover )
2857 	         {
2858 	            /* Check whether we want to try to construct a feasible solution: there should be no integer/binary variables
2859 	             * except the indicator variables. Thus, there should be no integral variables and the number of indicator
2860 	             * variables should be at least (actually equal to) the number of binary variables. */
2861 	            if ( SCIPgetNIntVars(scip) == 0 && nconss >= SCIPgetNBinVars(scip) )
2862 	            {
2863 	               SCIP_HEUR* heurindicator;
2864 	
2865 	               heurindicator = SCIPfindHeur(scip, "indicator");
2866 	               if ( heurindicator == NULL )
2867 	               {
2868 	                  SCIPerrorMessage("Could not find heuristic \"indicator\".\n");
2869 	                  return SCIP_PLUGINNOTFOUND;
2870 	               }
2871 	
2872 	               SCIP_CALL( SCIPheurPassIndicator(scip, heurindicator, nconss, conss, S, -*value) );
2873 	               SCIPdebugMsg(scip, "Passed feasible solution to indicator heuristic.\n");
2874 	            }
2875 	         }
2876 	         break;
2877 	      }
2878 	
2879 	      /* get solution of alternative LP */
2880 	      SCIP_CALL( SCIPlpiGetSol(lp, NULL, primsol, NULL, NULL, NULL) );
2881 	
2882 	      /* get value of cut and find candidate for variable to add */
2883 	      for (j = 0; j < nconss; ++j)
2884 	      {
2885 	         SCIP_CONSDATA* consdata;
2886 	         int ind;
2887 	
2888 	         consdata = SCIPconsGetData(conss[j]);
2889 	         assert( consdata != NULL );
2890 	         ind = consdata->colindex;
2891 	
2892 	         if ( ind >= 0 )
2893 	         {
2894 	            assert( ind < nCols );
2895 	
2896 	            /* check support of the solution, i.e., the corresponding IIS */
2897 	            if ( ! SCIPisFeasZero(scip, primsol[ind]) )
2898 	            {
2899 	               SCIP_Real val;
2900 	
2901 	               assert( ! S[j] );
2902 	               ++sizeIIS;
2903 	               val = SCIPgetSolVal(scip, sol, consdata->binvar);
2904 	               sum += val;
2905 	
2906 	               /* take element with smallest relaxation value */
2907 	               if ( val < candval )
2908 	               {
2909 	                  candidate = j;
2910 	                  candindex = ind;
2911 	                  candval = val;
2912 	                  candobj = varGetObjDelta(consdata->binvar);
2913 	               }
2914 	            }
2915 	         }
2916 	      }
2917 	
2918 	      /* check for error */
2919 	      if ( candidate < 0 )
2920 	      {
2921 	         /* Because of numerical problems it might happen that the solution primsol above is zero
2922 	          * within the tolerances. In this case we quit. */
2923 	         break;
2924 	      }
2925 	      assert( candidate >= 0 );
2926 	      assert( ! S[candidate] );
2927 	      assert( sizeIIS > 0 );
2928 	
2929 	      /* get the type of norm to use for efficacy calculations */
2930 	      switch ( conshdlrdata->normtype )
2931 	      {
2932 	      case 'e':
2933 	         norm = sqrt((SCIP_Real) sizeIIS);
2934 	         break;
2935 	      case 'm':
2936 	         norm = 1.0;
2937 	         break;
2938 	      case 's':
2939 	         norm = (SCIP_Real) sizeIIS;
2940 	         break;
2941 	      case 'd':
2942 	         norm = 1.0;
2943 	         break;
2944 	      default:
2945 	         SCIPerrorMessage("Invalid efficacy norm parameter '%c'.\n", conshdlrdata->normtype);
2946 	         SCIPABORT();
2947 	         norm = 1.0; /*lint !e527*/
2948 	      }
2949 	
2950 	      SCIPdebugMsg(scip, "   size: %4d, add var. %4d (obj: %-6g, alt-LP sol: %-8.4f); IIS size: %4d, eff.: %g.\n",
2951 	         *size, candidate, candobj, primsol[SCIPconsGetData(conss[candidate])->colindex], sizeIIS, (sum - (SCIP_Real) (sizeIIS - 1))/norm);
2952 	
2953 	      /* update new set S */
2954 	      S[candidate] = TRUE;
2955 	      ++(*size);
2956 	      *value += candobj;
2957 	
2958 	      /* fix chosen variable to 0 */
2959 	      SCIP_CALL( fixAltLPVariable(lp, candindex) );
2960 	
2961 	      /* if cut is violated, i.e., sum - sizeIIS + 1 > 0 */
2962 	      if ( SCIPisEfficacious(scip, (sum - (SCIP_Real) (sizeIIS - 1))/norm) )
2963 	      {
2964 	         SCIP_Bool isLocal = FALSE;
2965 	
2966 	#ifdef SCIP_ENABLE_IISCHECK
2967 	         /* check whether we really have an infeasible subsystem */
2968 	         SCIP_CALL( checkIIS(scip, nconss, conss, primsol) );
2969 	#endif
2970 	
2971 	         /* check whether IIS corresponds to a local cut */
2972 	         if (  conshdlrdata->updatebounds )
2973 	         {
2974 	            SCIP_CALL( checkIISlocal(scip, conshdlrdata, primsol, &isLocal) );
2975 	         }
2976 	
2977 	         if ( genlogicor )
2978 	         {
2979 	            SCIP_RESULT result;
2980 	            SCIP_CONS* cons;
2981 	            SCIP_VAR** vars;
2982 	            int cnt = 0;
2983 	
2984 	            SCIP_CALL( SCIPallocBufferArray(scip, &vars, nconss) );
2985 	
2986 	            /* collect variables corresponding to support to cut */
2987 	            for (j = 0; j < nconss; ++j)
2988 	            {
2989 	               SCIP_CONSDATA* consdata;
2990 	               int ind;
2991 	
2992 	               consdata = SCIPconsGetData(conss[j]);
2993 	               ind = consdata->colindex;
2994 	
2995 	               if ( ind >= 0 )
2996 	               {
2997 	                  assert( ind < nCols );
2998 	                  assert( consdata->binvar != NULL );
2999 	
3000 	                  /* check support of the solution, i.e., the corresponding IIS */
3001 	                  if ( ! SCIPisFeasZero(scip, primsol[ind]) )
3002 	                  {
3003 	                     SCIP_VAR* var;
3004 	                     SCIP_CALL( SCIPgetNegatedVar(scip, consdata->binvar, &var) );
3005 	                     vars[cnt++] = var;
3006 	                  }
3007 	               }
3008 	            }
3009 	            assert( cnt == sizeIIS );
3010 	
3011 	#ifdef SCIP_DEBUG
3012 	            (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "iis%d", conshdlrdata->niiscutsgen + *nGen);
3013 	            SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, name, cnt, vars, FALSE, TRUE, TRUE, TRUE, TRUE, isLocal, FALSE, TRUE, removable, FALSE) );
3014 	#else
3015 	            SCIP_CALL( SCIPcreateConsLogicor(scip, &cons, "", cnt, vars, FALSE, TRUE, TRUE, TRUE, TRUE, isLocal, FALSE, TRUE, removable, FALSE) );
3016 	#endif
3017 	
3018 	#ifdef SCIP_OUTPUT
3019 	            SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
3020 	            SCIPinfoMessage(scip, NULL, ";\n");
3021 	#endif
3022 	
3023 	            /* enforce or separate logicor constraint to make sure that this has an effect in this round */
3024 	            switch ( enfosepatype )
3025 	            {
3026 	            case SCIP_TYPE_ENFOLP:
3027 	               SCIP_CALL( SCIPenfolpCons(scip, cons, FALSE, &result) );
3028 	               break;
3029 	            case SCIP_TYPE_ENFOPS:
3030 	               SCIP_CALL( SCIPenfopsCons(scip, cons, FALSE, FALSE, &result) );
3031 	               break;
3032 	            case SCIP_TYPE_ENFORELAX:
3033 	               SCIP_CALL( SCIPenforelaxCons(scip, cons, sol, FALSE, &result) );
3034 	               break;
3035 	            case SCIP_TYPE_SEPALP:
3036 	               SCIP_CALL( SCIPsepalpCons(scip, cons, &result) );
3037 	               break;
3038 	            case SCIP_TYPE_SEPARELAX:
3039 	            case SCIP_TYPE_SEPASOL:
3040 	               SCIP_CALL( SCIPsepasolCons(scip, cons, sol, &result) );
3041 	               break;
3042 	            default:
3043 	               SCIPerrorMessage("Wrong enforcing/separation type.\n");
3044 	               SCIPABORT();
3045 	            }
3046 	
3047 	            SCIP_CALL( SCIPaddCons(scip, cons) );
3048 	            SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3049 	
3050 	            SCIPfreeBufferArray(scip, &vars);
3051 	            ++(*nGen);
3052 	         }
3053 	         else
3054 	         {
3055 	            SCIP_ROW* row;
3056 	
3057 	            /* create row */
3058 	#ifdef SCIP_DEBUG
3059 	            (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "iis%d", conshdlrdata->niiscutsgen + *nGen);
3060 	            SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, name, -SCIPinfinity(scip), (SCIP_Real) (sizeIIS - 1), isLocal, FALSE, removable) );
3061 	#else
3062 	            SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, "", -SCIPinfinity(scip), (SCIP_Real) (sizeIIS - 1), isLocal, FALSE, removable) );
3063 	#endif
3064 	            SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
3065 	
3066 	            /* add variables corresponding to support to cut */
3067 	            for (j = 0; j < nconss; ++j)
3068 	            {
3069 	               int ind;
3070 	               SCIP_CONSDATA* consdata;
3071 	
3072 	               consdata = SCIPconsGetData(conss[j]);
3073 	               ind = consdata->colindex;
3074 	
3075 	               if ( ind >= 0 )
3076 	               {
3077 	                  assert( ind < nCols );
3078 	                  assert( consdata->binvar != NULL );
3079 	
3080 	                  /* check support of the solution, i.e., the corresponding IIS */
3081 	                  if ( ! SCIPisFeasZero(scip, primsol[ind]) )
3082 	                  {
3083 	                     SCIP_VAR* var = consdata->binvar;
3084 	                     SCIP_CALL( SCIPaddVarToRow(scip, row, var, 1.0) );
3085 	                  }
3086 	               }
3087 	            }
3088 	            SCIP_CALL( SCIPflushRowExtensions(scip, row) );
3089 	#ifdef SCIP_OUTPUT
3090 	            SCIP_CALL( SCIPprintRow(scip, row, NULL) );
3091 	#endif
3092 	            SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
3093 	            if ( *cutoff )
3094 	            {
3095 	               SCIPfreeBufferArray(scip, &primsol);
3096 	               return SCIP_OKAY;
3097 	            }
3098 	
3099 	            /* cut should be violated: */
3100 	            assert( SCIPisFeasNegative(scip, SCIPgetRowSolFeasibility(scip, row, sol)) );
3101 	
3102 	            /* add cuts to pool if they are globally valid */
3103 	            if ( ! isLocal )
3104 	               SCIP_CALL( SCIPaddPoolCut(scip, row) );
3105 	            SCIP_CALL( SCIPreleaseRow(scip, &row));
3106 	            ++(*nGen);
3107 	         }
3108 	         nnonviolated = 0;
3109 	      }
3110 	      else
3111 	         ++nnonviolated;
3112 	      ++step;
3113 	
3114 	      if ( nnonviolated > conshdlrdata->maxsepanonviolated )
3115 	      {
3116 	         SCIPdebugMsg(scip, "Stop separation after %d non violated IISs.\n", nnonviolated);
3117 	         break;
3118 	      }
3119 	   }
3120 	   while (step < nconss);
3121 	
3122 	   SCIPfreeBufferArray(scip, &primsol);
3123 	
3124 	   return SCIP_OKAY;
3125 	}
3126 	
3127 	
3128 	/* ---------------------------- constraint handler local methods ----------------------*/
3129 	
3130 	/** creates and initializes consdata */
3131 	static
3132 	SCIP_RETCODE consdataCreate(
3133 	   SCIP*                 scip,               /**< SCIP data structure */
3134 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
3135 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
3136 	   const char*           consname,           /**< name of constraint (or NULL) */
3137 	   SCIP_CONSDATA**       consdata,           /**< pointer to linear constraint data */
3138 	   SCIP_EVENTHDLR*       eventhdlrbound,     /**< event handler for bound change events */
3139 	   SCIP_EVENTHDLR*       eventhdlrrestart,   /**< event handler for handling restarts */
3140 	   SCIP_VAR*             binvar,             /**< binary variable (or NULL) */
3141 	   SCIP_Bool             activeone,          /**< whether the constraint is active on 1 or not */
3142 	   SCIP_Bool             lessthanineq,       /**< whether the original linear constraint is a less-than-rhs (TRUE) or not */
3143 	   SCIP_VAR*             slackvar,           /**< slack variable */
3144 	   SCIP_CONS*            lincons,            /**< linear constraint (or NULL) */
3145 	   SCIP_Bool             linconsactive       /**< whether the linear constraint is active */
3146 	   )
3147 	{
3148 	   SCIP_VAR* binvarinternal;
3149 	
3150 	   assert( scip != NULL );
3151 	   assert( conshdlr != NULL );
3152 	   assert( conshdlrdata != NULL );
3153 	   assert( consdata != NULL );
3154 	   assert( slackvar != NULL );
3155 	   assert( eventhdlrbound != NULL );
3156 	   assert( eventhdlrrestart != NULL );
3157 	
3158 	   /* if active on 0, the binary variable is reversed */
3159 	   if ( activeone )
3160 	   {
3161 	      binvarinternal = binvar;
3162 	   }
3163 	   else
3164 	   {
3165 	      SCIP_CALL ( SCIPgetNegatedVar(scip, binvar, &binvarinternal) );
3166 	   }
3167 	
3168 	   /* create constraint data */
3169 	   SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
3170 	   (*consdata)->nfixednonzero = 0;
3171 	   (*consdata)->colindex = -1;
3172 	   (*consdata)->linconsactive = linconsactive;
3173 	   (*consdata)->binvar = binvarinternal;
3174 	   (*consdata)->slackvar = slackvar;
3175 	   (*consdata)->activeone = activeone;
3176 	   (*consdata)->lessthanineq = lessthanineq;
3177 	   (*consdata)->lincons = lincons;
3178 	   (*consdata)->implicationadded = FALSE;
3179 	   (*consdata)->slacktypechecked = FALSE;
3180 	
3181 	   /* if we are transformed, obtain transformed variables and catch events */
3182 	   if ( SCIPisTransformed(scip) )
3183 	   {
3184 	      SCIP_VAR* var;
3185 	
3186 	      /* handle binary variable */
3187 	      if ( binvarinternal != NULL )
3188 	      {
3189 	         SCIP_CALL( SCIPgetTransformedVar(scip, binvarinternal, &var) );
3190 	         assert( var != NULL );
3191 	         (*consdata)->binvar = var;
3192 	
3193 	         /* check type */
3194 	         if ( SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3195 	         {
3196 	            SCIPerrorMessage("Indicator variable <%s> is not binary %d.\n", SCIPvarGetName(var), SCIPvarGetType(var));
3197 	            return SCIP_ERROR;
3198 	         }
3199 	
3200 	         /* the indicator variable must not be multi-aggregated because the constraint handler propagation tries
3201 	          * to tighten its bounds, which is not allowed for multi-aggregated variables
3202 	          */
3203 	         SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, var) );
3204 	
3205 	         /* catch local bound change events on binary variable */
3206 	         if ( linconsactive )
3207 	         {
3208 	            SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlrbound, (SCIP_EVENTDATA*)*consdata, NULL) );
3209 	         }
3210 	
3211 	         /* catch global bound change events on binary variable */
3212 	         if ( conshdlrdata->forcerestart )
3213 	         {
3214 	            SCIPdebugMsg(scip, "Catching GBDCHANGED event for <%s>.\n", SCIPvarGetName(var));
3215 	            SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_GBDCHANGED, eventhdlrrestart, (SCIP_EVENTDATA*) conshdlrdata, NULL) );
3216 	         }
3217 	
3218 	         /* if binary variable is fixed to be nonzero */
3219 	         if ( SCIPvarGetLbLocal(var) > 0.5 )
3220 	            ++((*consdata)->nfixednonzero);
3221 	      }
3222 	
3223 	      /* handle slack variable */
3224 	      SCIP_CALL( SCIPgetTransformedVar(scip, slackvar, &var) );
3225 	      assert( var != NULL );
3226 	      (*consdata)->slackvar = var;
3227 	
3228 	      /* catch bound change events on slack variable and adjust nfixednonzero */
3229 	      if ( linconsactive )
3230 	      {
3231 	         SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlrbound, (SCIP_EVENTDATA*)*consdata, NULL) );
3232 	
3233 	         /* if slack variable is fixed to be nonzero */
3234 	         if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(var)) )
3235 	            ++((*consdata)->nfixednonzero);
3236 	      }
3237 	
3238 	      /* add corresponding column to alternative LP if the constraint is new */
3239 	      if ( conshdlrdata->sepaalternativelp && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && lincons != NULL )
3240 	      {
3241 	         assert( lincons != NULL );
3242 	         assert( consname != NULL );
3243 	
3244 	         SCIP_CALL( addAltLPConstraint(scip, conshdlr, lincons, var, 1.0, &(*consdata)->colindex) );
3245 	
3246 	         SCIPdebugMsg(scip, "Added column for <%s> to alternative LP with column index %d.\n", consname, (*consdata)->colindex);
3247 	#ifdef SCIP_OUTPUT
3248 	         SCIP_CALL( SCIPprintCons(scip, lincons, NULL) );
3249 	         SCIPinfoMessage(scip, NULL, ";\n");
3250 	#endif
3251 	      }
3252 	
3253 	#ifdef SCIP_DEBUG
3254 	      if ( (*consdata)->nfixednonzero > 0 )
3255 	      {
3256 	         SCIPdebugMsg(scip, "Constraint <%s> has %d variables fixed to be nonzero.\n", consname, (*consdata)->nfixednonzero);
3257 	      }
3258 	#endif
3259 	   }
3260 	
3261 	   return SCIP_OKAY;
3262 	}
3263 	
3264 	
3265 	/** create variable upper bounds for constraints */
3266 	static
3267 	SCIP_RETCODE createVarUbs(
3268 	   SCIP*                 scip,               /**< SCIP pointer */
3269 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
3270 	   SCIP_CONS**           conss,              /**< constraints */
3271 	   int                   nconss,             /**< number of constraints */
3272 	   int*                  ngen                /**< number of successful operations */
3273 	   )
3274 	{
3275 	   char name[50];
3276 	   int c;
3277 	
3278 	   assert( scip != NULL );
3279 	   assert( conshdlrdata != NULL );
3280 	   assert( ngen != NULL );
3281 	
3282 	   *ngen = 0;
3283 	
3284 	   /* check each constraint */
3285 	   for (c = 0; c < nconss; ++c)
3286 	   {
3287 	      SCIP_CONSDATA* consdata;
3288 	      SCIP_Real ub;
3289 	
3290 	      consdata = SCIPconsGetData(conss[c]);
3291 	      assert( consdata != NULL );
3292 	
3293 	      ub = SCIPvarGetUbGlobal(consdata->slackvar);
3294 	      assert( ! SCIPisNegative(scip, ub) );
3295 	
3296 	      /* insert corresponding row if helpful and coefficient is not too large */
3297 	      if ( ub <= conshdlrdata->maxcouplingvalue )
3298 	      {
3299 	         SCIP_CONS* cons;
3300 	
3301 	#ifndef NDEBUG
3302 	         (void) SCIPsnprintf(name, 50, "couple%d", c);
3303 	#else
3304 	         name[0] = '\0';
3305 	#endif
3306 	
3307 	         SCIPdebugMsg(scip, "Insert coupling varbound constraint for indicator constraint <%s> (coeff: %f).\n", SCIPconsGetName(conss[c]), ub);
3308 	
3309 	         /* add variable upper bound:
3310 	          * - check constraint if we remove the indicator constraint afterwards
3311 	          * - constraint is dynamic if we do not remove indicator constraints
3312 	          * - constraint is removable if we do not remove indicator constraints
3313 	          */
3314 	         SCIP_CALL( SCIPcreateConsVarbound(scip, &cons, name, consdata->slackvar, consdata->binvar, ub, -SCIPinfinity(scip), ub,
3315 	               TRUE, TRUE, TRUE, conshdlrdata->removeindicators, TRUE, FALSE, FALSE,
3316 	               !conshdlrdata->removeindicators, !conshdlrdata->removeindicators, FALSE) );
3317 	
3318 	         SCIP_CALL( SCIPaddCons(scip, cons) );
3319 	         SCIP_CALL( SCIPreleaseCons(scip, &cons) );
3320 	
3321 	         /* remove indicator constraint if required */
3322 	         if ( conshdlrdata->removeindicators )
3323 	         {
3324 	            SCIPdebugMsg(scip, "Removing indicator constraint <%s>.\n", SCIPconsGetName(conss[c]));
3325 	            assert( ! SCIPconsIsModifiable(conss[c]) );
3326 	
3327 	            /* mark linear constraint to be upgrade-able */
3328 	            if ( SCIPconsIsActive(consdata->lincons) )
3329 	            {
3330 	               SCIPconsAddUpgradeLocks(consdata->lincons, -1);
3331 	               assert( SCIPconsGetNUpgradeLocks(consdata->lincons) == 0 );
3332 	            }
3333 	
3334 	            SCIP_CALL( SCIPdelCons(scip, conss[c]) );
3335 	         }
3336 	
3337 	         ++(*ngen);
3338 	      }
3339 	   }
3340 	
3341 	   return SCIP_OKAY;
3342 	}
3343 	
3344 	
3345 	/** perform one presolving round */
3346 	static
3347 	SCIP_RETCODE presolRoundIndicator(
3348 	   SCIP*                 scip,               /**< SCIP pointer */
3349 	   SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
3350 	   SCIP_CONS*            cons,               /**< constraint */
3351 	   SCIP_CONSDATA*        consdata,           /**< constraint data */
3352 	   SCIP_Bool             dualreductions,     /**< should dual reductions be performed? */
3353 	   SCIP_Bool*            cutoff,             /**< whether a cutoff happened */
3354 	   SCIP_Bool*            success,            /**< whether we performed a successful reduction */
3355 	   int*                  ndelconss,          /**< number of deleted constraints */
3356 	   int*                  nfixedvars          /**< number of fixed variables */
3357 	   )
3358 	{
3359 	   SCIP_Bool infeasible;
3360 	   SCIP_Bool fixed;
3361 	
3362 	   assert( scip != NULL );
3363 	   assert( cons != NULL );
3364 	   assert( consdata != NULL );
3365 	   assert( cutoff != NULL );
3366 	   assert( success != NULL );
3367 	   assert( ndelconss != NULL );
3368 	   assert( nfixedvars != NULL );
3369 	   assert( consdata->binvar != NULL );
3370 	   assert( consdata->slackvar != NULL );
3371 	
3372 	   *cutoff = FALSE;
3373 	   *success = FALSE;
3374 	
3375 	   /* if the binary variable is fixed to nonzero */
3376 	   if ( SCIPvarGetLbLocal(consdata->binvar) > 0.5 )
3377 	   {
3378 	      SCIPdebugMsg(scip, "Presolving <%s>: Binary variable fixed to 1.\n", SCIPconsGetName(cons));
3379 	
3380 	      /* if slack variable is fixed to nonzero, we are infeasible */
3381 	      if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(consdata->slackvar)) )
3382 	      {
3383 	         SCIPdebugMsg(scip, "The problem is infeasible: binary and slack variable are fixed to be nonzero.\n");
3384 	         *cutoff = TRUE;
3385 	         return SCIP_OKAY;
3386 	      }
3387 	
3388 	      /* otherwise fix slack variable to 0 */
3389 	      SCIPdebugMsg(scip, "Fix slack variable to 0 and delete constraint.\n");
3390 	      SCIP_CALL( SCIPfixVar(scip, consdata->slackvar, 0.0, &infeasible, &fixed) );
3391 	      assert( ! infeasible );
3392 	      if ( fixed )
3393 	         ++(*nfixedvars);
3394 	
3395 	      /* mark linear constraint to be update-able */
3396 	      if ( SCIPconsIsActive(consdata->lincons) )
3397 	      {
3398 	         SCIPconsAddUpgradeLocks(consdata->lincons, -1);
3399 	         assert( SCIPconsGetNUpgradeLocks(consdata->lincons) == 0 );
3400 	      }
3401 	
3402 	      /* delete indicator constraint (leave linear constraint) */
3403 	      assert( ! SCIPconsIsModifiable(cons) );
3404 	      SCIP_CALL( SCIPdelCons(scip, cons) );
3405 	      ++(*ndelconss);
3406 	      *success = TRUE;
3407 	      return SCIP_OKAY;
3408 	   }
3409 	
3410 	   /* if the binary variable is fixed to zero */
3411 	   if ( SCIPvarGetUbLocal(consdata->binvar) < 0.5 )
3412 	   {
3413 	      SCIPdebugMsg(scip, "Presolving <%s>: Binary variable <%s> fixed to 0, deleting indicator constraint.\n", SCIPconsGetName(cons), SCIPvarGetName(consdata->binvar));
3414 	
3415 	      /* mark linear constraint to be update-able */
3416 	      if ( SCIPconsIsActive(consdata->lincons) )
3417 	      {
3418 	         SCIPconsAddUpgradeLocks(consdata->lincons, -1);
3419 	         assert( SCIPconsGetNUpgradeLocks(consdata->lincons) == 0 );
3420 	      }
3421 	
3422 	      /* delete indicator constraint */
3423 	      assert( ! SCIPconsIsModifiable(cons) );
3424 	      SCIP_CALL( SCIPdelCons(scip, cons) );
3425 	      ++(*ndelconss);
3426 	      *success = TRUE;
3427 	      return SCIP_OKAY;
3428 	   }
3429 	
3430 	   /* if the slack variable is fixed to nonzero */
3431 	   if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(consdata->slackvar)) )
3432 	   {
3433 	      SCIPdebugMsg(scip, "Presolving <%s>: Slack variable fixed to nonzero.\n", SCIPconsGetName(cons));
3434 	
3435 	      /* if binary variable is fixed to nonzero, we are infeasible */
3436 	      if ( SCIPvarGetLbLocal(consdata->binvar) > 0.5 )
3437 	      {
3438 	         SCIPdebugMsg(scip, "The problem is infeasible: binary and slack variable are fixed to be nonzero.\n");
3439 	         *cutoff = TRUE;
3440 	         return SCIP_OKAY;
3441 	      }
3442 	
3443 	      /* otherwise fix binary variable to 0 */
3444 	      SCIPdebugMsg(scip, "Fix binary variable to 0 and delete indicator constraint.\n");
3445 	      SCIP_CALL( SCIPfixVar(scip, consdata->binvar, 0.0, &infeasible, &fixed) );
3446 	      assert( ! infeasible );
3447 	      if ( fixed )
3448 	         ++(*nfixedvars);
3449 	
3450 	      /* mark linear constraint to be update-able */
3451 	      if ( SCIPconsIsActive(consdata->lincons) )
3452 	      {
3453 	         SCIPconsAddUpgradeLocks(consdata->lincons, -1);
3454 	         assert( SCIPconsGetNUpgradeLocks(consdata->lincons) == 0 );
3455 	      }
3456 	
3457 	      /* delete constraint */
3458 	      assert( ! SCIPconsIsModifiable(cons) );
3459 	      SCIP_CALL( SCIPdelCons(scip, cons) );
3460 	      ++(*ndelconss);
3461 	      *success = TRUE;
3462 	      return SCIP_OKAY;
3463 	   }
3464 	
3465 	   /* if the slack variable is fixed to zero */
3466 	   if ( SCIPisFeasZero(scip, SCIPvarGetUbLocal(consdata->slackvar)) )
3467 	   {
3468 	      /* perform dual reductions - if required */
3469 	      if ( dualreductions )
3470 	      {
3471 	         SCIP_VAR* binvar;
3472 	         SCIP_Real obj;
3473 	
3474 	         /* check objective of binary variable */
3475 	         binvar = consdata->binvar;
3476 	         obj = varGetObjDelta(binvar);
3477 	
3478 	         /* if obj = 0, we prefer fixing the binary variable to 1 (if possible) */
3479 	         if ( obj <= 0.0 )
3480 	         {
3481 	            /* In this case we would like to fix the binary variable to 1, if it is not locked up
3482 	               except by this indicator constraint. If more than one indicator constraint is
3483 	               effected, we have to hope that they are all fulfilled - in this case the last
3484 	               constraint will fix the binary variable to 1. */
3485 	            if ( SCIPvarGetNLocksUpType(binvar, SCIP_LOCKTYPE_MODEL) <= 1 )
3486 	            {
3487 	               if ( SCIPvarGetUbGlobal(binvar) > 0.5 )
3488 	               {
3489 	                  SCIPdebugMsg(scip, "Presolving <%s> - dual reduction: Slack variable fixed to 0, fix binary variable to 1.\n", SCIPconsGetName(cons));
3490 	                  SCIP_CALL( SCIPfixVar(scip, binvar, 1.0, &infeasible, &fixed) );
3491 	                  assert( ! infeasible );
3492 	                  if ( fixed )
3493 	                     ++(*nfixedvars);
3494 	                  /* make sure that the other case does not occur */
3495 	                  obj = -1.0;
3496 	               }
3497 	            }
3498 	         }
3499 	         if ( obj >= 0.0 )
3500 	         {
3501 	            /* In this case we would like to fix the binary variable to 0, if it is not locked down
3502 	               (should also have been performed by other dual reductions). */
3503 	            if ( SCIPvarGetNLocksDownType(binvar, SCIP_LOCKTYPE_MODEL) == 0 )
3504 	            {
3505 	               if ( SCIPvarGetLbGlobal(binvar) < 0.5 )
3506 	               {
3507 	                  SCIPdebugMsg(scip, "Presolving <%s> - dual reduction: Slack variable fixed to 0, fix binary variable to 0.\n", SCIPconsGetName(cons));
3508 	                  SCIP_CALL( SCIPfixVar(scip, binvar, 0.0, &infeasible, &fixed) );
3509 	                  assert( ! infeasible );
3510 	                  if ( fixed )
3511 	                     ++(*nfixedvars);
3512 	               }
3513 	            }
3514 	         }
3515 	      }
3516 	
3517 	      SCIPdebugMsg(scip, "Presolving <%s>: Slack variable fixed to zero, delete redundant indicator constraint.\n", SCIPconsGetName(cons));
3518 	
3519 	      /* mark linear constraint to be upgrade-able */
3520 	      if ( SCIPconsIsActive(consdata->lincons) )
3521 	      {
3522 	         SCIPconsAddUpgradeLocks(consdata->lincons, -1);
3523 	         assert( SCIPconsGetNUpgradeLocks(consdata->lincons) == 0 );
3524 	      }
3525 	
3526 	      /* delete constraint */
3527 	      assert( ! SCIPconsIsModifiable(cons) );
3528 	      SCIP_CALL( SCIPdelCons(scip, cons) );
3529 	      ++(*ndelconss);
3530 	      *success = TRUE;
3531 	      return SCIP_OKAY;
3532 	   }
3533 	
3534 	   /* check whether indicator variable is aggregated  */
3535 	   if ( SCIPvarGetStatus(consdata->binvar) == SCIP_VARSTATUS_AGGREGATED )
3536 	   {
3537 	      SCIP_Bool negated = FALSE;
3538 	      SCIP_VAR* var;
3539 	
3540 	      /* possibly get representation of indicator variable by active variable */
3541 	      var = consdata->binvar;
3542 	      SCIP_CALL( SCIPvarGetProbvarBinary(&var, &negated) );
3543 	      assert( var == consdata->binvar || SCIPvarIsActive(var) || SCIPvarIsNegated(var) );
3544 	
3545 	      /* we can replace the binary variable by the active variable if it is not negated */
3546 	      if ( var != consdata->binvar && ! negated )
3547 	      {
3548 	         SCIPdebugMsg(scip, "Indicator variable <%s> is aggregated and replaced by active/negated variable <%s>.\n", SCIPvarGetName(consdata->binvar), SCIPvarGetName(var) );
3549 	
3550 	         /* we need to update the events and locks */
3551 	         assert( conshdlrdata->eventhdlrbound != NULL );
3552 	         SCIP_CALL( SCIPdropVarEvent(scip, consdata->binvar, SCIP_EVENTTYPE_BOUNDCHANGED, conshdlrdata->eventhdlrbound, (SCIP_EVENTDATA*) consdata, -1) );
3553 	         SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, conshdlrdata->eventhdlrbound, (SCIP_EVENTDATA*) consdata, NULL) );
3554 	
3555 	         /* We also need to update the events and locks if restart is forced, since global bound change events on binary
3556 	          * variables are also caught in this case. If it would not be updated and forcerestart = TRUE, then an event
3557 	          * might be dropped on a wrong variable. */
3558 	         if ( conshdlrdata->forcerestart )
3559 	         {
3560 	            assert( conshdlrdata->eventhdlrrestart != NULL );
3561 	            SCIP_CALL( SCIPdropVarEvent(scip, consdata->binvar, SCIP_EVENTTYPE_GBDCHANGED,
3562 	                  conshdlrdata->eventhdlrrestart, (SCIP_EVENTDATA*) conshdlrdata, -1) );
3563 	            SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_GBDCHANGED, conshdlrdata->eventhdlrrestart,
3564 	                  (SCIP_EVENTDATA*) conshdlrdata, NULL) );
3565 	         }
3566 	
3567 	         SCIP_CALL( SCIPaddVarLocksType(scip, consdata->binvar, SCIP_LOCKTYPE_MODEL, 0, -1) );
3568 	         SCIP_CALL( SCIPaddVarLocksType(scip, var, SCIP_LOCKTYPE_MODEL, 0, 1) );
3569 	
3570 	         /* change binvary variable */
3571 	         consdata->binvar = var;
3572 	      }
3573 	   }
3574 	   else if ( SCIPvarGetStatus(consdata->binvar) == SCIP_VARSTATUS_NEGATED )
3575 	   {
3576 	      SCIP_VAR* var;
3577 	
3578 	      var = SCIPvarGetNegatedVar(consdata->binvar);
3579 	      assert( var != NULL );
3580 	
3581 	      /* if the binary variable is the negated slack variable, we have 1 - s = 1 -> s = 0, i.e., the constraint is redundant */
3582 	      if ( var == consdata->slackvar )
3583 	      {
3584 	         /* delete constraint */
3585 	         assert( ! SCIPconsIsModifiable(cons) );
3586 	         SCIP_CALL( SCIPdelCons(scip, cons) );
3587 	         ++(*ndelconss);
3588 	         *success = TRUE;
3589 	         return SCIP_OKAY;
3590 	      }
3591 	   }
3592 	
3593 	   /* check whether slack variable is aggregated  */
3594 	   if ( SCIPvarGetStatus(consdata->slackvar) == SCIP_VARSTATUS_AGGREGATED || SCIPvarGetStatus(consdata->slackvar) == SCIP_VARSTATUS_NEGATED )
3595 	   {
3596 	      SCIP_BOUNDTYPE boundtype = SCIP_BOUNDTYPE_LOWER;
3597 	      SCIP_Real bound;
3598 	      SCIP_VAR* var;
3599 	
3600 	      /* possibly get representation of slack variable by active variable */
3601 	      var = consdata->slackvar;
3602 	      bound = SCIPvarGetLbGlobal(var);
3603 	
3604 	      SCIP_CALL( SCIPvarGetProbvarBound(&var, &bound, &boundtype) );
3605 	      assert( var != consdata->slackvar );
3606 	
3607 	      /* we can replace the slack variable by the active variable if it is also a >= variable */
3608 	      if ( var != consdata->binvar && boundtype == SCIP_BOUNDTYPE_LOWER && SCIPisEQ(scip, bound, 0.0) )
3609 	      {
3610 	         assert( SCIPvarIsActive(var) );
3611 	         SCIPdebugMsg(scip, "Slack variable <%s> is aggregated or negated and replaced by active variable <%s>.\n", SCIPvarGetName(consdata->slackvar), SCIPvarGetName(var) );
3612 	
3613 	         /* we need to update the events, locks, and captures */
3614 	         assert( conshdlrdata->eventhdlrbound != NULL );
3615 	         SCIP_CALL( SCIPdropVarEvent(scip, consdata->slackvar, SCIP_EVENTTYPE_BOUNDCHANGED, conshdlrdata->eventhdlrbound, (SCIP_EVENTDATA*) consdata, -1) );
3616 	         SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, conshdlrdata->eventhdlrbound, (SCIP_EVENTDATA*) consdata, NULL) );
3617 	
3618 	         SCIP_CALL( SCIPunlockVarCons(scip, consdata->slackvar, cons, FALSE, TRUE) );
3619 	         SCIP_CALL( SCIPlockVarCons(scip, var, cons, FALSE, TRUE) );
3620 	
3621 	         SCIP_CALL( SCIPreleaseVar(scip, &consdata->slackvar) );
3622 	         SCIP_CALL( SCIPcaptureVar(scip, var) );
3623 	
3624 	         /* change slack variable */
3625 	         consdata->slackvar = var;
3626 	      }
3627 	      else if ( var == consdata->binvar )
3628 	      {
3629 	         /* check special case that aggregating variable is equal to the indicator variable */
3630 	         assert( SCIPisEQ(scip, bound, 0.0) || SCIPisEQ(scip, bound, 1.0) );
3631 	
3632 	         /* if the lower bound is transformed to an upper bound, we have "y = 1 -> 1 - y = 0", i.e., the constraint is redundant */
3633 	         if ( boundtype == SCIP_BOUNDTYPE_UPPER )
3634 	         {
3635 	            SCIPdebugMsg(scip, "Slack variable <%s> is aggregated to negated indicator variable <%s> -> constraint redundant.\n",
3636 	               SCIPvarGetName(consdata->slackvar), SCIPvarGetName(consdata->binvar));
3637 	            assert( SCIPisEQ(scip, bound, 1.0) );
3638 	
3639 	            /* delete constraint */
3640 	            assert( ! SCIPconsIsModifiable(cons) );
3641 	            SCIP_CALL( SCIPdelCons(scip, cons) );
3642 	            ++(*ndelconss);
3643 	            *success = TRUE;
3644 	            return SCIP_OKAY;
3645 	         }
3646 	         else
3647 	         {
3648 	            /* if the lower bound is transformed to a lower bound, we have "y = 1 -> y = 0", i.e., we can fix the binary variable to 0 */
3649 	            SCIPdebugMsg(scip, "Slack variable <%s> is aggregated to the indicator variable <%s> -> fix indicator variable to 0.\n",
3650 	               SCIPvarGetName(consdata->slackvar), SCIPvarGetName(consdata->binvar));
3651 	            assert( boundtype == SCIP_BOUNDTYPE_LOWER );
3652 	            assert( SCIPisEQ(scip, bound, 0.0) );
3653 	
3654 	            SCIP_CALL( SCIPfixVar(scip, consdata->binvar, 0.0, &infeasible, &fixed) );
3655 	            assert( ! infeasible );
3656 	
3657 	            if ( fixed )
3658 	               ++(*nfixedvars);
3659 	
3660 	            SCIP_CALL( SCIPdelCons(scip, cons) );
3661 	
3662 	            ++(*ndelconss);
3663 	            *success = TRUE;
3664 	
3665 	            return SCIP_OKAY;
3666 	         }
3667 	      }
3668 	   }
3669 	
3670 	   /* Note that because of possible multi-aggregation we cannot simply remove the indicator
3671 	    * constraint if the linear constraint is not active or disabled - see the note in @ref
3672 	    * PREPROC. */
3673 	
3674 	   return SCIP_OKAY;
3675 	}
3676 	
3677 	
3678 	/** propagate indicator constraint */
3679 	static
3680 	SCIP_RETCODE propIndicator(
3681 	   SCIP*                 scip,               /**< SCIP pointer */
3682 	   SCIP_CONS*            cons,               /**< constraint */
3683 	   SCIP_CONSDATA*        consdata,           /**< constraint data */
3684 	   SCIP_Bool             dualreductions,     /**< should dual reductions be performed? */
3685 	   SCIP_Bool             addopposite,        /**< add opposite inequalities if binary var = 0? */
3686 	   SCIP_Bool*            cutoff,             /**< whether a cutoff happened */
3687 	   int*                  nGen                /**< number of domain changes */
3688 	   )
3689 	{
3690 	   SCIP_Bool infeasible;
3691 	   SCIP_Bool tightened;
3692 	
3693 	   assert( scip != NULL );
3694 	   assert( cons != NULL );
3695 	   assert( consdata != NULL );
3696 	   assert( cutoff != NULL );
3697 	   assert( nGen != NULL );
3698 	
3699 	   *cutoff = FALSE;
3700 	   *nGen = 0;
3701 	
3702 	   /* if the linear constraint has not been generated, we do nothing */
3703 	   if ( ! consdata->linconsactive )
3704 	      return SCIP_OKAY;
3705 	
3706 	   assert( consdata->slackvar != NULL );
3707 	   assert( consdata->binvar != NULL );
3708 	   assert( SCIPisFeasGE(scip, SCIPvarGetLbLocal(consdata->slackvar), 0.0) );
3709 	
3710 	   /* if both slackvar and binvar are fixed to be nonzero */
3711 	   if ( consdata->nfixednonzero > 1 )
3712 	   {
3713 	      SCIPdebugMsg(scip, "The node is infeasible, both the slack variable and the binary variable are fixed to be nonzero.\n");
3714 	      *cutoff = TRUE;
3715 	
3716 	      SCIP_CALL( SCIPresetConsAge(scip, cons) );
3717 	      assert( SCIPvarGetLbLocal(consdata->binvar) > 0.5 );
3718 	      assert( SCIPisPositive(scip, SCIPvarGetLbLocal(consdata->slackvar)) );
3719 	
3720 	      /* check if conflict analysis is turned on */
3721 	      if ( ! SCIPisConflictAnalysisApplicable(scip) )
3722 	         return SCIP_OKAY;
3723 	
3724 	      /* conflict analysis can only be applied in solving stage */
3725 	      assert( SCIPgetStage(scip) == SCIP_STAGE_SOLVING || SCIPinProbing(scip) );
3726 	
3727 	      /* perform conflict analysis */
3728 	      SCIP_CALL( SCIPinitConflictAnalysis(scip, SCIP_CONFTYPE_PROPAGATION, FALSE) );
3729 	
3730 	      SCIP_CALL( SCIPaddConflictBinvar(scip, consdata->binvar) );
3731 	      SCIP_CALL( SCIPaddConflictLb(scip, consdata->slackvar, NULL) );
3732 	      SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
3733 	
3734 	      return SCIP_OKAY;
3735 	   }
3736 	
3737 	   /* if exactly one of the variables is fixed to be nonzero */
3738 	   if ( consdata->nfixednonzero == 1 )
3739 	   {
3740 	      /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
3741 	      if ( ! SCIPinRepropagation(scip) )
3742 	         SCIP_CALL( SCIPincConsAge(scip, cons) );
3743 	
3744 	      /* if binvar is fixed to be nonzero */
3745 	      if ( SCIPvarGetLbLocal(consdata->binvar) > 0.5 )
3746 	      {
3747 	         assert( SCIPvarGetStatus(consdata->slackvar) != SCIP_VARSTATUS_MULTAGGR );
3748 	
3749 	         /* if slack variable is not already fixed to 0 */
3750 	         if ( ! SCIPisZero(scip, SCIPvarGetUbLocal(consdata->slackvar)) )
3751 	         {
3752 	            SCIPdebugMsg(scip, "Binary variable <%s> is fixed to be nonzero, fixing slack variable <%s> to 0.\n",
3753 	               SCIPvarGetName(consdata->binvar), SCIPvarGetName(consdata->slackvar));
3754 	
3755 	            /* fix slack variable to 0 */
3756 	            SCIP_CALL( SCIPinferVarUbCons(scip, consdata->slackvar, 0.0, cons, 0, FALSE, &infeasible, &tightened) );
3757 	            assert( ! infeasible );
3758 	            if ( tightened )
3759 	               ++(*nGen);
3760 	         }
3761 	      }
3762 	
3763 	      /* if slackvar is fixed to be nonzero */
3764 	      if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(consdata->slackvar)) )
3765 	      {
3766 	         /* if binary variable is not yet fixed to 0 */
3767 	         if ( SCIPvarGetUbLocal(consdata->binvar) > 0.5 )
3768 	         {
3769 	            SCIPdebugMsg(scip, "Slack variable <%s> is fixed to be nonzero, fixing binary variable <%s> to 0.\n",
3770 	               SCIPvarGetName(consdata->slackvar), SCIPvarGetName(consdata->binvar));
3771 	
3772 	            /* fix binary variable to 0 */
3773 	            SCIP_CALL( SCIPinferVarUbCons(scip, consdata->binvar, 0.0, cons, 1, FALSE, &infeasible, &tightened) );
3774 	            assert( ! infeasible );
3775 	            if ( tightened )
3776 	               ++(*nGen);
3777 	         }
3778 	      }
3779 	
3780 	      /* reset constraint age counter */
3781 	      if ( *nGen > 0 )
3782 	         SCIP_CALL( SCIPresetConsAge(scip, cons) );
3783 	
3784 	      /* remove constraint if we are not in probing */
3785 	      if ( ! SCIPinProbing(scip) )
3786 	      {
3787 	         /* mark linear constraint to be update-able */
3788 	         if ( SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING && SCIPconsIsActive(consdata->lincons) )
3789 	         {
3790 	            SCIPconsAddUpgradeLocks(consdata->lincons, -1);
3791 	            assert( SCIPconsGetNUpgradeLocks(consdata->lincons) == 0 );
3792 	         }
3793 	
3794 	         /* delete constraint locally */
3795 	         assert( ! SCIPconsIsModifiable(cons) );
3796 	         SCIP_CALL( SCIPdelConsLocal(scip, cons) );
3797 	      }
3798 	   }
3799 	   else
3800 	   {
3801 	      /* if the binary variable is fixed to zero */
3802 	      if ( SCIPvarGetUbLocal(consdata->binvar) < 0.5 )
3803 	      {
3804 	         if ( addopposite && consdata->linconsactive )
3805 	         {
3806 	            char name[SCIP_MAXSTRLEN];
3807 	            SCIP_CONS* reversecons;
3808 	            SCIP_VAR** linvars;
3809 	            SCIP_Real* linvals;
3810 	            SCIP_Bool allintegral = TRUE;
3811 	            SCIP_VAR* slackvar;
3812 	            SCIP_VAR** vars;
3813 	            SCIP_Real* vals;
3814 	            SCIP_Real lhs;
3815 	            SCIP_Real rhs;
3816 	            int nlinvars;
3817 	            int nvars = 0;
3818 	            int j;
3819 	
3820 	            /* determine lhs/rhs (first exchange lhs/rhs) */
3821 	            lhs = SCIPgetRhsLinear(scip, consdata->lincons);
3822 	            if ( SCIPisInfinity(scip, lhs) )
3823 	               lhs = -SCIPinfinity(scip);
3824 	            rhs = SCIPgetLhsLinear(scip, consdata->lincons);
3825 	            if ( SCIPisInfinity(scip, -rhs) )
3826 	               rhs = SCIPinfinity(scip);
3827 	
3828 	            assert( ! SCIPisInfinity(scip, lhs) );
3829 	            assert( ! SCIPisInfinity(scip, -rhs) );
3830 	
3831 	            /* consider only finite lhs/rhs */
3832 	            if ( ! SCIPisInfinity(scip, -lhs) || ! SCIPisInfinity(scip, rhs) )
3833 	            {
3834 	               /* ignore equations (cannot add opposite constraint) */
3835 	               if ( ! SCIPisEQ(scip, lhs, rhs) )
3836 	               {
3837 	                  assert( consdata->lincons != NULL );
3838 	                  nlinvars = SCIPgetNVarsLinear(scip, consdata->lincons);
3839 	                  linvars = SCIPgetVarsLinear(scip, consdata->lincons);
3840 	                  linvals = SCIPgetValsLinear(scip, consdata->lincons);
3841 	                  slackvar = consdata->slackvar;
3842 	                  assert( slackvar != NULL );
3843 	
3844 	                  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nlinvars) );
3845 	                  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nlinvars) );
3846 	
3847 	                  /* copy data and check whether the linear constraint is integral */
3848 	                  for (j = 0; j < nlinvars; ++j)
3849 	                  {
3850 	                     if ( linvars[j] != slackvar )
3851 	                     {
3852 	                        if (! SCIPvarIsIntegral(linvars[j]) || ! SCIPisIntegral(scip, linvals[j]) )
3853 	                           allintegral = FALSE;
3854 	
3855 	                        vars[nvars] = linvars[j];
3856 	                        vals[nvars++] = linvals[j];
3857 	                     }
3858 	                  }
3859 	                  assert( nlinvars == nvars + 1 );
3860 	
3861 	                  /* possibly adjust lhs/rhs */
3862 	                  if ( allintegral && ! SCIPisInfinity(scip, REALABS(lhs)) )
3863 	                     lhs += 1.0;
3864 	
3865 	                  if ( allintegral && ! SCIPisInfinity(scip, REALABS(rhs)) )
3866 	                     rhs -= 1.0;
3867 	
3868 	                  /* create reverse constraint */
3869 	                  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "reverse_%s", SCIPconsGetName(consdata->lincons));
3870 	
3871 	                  /* constraint is initial, separated, not enforced, not checked, propagated, local, not modifiable, dynamic, removable */
3872 	                  SCIP_CALL( SCIPcreateConsLinear(scip, &reversecons, name, nvars, vars, vals, lhs, rhs,
3873 	                        TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE) );
3874 	
3875 	                  SCIPdebugMsg(scip, "Binary variable <%s> fixed to 0. Adding opposite linear inequality.\n", SCIPvarGetName(consdata->binvar));
3876 	                  SCIPdebugPrintCons(scip, reversecons, NULL);
3877 	
3878 	                  /* add constraint */
3879 	                  SCIP_CALL( SCIPaddCons(scip, reversecons) );
3880 	                  SCIP_CALL( SCIPreleaseCons(scip, &reversecons) );
3881 	
3882 	                  SCIPfreeBufferArray(scip, &vals);
3883 	                  SCIPfreeBufferArray(scip, &vars);
3884 	               }
3885 	            }
3886 	         }
3887 	
3888 	         SCIP_CALL( SCIPdelConsLocal(scip, cons) );
3889 	      }
3890 	
3891 	      /* if the slack variable is fixed to zero */
3892 	      if ( SCIPisFeasZero(scip, SCIPvarGetUbLocal(consdata->slackvar)) )
3893 	      {
3894 	         /* perform dual reduction - if required */
3895 	         if ( dualreductions )
3896 	         {
3897 	            SCIP_VAR* binvar;
3898 	            SCIP_Real obj;
3899 	
3900 	            /* check objective of binary variable */
3901 	            binvar = consdata->binvar;
3902 	            obj = varGetObjDelta(binvar);
3903 	
3904 	            /* if obj = 0, we prefer setting the binary variable to 1 (if possible) */
3905 	            if ( obj <= 0.0 )
3906 	            {
3907 	               /* In this case we would like to fix the binary variable to 1, if it is not locked up
3908 	                  except by this indicator constraint. If more than one indicator constraint is
3909 	                  affected, we have to hope that they are all fulfilled - in this case the last
3910 	                  constraint will fix the binary variable to 1. */
3911 	               if ( SCIPvarGetNLocksUpType(binvar, SCIP_LOCKTYPE_MODEL) <= 1 )
3912 	               {
3913 	                  if ( SCIPvarGetUbLocal(binvar) > 0.5 )
3914 	                  {
3915 	                     SCIPdebugMsg(scip, "Propagating <%s> - dual reduction: Slack variable fixed to 0, fix binary variable to 1.\n", SCIPconsGetName(cons));
3916 	                     SCIP_CALL( SCIPinferVarLbCons(scip, binvar, 1.0, cons, 2, FALSE, &infeasible, &tightened) );
3917 	                     assert( ! infeasible );
3918 	                     if ( tightened )
3919 	                        ++(*nGen);
3920 	                     /* Make sure that the other case does not occur, since we are not sure whether SCIPinferVarLbCons() directly changes the bounds. */
3921 	                     obj = -1.0;
3922 	                  }
3923 	               }
3924 	            }
3925 	            if ( obj >= 0.0 )
3926 	            {
3927 	               /* In this case we would like to fix the binary variable to 0, if it is not locked down
3928 	                  (should also have been performed by other dual reductions). */
3929 	               if ( SCIPvarGetNLocksDownType(binvar, SCIP_LOCKTYPE_MODEL) == 0 )
3930 	               {
3931 	                  if ( SCIPvarGetLbLocal(binvar) < 0.5 )
3932 	                  {
3933 	                     SCIPdebugMsg(scip, "Propagating <%s> - dual reduction: Slack variable fixed to 0, fix binary variable to 0.\n", SCIPconsGetName(cons));
3934 	                     SCIP_CALL( SCIPinferVarUbCons(scip, binvar, 0.0, cons, 2, FALSE, &infeasible, &tightened) );
3935 	                     assert( ! infeasible );
3936 	                     if ( tightened )
3937 	                        ++(*nGen);
3938 	                  }
3939 	               }
3940 	            }
3941 	         }
3942 	
3943 	         SCIPdebugMsg(scip, "Slack variable fixed to zero, delete redundant indicator constraint <%s>.\n", SCIPconsGetName(cons));
3944 	
3945 	         /* delete constraint */
3946 	         assert( ! SCIPconsIsModifiable(cons) );
3947 	
3948 	         /* remove constraint if we are not in probing */
3949 	         if ( ! SCIPinProbing(scip) )
3950 	         {
3951 	            /* mark linear constraint to be update-able */
3952 	            if ( SCIPgetStage(scip) == SCIP_STAGE_PRESOLVING && SCIPconsIsActive(consdata->lincons) )
3953 	            {
3954 	               SCIPconsAddUpgradeLocks(consdata->lincons, -1);
3955 	               assert( SCIPconsGetNUpgradeLocks(consdata->lincons) == 0 );
3956 	            }
3957 	
3958 	            SCIP_CALL( SCIPdelConsLocal(scip, cons) );
3959 	         }
3960 	         SCIP_CALL( SCIPresetConsAge(scip, cons) );
3961 	         ++(*nGen);
3962 	      }
3963 	
3964 	      /* Note that because of possible multi-aggregation we cannot simply remove the indicator
3965 	       * constraint if the linear constraint is not active or disabled - see the note in @ref
3966 	       * PREPROC and consPresolIndicator(). Moreover, it would drastically increase memory
3967 	       * consumption, because the linear constraints have to be stored in each node. */
3968 	   }
3969 	
3970 	   return SCIP_OKAY;
3971 	}
3972 	
3973 	
3974 	/** enforcement method that produces cuts if possible
3975 	 *
3976 	 *  This is a variant of the enforcement method that generates cuts/constraints via the alternative
3977 	 *  LP, if possible.
3978 	 */
3979 	static
3980 	SCIP_RETCODE enforceCuts(
3981 	   SCIP*                 scip,               /**< SCIP pointer */
3982 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
3983 	   int                   nconss,             /**< number of constraints */
3984 	   SCIP_CONS**           conss,              /**< indicator constraints */
3985 	   SCIP_SOL*             sol,                /**< solution to be enforced */
3986 	   SCIP_ENFOSEPATYPE     enfosepatype,       /**< type of enforcing/separating type */
3987 	   SCIP_Bool             genlogicor,         /**< whether logicor constraint should be generated */
3988 	   SCIP_Bool*            cutoff,             /**< whether we detected a cutoff by an infeasible inequality */
3989 	   int*                  nGen                /**< number of cuts generated */
3990 	   )
3991 	{
3992 	   SCIP_CONSHDLRDATA* conshdlrdata;
3993 	   SCIP_LPI* lp;
3994 	   SCIP_Bool* S;
3995 	   SCIP_Real value = 0.0;
3996 	   SCIP_Bool error;
3997 	   int size = 0;
3998 	   int nCuts;
3999 	   int j;
4000 	
4001 	   assert( scip != NULL );
4002 	   assert( conshdlr != NULL );
4003 	   assert( conss != NULL );
4004 	   assert( cutoff != NULL );
4005 	   assert( nGen != NULL );
4006 	
4007 	   SCIPdebugMsg(scip, "Enforcing via cuts ...\n");
4008 	   *cutoff = FALSE;
4009 	   *nGen = 0;
4010 	
4011 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
4012 	   assert( conshdlrdata != NULL );
4013 	   lp = conshdlrdata->altlp;
4014 	   assert( lp != NULL );
4015 	
4016 	#ifndef NDEBUG
4017 	   SCIP_CALL( checkLPBoundsClean(scip, lp, nconss, conss) );
4018 	#endif
4019 	
4020 	   /* change coefficients of bounds in alternative LP */
4021 	   if ( conshdlrdata->updatebounds )
4022 	      SCIP_CALL( updateFirstRowGlobal(scip, conshdlrdata) );
4023 	
4024 	   /* possibly update upper bound */
4025 	   SCIP_CALL( updateObjUpperbound(scip, conshdlr, conshdlrdata) );
4026 	
4027 	   /* scale first row if necessary */
4028 	   SCIP_CALL( scaleFirstRow(scip, conshdlrdata) );
4029 	
4030 	   /* set objective function to current solution */
4031 	   SCIP_CALL( setAltLPObjZero(scip, lp, nconss, conss) );
4032 	
4033 	   SCIP_CALL( SCIPallocBufferArray(scip, &S, nconss) );
4034 	
4035 	   /* set up variables fixed to 1 */
4036 	   for (j = 0; j < nconss; ++j)
4037 	   {
4038 	      SCIP_CONSDATA* consdata;
4039 	
4040 	      assert( conss[j] != NULL );
4041 	      consdata = SCIPconsGetData(conss[j]);
4042 	      assert( consdata != NULL );
4043 	
4044 	      assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, consdata->binvar)) );
4045 	      if ( SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->binvar)) )
4046 	      {
4047 	         ++size;
4048 	         value += varGetObjDelta(consdata->binvar);
4049 	         S[j] = TRUE;
4050 	      }
4051 	      else
4052 	         S[j] = FALSE;
4053 	   }
4054 	
4055 	   /* fix the variables in S */
4056 	   SCIP_CALL( fixAltLPVariables(scip, lp, nconss, conss, S) );
4057 	
4058 	   /* extend set S to a cover and generate cuts */
4059 	   error = FALSE;
4060 	   SCIP_CALL( extendToCover(scip, conshdlr, conshdlrdata, lp, sol, enfosepatype, conshdlrdata->removable, genlogicor, nconss, conss, S, &size, &value, &error, cutoff, &nCuts) );
4061 	   *nGen = nCuts;
4062 	
4063 	   /* return with an error if no cuts have been produced and and error occurred in extendToCover() */
4064 	   if ( nCuts == 0 && error )
4065 	      return SCIP_LPERROR;
4066 	
4067 	   SCIPdebugMsg(scip, "Generated %d IIS-cuts.\n", nCuts);
4068 	
4069 	   /* reset bounds */
4070 	   SCIP_CALL( unfixAltLPVariables(scip, lp, nconss, conss, S) );
4071 	
4072 	#ifndef NDEBUG
4073 	   SCIP_CALL( checkLPBoundsClean(scip, lp, nconss, conss) );
4074 	#endif
4075 	
4076 	   SCIPfreeBufferArray(scip, &S);
4077 	
4078 	   return SCIP_OKAY;
4079 	}
4080 	
4081 	
4082 	/** enforcement method
4083 	 *
4084 	 *  We check whether the current solution is feasible, i.e., if binvar = 1
4085 	 *  implies that slackvar = 0. If not, we branch as follows:
4086 	 *
4087 	 *  In one branch we fix binvar = 1 and slackvar = 0. In the other branch
4088 	 *  we fix binvar = 0 and leave slackvar unchanged.
4089 	 */
4090 	static
4091 	SCIP_RETCODE enforceIndicators(
4092 	   SCIP*                 scip,               /**< SCIP pointer */
4093 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4094 	   int                   nconss,             /**< number of constraints */
4095 	   SCIP_CONS**           conss,              /**< indicator constraints */
4096 	   SCIP_SOL*             sol,                /**< solution to be enforced (NULL for LP solution) */
4097 	   SCIP_ENFOSEPATYPE     enfosepatype,       /**< type of enforcing/separating type */
4098 	   SCIP_Bool             genlogicor,         /**< whether logicor constraint should be generated */
4099 	   SCIP_RESULT*          result              /**< result */
4100 	   )
4101 	{
4102 	   SCIP_CONSDATA* consdata;
4103 	   SCIP_CONSHDLRDATA* conshdlrdata;
4104 	   SCIP_NODE* node1;
4105 	   SCIP_NODE* node2;
4106 	   SCIP_VAR* slackvar;
4107 	   SCIP_VAR* binvar;
4108 	   SCIP_CONS* branchCons = NULL;
4109 	   SCIP_Real maxSlack = -1.0;
4110 	   SCIP_Bool someLinconsNotActive = FALSE;
4111 	   int c;
4112 	
4113 	   assert( scip != NULL );
4114 	   assert( conshdlr != NULL );
4115 	   assert( conss != NULL );
4116 	   assert( result != NULL );
4117 	
4118 	   *result = SCIP_FEASIBLE;
4119 	
4120 	   SCIPdebugMsg(scip, "Enforcing indicator constraints for <%s> ...\n", SCIPconshdlrGetName(conshdlr) );
4121 	
4122 	   /* get constraint handler data */
4123 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
4124 	   assert( conshdlrdata != NULL );
4125 	
4126 	#ifdef SCIP_OUTPUT
4127 	   SCIP_CALL( SCIPwriteTransProblem(scip, "ind.cip", "cip", FALSE) );
4128 	#endif
4129 	
4130 	   /* check each constraint */
4131 	   for (c = 0; c < nconss; ++c)
4132 	   {
4133 	      SCIP_Bool cutoff;
4134 	      SCIP_Real valSlack;
4135 	      int cnt;
4136 	
4137 	      assert( conss[c] != NULL );
4138 	      consdata = SCIPconsGetData(conss[c]);
4139 	      assert( consdata != NULL );
4140 	      assert( consdata->lincons != NULL );
4141 	
4142 	      /* if the linear constraint has not been generated, we do nothing */
4143 	      if ( ! consdata->linconsactive )
4144 	      {
4145 	         someLinconsNotActive = TRUE;
4146 	         continue;
4147 	      }
4148 	
4149 	      /* first perform propagation (it might happen that standard propagation is turned off) */
4150 	      SCIP_CALL( propIndicator(scip, conss[c], consdata,
4151 	            conshdlrdata->dualreductions && SCIPallowStrongDualReds(scip), conshdlrdata->addopposite,
4152 	            &cutoff, &cnt) );
4153 	      if ( cutoff )
4154 	      {
4155 	         SCIPdebugMsg(scip, "Propagation in enforcing <%s> detected cutoff.\n", SCIPconsGetName(conss[c]));
4156 	         *result = SCIP_CUTOFF;
4157 	         return SCIP_OKAY;
4158 	      }
4159 	      if ( cnt > 0 )
4160 	      {
4161 	         SCIPdebugMsg(scip, "Propagation in enforcing <%s> reduced domains: %d.\n", SCIPconsGetName(conss[c]), cnt);
4162 	         *result = SCIP_REDUCEDDOM;
4163 	         return SCIP_OKAY;
4164 	      }
4165 	
4166 	      /* check whether constraint is infeasible */
4167 	      binvar = consdata->binvar;
4168 	      valSlack = SCIPgetSolVal(scip, sol, consdata->slackvar);
4169 	      assert( ! SCIPisFeasNegative(scip, valSlack) );
4170 	      if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, binvar)) && ! SCIPisFeasZero(scip, valSlack) )
4171 	      {
4172 	         /* binary variable is not fixed - otherwise we would not be infeasible */
4173 	         assert( SCIPvarGetLbLocal(binvar) < 0.5 && SCIPvarGetUbLocal(binvar) > 0.5 );
4174 	
4175 	         if ( valSlack > maxSlack )
4176 	         {
4177 	            maxSlack = valSlack;
4178 	            branchCons = conss[c];
4179 	#ifdef SCIP_OUTPUT
4180 	            SCIPinfoMessage(scip, NULL, "Violated indicator constraint:\n");
4181 	            SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) );
4182 	            SCIPinfoMessage(scip, NULL, ";\n");
4183 	            SCIPinfoMessage(scip, NULL, "Corresponding linear constraint:\n");
4184 	            SCIP_CALL( SCIPprintCons(scip, consdata->lincons, NULL) );
4185 	            SCIPinfoMessage(scip, NULL, ";\n");
4186 	#endif
4187 	         }
4188 	      }
4189 	   }
4190 	
4191 	   /* if some constraint has a linear constraint that is not active, we need to check feasibility via the alternative polyhedron */
4192 	   if ( (someLinconsNotActive || conshdlrdata->enforcecuts) && conshdlrdata->sepaalternativelp )
4193 	   {
4194 	      SCIP_Bool cutoff;
4195 	      int ngen;
4196 	
4197 	      SCIP_CALL( enforceCuts(scip, conshdlr, nconss, conss, sol, enfosepatype, genlogicor, &cutoff, &ngen) );
4198 	      if ( cutoff )
4199 	      {
4200 	         conshdlrdata->niiscutsgen += ngen;
4201 	         *result = SCIP_CUTOFF;
4202 	         return SCIP_OKAY;
4203 	      }
4204 	
4205 	      if ( ngen > 0 )
4206 	      {
4207 	         conshdlrdata->niiscutsgen += ngen;
4208 	         if ( genlogicor )
4209 	         {
4210 	            SCIPdebugMsg(scip, "Generated %d constraints.\n", ngen);
4211 	            *result = SCIP_CONSADDED;
4212 	         }
4213 	         else
4214 	         {
4215 	            SCIPdebugMsg(scip, "Generated %d cuts.\n", ngen);
4216 	            *result = SCIP_SEPARATED;
4217 	         }
4218 	         return SCIP_OKAY;
4219 	      }
4220 	      SCIPdebugMsg(scip, "Enforcing produced no cuts.\n");
4221 	
4222 	      assert( ! someLinconsNotActive || branchCons == NULL );
4223 	   }
4224 	
4225 	   /* if all constraints are feasible */
4226 	   if ( branchCons == NULL )
4227 	   {
4228 	      SCIPdebugMsg(scip, "All indicator constraints are feasible.\n");
4229 	      return SCIP_OKAY;
4230 	   }
4231 	
4232 	   /* skip branching if required */
4233 	   if ( ! conshdlrdata->branchindicators )
4234 	   {
4235 	      *result = SCIP_INFEASIBLE;
4236 	      return SCIP_OKAY;
4237 	   }
4238 	
4239 	   /* otherwise create branches */
4240 	   SCIPdebugMsg(scip, "Branching on constraint <%s> (slack value: %f).\n", SCIPconsGetName(branchCons), maxSlack);
4241 	   consdata = SCIPconsGetData(branchCons);
4242 	   assert( consdata != NULL );
4243 	   binvar = consdata->binvar;
4244 	   slackvar = consdata->slackvar;
4245 	
4246 	   /* node1: binvar = 1, slackvar = 0 */
4247 	   SCIP_CALL( SCIPcreateChild(scip, &node1, 0.0, SCIPcalcChildEstimate(scip, binvar, 1.0) ) );
4248 	
4249 	   if ( SCIPvarGetLbLocal(binvar) < 0.5 )
4250 	   {
4251 	      SCIP_CALL( SCIPchgVarLbNode(scip, node1, binvar, 1.0) );
4252 	   }
4253 	
4254 	   /* if slack-variable is multi-aggregated */
4255 	   assert( SCIPvarGetStatus(slackvar) != SCIP_VARSTATUS_MULTAGGR );
4256 	   if ( ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(slackvar)) )
4257 	   {
4258 	      SCIP_CALL( SCIPchgVarUbNode(scip, node1, slackvar, 0.0) );
4259 	   }
4260 	
4261 	   /* node2: binvar = 0, no restriction on slackvar */
4262 	   SCIP_CALL( SCIPcreateChild(scip, &node2, 0.0, SCIPcalcChildEstimate(scip, binvar, 0.0) ) );
4263 	
4264 	   if ( SCIPvarGetUbLocal(binvar) > 0.5 )
4265 	   {
4266 	      SCIP_CALL( SCIPchgVarUbNode(scip, node2, binvar, 0.0) );
4267 	   }
4268 	
4269 	   SCIP_CALL( SCIPresetConsAge(scip, branchCons) );
4270 	   *result = SCIP_BRANCHED;
4271 	
4272 	   return SCIP_OKAY;
4273 	}
4274 	
4275 	
4276 	/** separate IIS-cuts via rounding
4277 	 *
4278 	 *  @todo Check whether the cover produced at the end is a feasible solution.
4279 	 */
4280 	static
4281 	SCIP_RETCODE separateIISRounding(
4282 	   SCIP*                 scip,               /**< SCIP pointer */
4283 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4284 	   SCIP_SOL*             sol,                /**< solution to be separated */
4285 	   SCIP_ENFOSEPATYPE     enfosepatype,       /**< type of enforcing/separating type */
4286 	   int                   nconss,             /**< number of constraints */
4287 	   SCIP_CONS**           conss,              /**< indicator constraints */
4288 	   int                   maxsepacuts,        /**< maximal number of cuts to be generated */
4289 	   SCIP_Bool*            cutoff,             /**< whether we detected a cutoff by an infeasible inequality */
4290 	   int*                  nGen                /**< number of domain changes */
4291 	   )
4292 	{ /*lint --e{850}*/
4293 	   SCIP_CONSHDLRDATA* conshdlrdata;
4294 	   SCIP_LPI* lp;
4295 	   int rounds;
4296 	   SCIP_Real threshold;
4297 	   SCIP_Bool* S;
4298 	   SCIP_Bool error;
4299 	   int oldsize = -1;
4300 	   SCIPdebug( int nGenOld = *nGen; )
4301 	
4302 	   assert( scip != NULL );
4303 	   assert( conshdlr != NULL );
4304 	   assert( conss != NULL );
4305 	   assert( cutoff != NULL );
4306 	   assert( nGen != NULL );
4307 	
4308 	   if ( *nGen >= maxsepacuts )
4309 	      return SCIP_OKAY;
4310 	
4311 	   *cutoff = FALSE;
4312 	   rounds = 0;
4313 	
4314 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
4315 	   assert( conshdlrdata != NULL );
4316 	   lp = conshdlrdata->altlp;
4317 	   assert( lp != NULL );
4318 	
4319 	   SCIPdebugMsg(scip, "Separating IIS-cuts by rounding ...\n");
4320 	
4321 	#ifndef NDEBUG
4322 	   SCIP_CALL( checkLPBoundsClean(scip, lp, nconss, conss) );
4323 	#endif
4324 	
4325 	   /* change coefficients of bounds in alternative LP */
4326 	   if ( conshdlrdata->updatebounds )
4327 	   {
4328 	      /* update to local bounds */
4329 	      SCIP_CALL( updateFirstRow(scip, conshdlrdata) );
4330 	   }
4331 	
4332 	   /* possibly update upper bound */
4333 	   SCIP_CALL( updateObjUpperbound(scip, conshdlr, conshdlrdata) );
4334 	
4335 	   /* scale first row if necessary */
4336 	   SCIP_CALL( scaleFirstRow(scip, conshdlrdata) );
4337 	
4338 	   /* set objective function to current solution */
4339 	   SCIP_CALL( setAltLPObj(scip, lp, sol, nconss, conss) );
4340 	
4341 	   SCIP_CALL( SCIPallocBufferArray(scip, &S, nconss) );
4342 	
4343 	   /* loop through the possible thresholds */
4344 	   for (threshold = conshdlrdata->roundingmaxthres;
4345 	        rounds < conshdlrdata->maxroundingrounds && threshold >= conshdlrdata->roundingminthres && *nGen < maxsepacuts && ! (*cutoff);
4346 	        threshold -= conshdlrdata->roundingoffset )
4347 	   {
4348 	      SCIP_Real value = 0.0;
4349 	      int size = 0;
4350 	      int nCuts = 0;
4351 	      int j;
4352 	#ifdef SCIP_DEBUG
4353 	      int nvarsone = 0;
4354 	      int nvarszero = 0;
4355 	      int nvarsfrac = 0;
4356 	#endif
4357 	
4358 	      SCIPdebugMsg(scip, "Threshold: %g.\n", threshold);
4359 	
4360 	      /* choose variables that have a value < current threshold value */
4361 	      for (j = 0; j < nconss; ++j)
4362 	      {
4363 	         SCIP_CONSDATA* consdata;
4364 	         SCIP_Real binvarval;
4365 	         SCIP_VAR* binvarneg;
4366 	
4367 	         assert( conss[j] != NULL );
4368 	         consdata = SCIPconsGetData(conss[j]);
4369 	         assert( consdata != NULL );
4370 	
4371 	         binvarval = SCIPgetVarSol(scip, consdata->binvar);
4372 	
4373 	#ifdef SCIP_DEBUG
4374 	         if ( SCIPisFeasEQ(scip, binvarval, 1.0) )
4375 	            ++nvarsone;
4376 	         else if ( SCIPisFeasZero(scip, binvarval) )
4377 	            ++nvarszero;
4378 	         else
4379 	            ++nvarsfrac;
4380 	#endif
4381 	
4382 	         /* check whether complementary (negated) variable is present as well */
4383 	         binvarneg = SCIPvarGetNegatedVar(consdata->binvar);
4384 	         assert( binvarneg != NULL );
4385 	
4386 	         /* negated variable is present as well */
4387 	         assert( conshdlrdata->binvarhash != NULL );
4388 	         if ( SCIPhashmapExists(conshdlrdata->binvarhash, (void*) binvarneg) )
4389 	         {
4390 	            SCIP_Real binvarnegval = SCIPgetVarSol(scip, binvarneg);
4391 	
4392 	            /* take larger one */
4393 	            if ( binvarval > binvarnegval )
4394 	               S[j] = TRUE;
4395 	            else
4396 	               S[j] = FALSE;
4397 	            continue;
4398 	         }
4399 	
4400 	         /* check for threshold */
4401 	         if ( SCIPisFeasLT(scip, SCIPgetVarSol(scip, consdata->binvar), threshold) )
4402 	         {
4403 	            S[j] = TRUE;
4404 	            value += varGetObjDelta(consdata->binvar);
4405 	            ++size;
4406 	         }
4407 	         else
4408 	            S[j] = FALSE;
4409 	      }
4410 	
4411 	      if ( size == nconss )
4412 	      {
4413 	         SCIPdebugMsg(scip, "All variables in the set. Continue ...\n");
4414 	         continue;
4415 	      }
4416 	
4417 	      /* skip computation if size has not changed (computation is likely the same) */
4418 	      if ( size == oldsize )
4419 	      {
4420 	         SCIPdebugMsg(scip, "Skipping computation: size support has not changed.\n");
4421 	         continue;
4422 	      }
4423 	      oldsize = size;
4424 	
4425 	#ifdef SCIP_DEBUG
4426 	      SCIPdebugMsg(scip, "   Vars with value 1: %d  0: %d  and fractional: %d.\n", nvarsone, nvarszero, nvarsfrac);
4427 	#endif
4428 	
4429 	      /* fix the variables in S */
4430 	      SCIP_CALL( fixAltLPVariables(scip, lp, nconss, conss, S) );
4431 	
4432 	      /* extend set S to a cover and generate cuts */
4433 	      SCIP_CALL( extendToCover(scip, conshdlr, conshdlrdata, lp, sol, enfosepatype, conshdlrdata->removable, conshdlrdata->genlogicor,
4434 	            nconss, conss, S, &size, &value, &error, cutoff, &nCuts) );
4435 	
4436 	      /* we ignore errors in extendToCover */
4437 	      if ( nCuts > 0 )
4438 	      {
4439 	         *nGen += nCuts;
4440 	         ++rounds;
4441 	      }
4442 	      else
4443 	      {
4444 	         /* possibly update upper bound */
4445 	         SCIP_CALL( updateObjUpperbound(scip, conshdlr, conshdlrdata) );
4446 	      }
4447 	
4448 	      /* reset bounds */
4449 	      SCIP_CALL( unfixAltLPVariables(scip, lp, nconss, conss, S) );
4450 	   }
4451 	   SCIPdebug( SCIPdebugMsg(scip, "Generated %d IISs.\n", *nGen - nGenOld); )
4452 	
4453 	#ifndef NDEBUG
4454 	   SCIP_CALL( checkLPBoundsClean(scip, lp, nconss, conss) );
4455 	#endif
4456 	
4457 	   SCIPfreeBufferArray(scip, &S);
4458 	
4459 	   return SCIP_OKAY;
4460 	}
4461 	
4462 	
4463 	
4464 	/** separate cuts based on perspective formulation
4465 	 *
4466 	 *  Hijazi, Bonami, and Ouorou (2014) introduced the following cuts: We consider an indicator constraint
4467 	 *  \f[
4468 	 *  y = 1 \rightarrow \alpha^T x \leq \beta
4469 	 *  \f]
4470 	 *  and assume finite bounds \f$\ell \leq x \leq u\f$. Then for \f$I \subseteq \{1, \dots, n\}\f$ define
4471 	 *  \f[
4472 	 *    \Sigma(I,x,y) = \sum_{i \notin I} \alpha_i x_i +
4473 	 *    y \Big(\sum_{i \in I, \alpha_i < 0} \alpha_i u_i + \sum_{i \in I, \alpha_i > 0} \alpha_i \ell_i +
4474 	 *    \sum_{i \notin I, \alpha_i < 0} \alpha_i \ell_i + \sum_{i \notin I, \alpha_i > 0} \alpha_i u_i - \beta\Big).
4475 	 *  \f]
4476 	 *  Then the cuts
4477 	 *  \f[
4478 	 *  \Sigma(I,x,y) \leq \sum_{i \notin I, \alpha_i < 0} \alpha_i \ell_i + \sum_{i \notin I, \alpha_i > 0} \alpha_i u_i
4479 	 *  \f]
4480 	 *  are valid for the disjunction
4481 	 *  \f[
4482 	 *  \{y = 0,\; \ell \leq x \leq u\} \cup \{y = 1,\; \ell \leq x \leq u,\; \alpha^T x \leq \beta\}.
4483 	 *  \f]
4484 	 *  These cuts can easily be separated for a given point \f$(x^*, y^*)\f$ by checking for each \f$i \in \{1, \dots, n\}\f$ whether
4485 	 *  \f[
4486 	 *  y^*(\alpha_i\, u_i\, [\alpha_i < 0] + \alpha_i\, \ell_i\, [\alpha_i > 0]) >
4487 	 *  \alpha_i x_i^* + y^* )\alpha_i \ell_i [\alpha_i < 0] + \alpha_i u_i [\alpha_i > 0]),
4488 	 *  \f]
4489 	 *  where \f$[C] = 1\f$ if condition \f$C\f$ is satisfied, otherwise it is 0.
4490 	 *  If the above inequality holds, \f$i\f$ is included in \f$I\f$, otherwise not.
4491 	 */
4492 	static
4493 	SCIP_RETCODE separatePerspective(
4494 	   SCIP*                 scip,               /**< SCIP pointer */
4495 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4496 	   SCIP_SOL*             sol,                /**< solution to be separated */
4497 	   int                   nconss,             /**< number of constraints */
4498 	   SCIP_CONS**           conss,              /**< indicator constraints */
4499 	   int                   maxsepacuts,        /**< maximal number of cuts to be generated */
4500 	   int*                  nGen                /**< number of generated cuts */
4501 	   )
4502 	{  /*lint --e{850}*/
4503 	   SCIP_CONSHDLRDATA* conshdlrdata;
4504 	   SCIP_VAR** cutvars;
4505 	   SCIP_Real* cutvals;
4506 	   int nvars;
4507 	   int c;
4508 	
4509 	   assert( scip != NULL );
4510 	   assert( conshdlr != NULL );
4511 	   assert( conss != NULL );
4512 	   assert( nGen != NULL );
4513 	
4514 	   if ( *nGen >= maxsepacuts )
4515 	      return SCIP_OKAY;
4516 	
4517 	   nvars = SCIPgetNVars(scip);
4518 	   SCIP_CALL( SCIPallocBufferArray(scip, &cutvars, nvars+1) );
4519 	   SCIP_CALL( SCIPallocBufferArray(scip, &cutvals, nvars+1) );
4520 	
4521 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
4522 	   assert( conshdlrdata != NULL );
4523 	
4524 	   /* loop through constraints */
4525 	   for (c = 0; c < nconss; ++c)
4526 	   {
4527 	      SCIP_CONSDATA* consdata;
4528 	      SCIP_CONS* lincons;
4529 	      SCIP_VAR* slackvar;
4530 	      SCIP_VAR* binvar;
4531 	      SCIP_Real binval;
4532 	
4533 	      assert( conss[c] != NULL );
4534 	      consdata = SCIPconsGetData(conss[c]);
4535 	      assert( consdata != NULL );
4536 	      slackvar = consdata->slackvar;
4537 	
4538 	      lincons = consdata->lincons;
4539 	      assert( lincons != NULL );
4540 	
4541 	      binvar = consdata->binvar;
4542 	      assert( binvar != NULL );
4543 	      binval = SCIPgetSolVal(scip, sol, binvar);
4544 	
4545 	      if ( SCIPconsIsActive(lincons) )
4546 	      {
4547 	         SCIP_VAR** linvars;
4548 	         SCIP_Real* linvals;
4549 	         SCIP_Real linrhs;
4550 	         SCIP_Bool finitebound = TRUE;
4551 	         SCIP_Real cutrhs = 0.0;
4552 	         SCIP_Real cutval;
4553 	         SCIP_Real signfactor = 1.0;
4554 	         SCIP_Real ypart;
4555 	         SCIP_Bool islocal = FALSE;
4556 	         int nlinvars;
4557 	         int cnt = 0;
4558 	         int j;
4559 	
4560 	         linvars = SCIPgetVarsLinear(scip, lincons);
4561 	         linvals = SCIPgetValsLinear(scip, lincons);
4562 	         nlinvars = SCIPgetNVarsLinear(scip, lincons);
4563 	
4564 	         linrhs = SCIPgetRhsLinear(scip, lincons);
4565 	         if ( SCIPisInfinity(scip, linrhs) )
4566 	         {
4567 	            if ( ! SCIPisInfinity(scip, SCIPgetLhsLinear(scip, lincons)) )
4568 	            {
4569 	               linrhs = -SCIPgetLhsLinear(scip, lincons);
4570 	               signfactor = -1.0;
4571 	            }
4572 	            else
4573 	               continue;
4574 	         }
4575 	         ypart = -linrhs;
4576 	         cutval = binval * ypart;
4577 	
4578 	         for (j = 0; j < nlinvars; ++j)
4579 	         {
4580 	            SCIP_Real linval;
4581 	            SCIP_Real lb;
4582 	            SCIP_Real ub;
4583 	            SCIP_Real din = 0.0;
4584 	            SCIP_Real dout = 0.0;
4585 	            SCIP_Real xpart;
4586 	            SCIP_Real xval;
4587 	
4588 	            if ( linvars[j] == slackvar )
4589 	               continue;
4590 	
4591 	            if ( conshdlrdata->sepapersplocal )
4592 	            {
4593 	               lb = SCIPvarGetLbLocal(linvars[j]);
4594 	               ub = SCIPvarGetUbLocal(linvars[j]);
4595 	
4596 	               if ( lb > SCIPvarGetLbGlobal(linvars[j]) )
4597 	                  islocal = TRUE;
4598 	               if ( ub < SCIPvarGetUbGlobal(linvars[j]) )
4599 	                  islocal = TRUE;
4600 	            }
4601 	            else
4602 	            {
4603 	               lb = SCIPvarGetLbGlobal(linvars[j]);
4604 	               ub = SCIPvarGetUbGlobal(linvars[j]);
4605 	            }
4606 	
4607 	            /* skip cases with unbounded variables */
4608 	            if ( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
4609 	            {
4610 	               finitebound = FALSE;
4611 	               break;
4612 	            }
4613 	
4614 	            /* compute rest parts for i in the set (din) or not in the set (dout) */
4615 	            linval = signfactor * linvals[j];
4616 	            if ( SCIPisNegative(scip, linval) )
4617 	            {
4618 	               din += linval * ub;
4619 	               dout += linval * lb;
4620 	            }
4621 	            else if ( SCIPisPositive(scip, linval) )
4622 	            {
4623 	               din += linval * lb;
4624 	               dout += linval * ub;
4625 	            }
4626 	
4627 	            xval = SCIPgetSolVal(scip, sol, linvars[j]);
4628 	            xpart = linval * xval;
4629 	
4630 	            /* if din > dout, we want to include i in the set */
4631 	            if ( SCIPisGT(scip, binval * din, binval * dout + xpart) )
4632 	            {
4633 	               ypart += din;
4634 	               cutval += binval * din;
4635 	            }
4636 	            else
4637 	            {
4638 	               /* otherwise i is not in the set */
4639 	               ypart += dout;
4640 	
4641 	               cutrhs += dout;
4642 	               cutval += binval * dout + xpart;
4643 	
4644 	               cutvars[cnt] = linvars[j];
4645 	               cutvals[cnt++] = linval;
4646 	            }
4647 	         }
4648 	
4649 	         if ( ! finitebound )
4650 	            continue;
4651 	
4652 	         if ( SCIPisEfficacious(scip, cutval - cutrhs) )
4653 	         {
4654 	            SCIP_ROW* row;
4655 	            SCIP_Bool infeasible;
4656 	            char name[50];
4657 	
4658 	            /* add y-variable */
4659 	            cutvars[cnt] = binvar;
4660 	            cutvals[cnt] = ypart;
4661 	            ++cnt;
4662 	
4663 	            SCIPdebugMsg(scip, "Found cut of lhs value %f > %f.\n", cutval, cutrhs);
4664 	            (void) SCIPsnprintf(name, 50, "persp%d", conshdlrdata->nperspcutsgen + *nGen);
4665 	            SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conss[c], name, -SCIPinfinity(scip), cutrhs, islocal, FALSE, conshdlrdata->removable) );
4666 	            SCIP_CALL( SCIPaddVarsToRow(scip, row, cnt, cutvars, cutvals) );
4667 	#ifdef SCIP_OUTPUT
4668 	            SCIP_CALL( SCIPprintRow(scip, row, NULL) );
4669 	#endif
4670 	            SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
4671 	            assert( ! infeasible );
4672 	            SCIP_CALL( SCIPreleaseRow(scip, &row));
4673 	            SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
4674 	            ++(*nGen);
4675 	         }
4676 	      }
4677 	      if ( *nGen >= maxsepacuts )
4678 	         break;
4679 	   }
4680 	
4681 	   SCIPfreeBufferArray(scip, &cutvals);
4682 	   SCIPfreeBufferArray(scip, &cutvars);
4683 	
4684 	   return SCIP_OKAY;
4685 	}
4686 	
4687 	
4688 	/** separation method
4689 	 *
4690 	 *  We first check whether coupling inequalities can be separated (if required). If not enough of
4691 	 *  these could be generated, we check whether IIS inequalities can be separated.
4692 	 */
4693 	static
4694 	SCIP_RETCODE separateIndicators(
4695 	   SCIP*                 scip,               /**< SCIP pointer */
4696 	   SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4697 	   int                   nconss,             /**< number of constraints */
4698 	   int                   nusefulconss,       /**< number of useful constraints */
4699 	   SCIP_CONS**           conss,              /**< indicator constraints */
4700 	   SCIP_SOL*             sol,                /**< solution to be separated */
4701 	   SCIP_ENFOSEPATYPE     enfosepatype,       /**< type of enforcing/separating type */
4702 	   SCIP_RESULT*          result              /**< result */
4703 	   )
4704 	{
4705 	   SCIP_CONSHDLRDATA* conshdlrdata;
4706 	   int maxsepacuts;
4707 	   int ncuts;
4708 	
4709 	   assert( scip != NULL );
4710 	   assert( conshdlr != NULL );
4711 	   assert( conss != NULL );
4712 	   assert( result != NULL );
4713 	
4714 	   *result = SCIP_DIDNOTRUN;
4715 	
4716 	   if ( nconss == 0 )
4717 	      return SCIP_OKAY;
4718 	
4719 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
4720 	   assert( conshdlrdata != NULL );
4721 	   ncuts = 0;
4722 	
4723 	   /* get the maximal number of cuts allowed in a separation round */
4724 	   if ( SCIPgetDepth(scip) == 0 )
4725 	      maxsepacuts = conshdlrdata->maxsepacutsroot;
4726 	   else
4727 	      maxsepacuts = conshdlrdata->maxsepacuts;
4728 	
4729 	   /* first separate coupling inequalities (if required) */
4730 	   if ( conshdlrdata->sepacouplingcuts )
4731 	   {
4732 	      int c;
4733 	
4734 	      *result = SCIP_DIDNOTFIND;
4735 	
4736 	      /* check each constraint */
4737 	      for (c = 0; c < nusefulconss && ncuts < maxsepacuts; ++c)
4738 	      {
4739 	         SCIP_CONSDATA* consdata;
4740 	         SCIP_Bool islocal;
4741 	         SCIP_Real ub;
4742 	
4743 	         assert( conss != NULL );
4744 	         assert( conss[c] != NULL );
4745 	         consdata = SCIPconsGetData(conss[c]);
4746 	         assert( consdata != NULL );
4747 	         assert( consdata->slackvar != NULL );
4748 	         assert( consdata->binvar != NULL );
4749 	
4750 	         /* get upper bound for slack variable in linear constraint */
4751 	         islocal = FALSE;
4752 	         if ( conshdlrdata->sepacouplinglocal )
4753 	         {
4754 	            ub = SCIPvarGetUbLocal(consdata->slackvar);
4755 	            if ( ub < SCIPvarGetUbGlobal(consdata->slackvar) )
4756 	               islocal = TRUE;
4757 	         }
4758 	         else
4759 	            ub = SCIPvarGetUbGlobal(consdata->slackvar);
4760 	         assert( ! SCIPisFeasNegative(scip, ub) );
4761 	
4762 	         /* only use coefficients that are not too large */
4763 	         if ( ub <= conshdlrdata->sepacouplingvalue )
4764 	         {
4765 	            SCIP_Real activity;
4766 	
4767 	            activity = SCIPgetSolVal(scip, sol, consdata->slackvar) + ub * SCIPgetSolVal(scip, sol, consdata->binvar) - ub;
4768 	            if ( SCIPisEfficacious(scip, activity) )
4769 	            {
4770 	               SCIP_ROW* row;
4771 	               SCIP_Bool infeasible;
4772 	#ifndef NDEBUG
4773 	               char name[50];
4774 	
4775 	               (void) SCIPsnprintf(name, 50, "couple%d", c);
4776 	               SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conss[c], name, -SCIPinfinity(scip), ub, islocal, FALSE, conshdlrdata->removable) );
4777 	#else
4778 	               SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conss[c], "", -SCIPinfinity(scip), ub, islocal, FALSE, conshdlrdata->removable) );
4779 	#endif
4780 	               SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
4781 	
4782 	               SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->slackvar, 1.0) );
4783 	               SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->binvar, ub) );
4784 	               SCIP_CALL( SCIPflushRowExtensions(scip, row) );
4785 	
4786 	               SCIPdebugMsg(scip, "Separated coupling inequality for indicator constraint <%s> (coeff: %f).\n", SCIPconsGetName(conss[c]), ub);
4787 	#ifdef SCIP_OUTPUT
4788 	               SCIP_CALL( SCIPprintRow(scip, row, NULL) );
4789 	#endif
4790 	               SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
4791 	               assert( ! infeasible );
4792 	               SCIP_CALL( SCIPreleaseRow(scip, &row));
4793 	
4794 	               SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
4795 	               *result = SCIP_SEPARATED;
4796 	
4797 	               ++ncuts;
4798 	            }
4799 	         }
4800 	      }
4801 	      SCIPdebugMsg(scip, "Number of separated coupling inequalities: %d.\n", ncuts);
4802 	   }
4803 	
4804 	   /* separate cuts from the alternative lp (if required) */
4805 	   if ( conshdlrdata->sepaalternativelp && ncuts < SEPAALTTHRESHOLD )
4806 	   {
4807 	      SCIP_Bool cutoff;
4808 	      int noldcuts;
4809 	
4810 	      SCIPdebugMsg(scip, "Separating inequalities for indicator constraints.\n");
4811 	
4812 	      noldcuts = ncuts;
4813 	      if ( *result == SCIP_DIDNOTRUN )
4814 	         *result = SCIP_DIDNOTFIND;
4815 	
4816 	      /* start separation */
4817 	      SCIP_CALL( separateIISRounding(scip, conshdlr, sol, enfosepatype, nconss, conss, maxsepacuts, &cutoff, &ncuts) );
4818 	      SCIPdebugMsg(scip, "Separated %d cuts from indicator constraints.\n", ncuts - noldcuts);
4819 	
4820 	      if ( cutoff )
4821 	         *result = SCIP_CUTOFF;
4822 	      else if ( ncuts > noldcuts )
4823 	      {
4824 	         conshdlrdata->niiscutsgen += ncuts;
4825 	
4826 	         /* possibly overwrite result from separation above */
4827 	         if ( conshdlrdata->genlogicor )
4828 	            *result = SCIP_CONSADDED;
4829 	         else
4830 	            *result = SCIP_SEPARATED;
4831 	      }
4832 	   }
4833 	
4834 	   /* separate cuts based on perspective formulation */
4835 	   if ( conshdlrdata->sepaperspective && ncuts < SEPAALTTHRESHOLD )
4836 	   {
4837 	      int noldcuts;
4838 	
4839 	      SCIPdebugMsg(scip, "Separating inequalities based on perspective formulation.\n");
4840 	
4841 	      noldcuts = ncuts;
4842 	      if ( *result == SCIP_DIDNOTRUN )
4843 	         *result = SCIP_DIDNOTFIND;
4844 	
4845 	      /* start separation */
4846 	      SCIP_CALL( separatePerspective(scip, conshdlr, sol, nconss, conss, maxsepacuts, &ncuts) );
4847 	      SCIPdebugMsg(scip, "Separated %d cuts from perspective formulation.\n", ncuts - noldcuts);
4848 	
4849 	      if ( ncuts > noldcuts )
4850 	      {
4851 	         conshdlrdata->nperspcutsgen += ncuts;
4852 	
4853 	         /* possibly overwrite result from separation above */
4854 	         *result = SCIP_SEPARATED;
4855 	      }
4856 	   }
4857 	
4858 	   return SCIP_OKAY;
4859 	}
4860 	
4861 	
4862 	/** initializes the constraint handler data */
4863 	static
4864 	void initConshdlrData(
4865 	   SCIP*                 scip,               /**< SCIP pointer */
4866 	   SCIP_CONSHDLRDATA*    conshdlrdata        /**< constraint handler data */
4867 	   )
4868 	{
4869 	   assert( conshdlrdata != NULL );
4870 	
4871 	   conshdlrdata->removable = TRUE;
4872 	   conshdlrdata->scaled = FALSE;
4873 	   conshdlrdata->altlp = NULL;
4874 	   conshdlrdata->nrows = 0;
4875 	   conshdlrdata->varhash = NULL;
4876 	   conshdlrdata->slackhash = NULL;
4877 	   conshdlrdata->lbhash = NULL;
4878 	   conshdlrdata->ubhash = NULL;
4879 	   conshdlrdata->nlbbounds = 0;
4880 	   conshdlrdata->nubbounds = 0;
4881 	   conshdlrdata->nslackvars = 0;
4882 	   conshdlrdata->objcutindex = -1;
4883 	   conshdlrdata->objupperbound = SCIPinfinity(scip);
4884 	   conshdlrdata->objaltlpbound = SCIPinfinity(scip);
4885 	   conshdlrdata->roundingminthres = 0.1;
4886 	   conshdlrdata->roundingmaxthres = 0.6;
4887 	   conshdlrdata->maxroundingrounds = MAXROUNDINGROUNDS;
4888 	   conshdlrdata->roundingoffset = 0.1;
4889 	   conshdlrdata->addedcouplingcons = FALSE;
4890 	   conshdlrdata->ninitconss = 0;
4891 	   conshdlrdata->nbinvarszero = 0;
4892 	   conshdlrdata->performedrestart = FALSE;
4893 	   conshdlrdata->objindicatoronly = FALSE;
4894 	   conshdlrdata->objothervarsonly = FALSE;
4895 	   conshdlrdata->minabsobj = 0.0;
4896 	   conshdlrdata->normtype = 'e';
4897 	   conshdlrdata->niiscutsgen = 0;
4898 	   conshdlrdata->nperspcutsgen = 0;
4899 	}
4900 	
4901 	
4902 	/* ---------------------------- upgrading methods -----------------------------------*/
4903 	
4904 	/** tries to upgrade a linear constraint into an indicator constraint
4905 	 *
4906 	 *  For some linear constraint of the form \f$a^T x + \alpha\, y \geq \beta\f$ with \f$y \in \{0,1\}\f$, we can upgrade
4907 	 *  it to an indicator constraint if for the residual value \f$a^T x \geq \gamma\f$, we have \f$\alpha + \gamma \geq
4908 	 *  \beta\f$: in this case, the constraint is always satisfied if \f$y = 1\f$.
4909 	 *
4910 	 *  Similarly, for a linear constraint in the form \f$a^T x + \alpha\, y \leq \beta\f$ with \f$y \in \{0,1\}\f$, we can
4911 	 *  upgrade it to an indicator constraint if for the residual value \f$a^T x \leq \gamma\f$, we have \f$\alpha + \gamma
4912 	 *  \leq \beta\f$.
4913 	 */
4914 	static
4915 	SCIP_DECL_LINCONSUPGD(linconsUpgdIndicator)
4916 	{  /*lint --e{715}*/
4917 	   SCIP_CONSHDLRDATA* conshdlrdata;
4918 	   SCIP_CONSHDLR* conshdlr;
4919 	   SCIP_Real minactivity = 0.0;
4920 	   SCIP_Real maxactivity = 0.0;
4921 	   SCIP_Real maxabsval = -1.0;
4922 	   SCIP_Real secabsval = -1.0;
4923 	   int maxabsvalidx = -1;
4924 	   int j;
4925 	
4926 	   assert( scip != NULL );
4927 	   assert( upgdcons != NULL );
4928 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), "linear") == 0 );
4929 	   assert( ! SCIPconsIsModifiable(cons) );
4930 	
4931 	   /* do not upgrade if there are at most 2 variables (2 variables should be upgraded to a varbound constraint) */
4932 	   if ( nvars <= 2 )
4933 	      return SCIP_OKAY;
4934 	
4935 	   /* cannot currently ranged constraints, since we can only return one constraint (and we would need one for each side each) */
4936 	   if ( ! SCIPisInfinity(scip, -lhs) && ! SCIPisInfinity(scip, rhs) )
4937 	      return SCIP_OKAY;
4938 	
4939 	   /* check whether upgrading is turned on */
4940 	   conshdlr = SCIPfindConshdlr(scip, "indicator");
4941 	   assert( conshdlr != NULL );
4942 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
4943 	   assert( conshdlrdata != NULL );
4944 	
4945 	   if ( ! conshdlrdata->upgradelinear )
4946 	      return SCIP_OKAY;
4947 	
4948 	   /* calculate activities */
4949 	   for (j = 0; j < nvars; ++j)
4950 	   {
4951 	      SCIP_VAR* var;
4952 	      SCIP_Real val;
4953 	      SCIP_Real lb;
4954 	      SCIP_Real ub;
4955 	
4956 	      val = vals[j];
4957 	      assert( ! SCIPisZero(scip, val) );
4958 	
4959 	      var = vars[j];
4960 	      assert( var != NULL );
4961 	
4962 	      /* store maximal (and second to largest) value of coefficients */
4963 	      if ( SCIPisGE(scip, REALABS(val), maxabsval) )
4964 	      {
4965 	         secabsval = maxabsval;
4966 	         maxabsval = REALABS(val);
4967 	         maxabsvalidx = j;
4968 	      }
4969 	
4970 	      if ( ! SCIPvarIsBinary(var) )
4971 	      {
4972 	         if ( val > 0.0 )
4973 	         {
4974 	            lb = SCIPvarGetLbGlobal(var);
4975 	            ub = SCIPvarGetUbGlobal(var);
4976 	         }
4977 	         else
4978 	         {
4979 	            ub = SCIPvarGetLbGlobal(var);
4980 	            lb = SCIPvarGetUbGlobal(var);
4981 	         }
4982 	
4983 	         /* compute minimal activity */
4984 	         if ( SCIPisInfinity(scip, -lb) )
4985 	            minactivity = -SCIPinfinity(scip);
4986 	         else
4987 	         {
4988 	            if ( ! SCIPisInfinity(scip, -minactivity) )
4989 	               minactivity += val * lb;
4990 	         }
4991 	
4992 	         /* compute maximal activity */
4993 	         if ( SCIPisInfinity(scip, ub) )
4994 	            maxactivity = SCIPinfinity(scip);
4995 	         else
4996 	         {
4997 	            if ( ! SCIPisInfinity(scip, maxactivity) )
4998 	               maxactivity += val * ub;
4999 	         }
5000 	      }
5001 	   }
5002 	   assert( maxabsval >= 0.0 );
5003 	   assert( 0 <= maxabsvalidx && maxabsvalidx < nvars );
5004 	
5005 	   /* exit if largest coefficient does not belong to binary variable */
5006 	   if ( ! SCIPvarIsBinary(vars[maxabsvalidx]) )
5007 	      return SCIP_OKAY;
5008 	
5009 	   /* exit if the second largest coefficient is as large as largest */
5010 	   if ( SCIPisEQ(scip, secabsval, maxabsval) )
5011 	      return SCIP_OKAY;
5012 	
5013 	   /* cannot upgrade if all activities are infinity */
5014 	   if ( SCIPisInfinity(scip, -minactivity) && SCIPisInfinity(scip, maxactivity) )
5015 	      return SCIP_OKAY;
5016 	
5017 	   /* check each variable as indicator variable */
5018 	   for (j = 0; j < nvars; ++j)
5019 	   {
5020 	      SCIP_VAR** indconsvars;
5021 	      SCIP_Real* indconsvals;
5022 	      SCIP_Bool upgdlhs = FALSE;
5023 	      SCIP_Bool upgdrhs = FALSE;
5024 	      SCIP_Bool indneglhs = FALSE;
5025 	      SCIP_Bool indnegrhs = FALSE;
5026 	      SCIP_VAR* indvar;
5027 	      SCIP_Real indval;
5028 	      int l;
5029 	
5030 	      indvar = vars[j];
5031 	      indval = vals[j];
5032 	      assert( ! SCIPisZero(scip, indval) );
5033 	
5034 	      if ( ! SCIPvarIsBinary(indvar) )
5035 	         continue;
5036 	
5037 	      /* check for upgrading of lhs */
5038 	      if ( ! SCIPisInfinity(scip, -minactivity) && ! SCIPisInfinity(scip, -lhs) )
5039 	      {
5040 	         /* upgrading is possible with binary variable */
5041 	         if ( SCIPisGE(scip, minactivity, lhs) )
5042 	            upgdlhs = TRUE;
5043 	
5044 	         /* upgrading is possible with negated binary variable */
5045 	         if ( SCIPisGE(scip, minactivity + indval, lhs) )
5046 	         {
5047 	            upgdlhs = TRUE;
5048 	            indneglhs = TRUE;
5049 	         }
5050 	      }
5051 	
5052 	      /* check for upgrading of rhs */
5053 	      if ( ! SCIPisInfinity(scip, maxactivity) && ! SCIPisInfinity(scip, rhs) )
5054 	      {
5055 	         /* upgrading is possible with binary variable */
5056 	         if ( SCIPisLE(scip, maxactivity, rhs) )
5057 	            upgdrhs = TRUE;
5058 	
5059 	         /* upgrading is possible with negated binary variable */
5060 	         if ( SCIPisLE(scip, maxactivity + indval, rhs) )
5061 	         {
5062 	            upgdrhs = TRUE;
5063 	            indnegrhs = TRUE;
5064 	         }
5065 	      }
5066 	
5067 	      /* upgrade constraint */
5068 	      if ( upgdlhs || upgdrhs )
5069 	      {
5070 	         SCIP_VAR* indvar2;
5071 	         SCIP_Real bnd;
5072 	         int cnt = 0;
5073 	
5074 	         assert( ! upgdlhs || ! upgdrhs ); /* cannot treat ranged rows */
5075 	         SCIPdebugMsg(scip, "upgrading constraint <%s> to an indicator constraint.\n", SCIPconsGetName(cons));
5076 	
5077 	         SCIP_CALL( SCIPallocBufferArray(scip, &indconsvars, nvars - 1) );
5078 	         SCIP_CALL( SCIPallocBufferArray(scip, &indconsvals, nvars - 1) );
5079 	
5080 	         /* create constraint */
5081 	         for (l = 0; l < nvars; ++l)
5082 	         {
5083 	            if ( vars[l] == indvar )
5084 	               continue;
5085 	            indconsvars[cnt] = vars[l];
5086 	            if ( upgdlhs )
5087 	               indconsvals[cnt] = -vals[l];
5088 	            else
5089 	               indconsvals[cnt] = vals[l];
5090 	            ++cnt;
5091 	         }
5092 	
5093 	         if ( indneglhs || indnegrhs )
5094 	         {
5095 	            SCIP_CALL( SCIPgetNegatedVar(scip, indvar, &indvar2) );
5096 	         }
5097 	         else
5098 	            indvar2 = indvar;
5099 	
5100 	         if ( upgdlhs )
5101 	         {
5102 	            bnd = -lhs;
5103 	            if ( ! indneglhs )
5104 	               bnd -= indval;
5105 	            SCIP_CALL( SCIPcreateConsIndicator(scip, upgdcons, SCIPconsGetName(cons), indvar2, nvars-1, indconsvars, indconsvals, bnd,
5106 	                  SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),
5107 	                  SCIPconsIsLocal(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
5108 	         }
5109 	         else
5110 	         {
5111 	            bnd = rhs;
5112 	            if ( ! indnegrhs )
5113 	               bnd -= indval;
5114 	            SCIP_CALL( SCIPcreateConsIndicator(scip, upgdcons, SCIPconsGetName(cons), indvar2, nvars-1, indconsvars, indconsvals, bnd,
5115 	                  SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),
5116 	                  SCIPconsIsLocal(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
5117 	         }
5118 	
5119 	#ifdef SCIP_DEBUG
5120 	         SCIPinfoMessage(scip, NULL, "upgrade: \n");
5121 	         SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5122 	         SCIPinfoMessage(scip, NULL, "\n");
5123 	         SCIP_CALL( SCIPprintCons(scip, *upgdcons, NULL) );
5124 	         SCIPinfoMessage(scip, NULL, "\n");
5125 	         SCIP_CALL( SCIPprintCons(scip, SCIPgetLinearConsIndicator(*upgdcons), NULL) );
5126 	         SCIPinfoMessage(scip, NULL, "  (minact: %f, maxact: %f)\n", minactivity, maxactivity);
5127 	#endif
5128 	
5129 	         SCIPfreeBufferArray(scip, &indconsvars);
5130 	         SCIPfreeBufferArray(scip, &indconsvals);
5131 	
5132 	         return SCIP_OKAY;
5133 	      }
5134 	   }
5135 	
5136 	   return SCIP_OKAY;
5137 	}
5138 	
5139 	
5140 	/* ---------------------------- constraint handler callback methods ----------------------*/
5141 	
5142 	/** copy method for constraint handler plugins (called when SCIP copies plugins) */
5143 	static
5144 	SCIP_DECL_CONSHDLRCOPY(conshdlrCopyIndicator)
5145 	{  /*lint --e{715}*/
5146 	   assert( scip != NULL );
5147 	   assert( conshdlr != NULL );
5148 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
5149 	   assert( valid != NULL );
5150 	
5151 	   /* call inclusion method of constraint handler */
5152 	   SCIP_CALL( SCIPincludeConshdlrIndicator(scip) );
5153 	
5154 	   *valid = TRUE;
5155 	
5156 	   return SCIP_OKAY;
5157 	}
5158 	
5159 	
5160 	/** initialization method of constraint handler (called after problem was transformed) */
5161 	static
5162 	SCIP_DECL_CONSINIT(consInitIndicator)
5163 	{  /*lint --e{715}*/
5164 	   SCIP_CONSHDLRDATA* conshdlrdata;
5165 	
5166 	   assert( scip != NULL );
5167 	   assert( conshdlr != NULL );
5168 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
5169 	
5170 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
5171 	   assert( conshdlrdata != NULL );
5172 	
5173 	   initConshdlrData(scip, conshdlrdata);
5174 	
5175 	   /* find trysol heuristic */
5176 	   if ( conshdlrdata->trysolutions && conshdlrdata->heurtrysol == NULL )
5177 	   {
5178 	      conshdlrdata->heurtrysol = SCIPfindHeur(scip, "trysol");
5179 	   }
5180 	
5181 	   return SCIP_OKAY;
5182 	}
5183 	
5184 	
5185 	/** deinitialization method of constraint handler (called before transformed problem is freed) */
5186 	static
5187 	SCIP_DECL_CONSEXIT(consExitIndicator)
5188 	{  /*lint --e{715}*/
5189 	   SCIP_CONSHDLRDATA* conshdlrdata;
5190 	
5191 	   assert( scip != NULL );
5192 	   assert( conshdlr != NULL );
5193 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
5194 	
5195 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
5196 	
5197 	   if ( conshdlrdata->binvarhash != NULL )
5198 	      SCIPhashmapFree(&conshdlrdata->binvarhash);
5199 	
5200 	   SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->addlincons, conshdlrdata->maxaddlincons);
5201 	   conshdlrdata->maxaddlincons = 0;
5202 	   conshdlrdata->naddlincons = 0;
5203 	   conshdlrdata->nrows = 0;
5204 	
5205 	   return SCIP_OKAY;
5206 	}
5207 	
5208 	
5209 	/** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
5210 	static
5211 	SCIP_DECL_CONSFREE(consFreeIndicator)
5212 	{
5213 	   SCIP_CONSHDLRDATA* conshdlrdata;
5214 	
5215 	   assert( scip != NULL );
5216 	   assert( conshdlr != NULL );
5217 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
5218 	
5219 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
5220 	   assert( conshdlrdata != NULL );
5221 	   assert( conshdlrdata->altlp == NULL );
5222 	   assert( conshdlrdata->varhash == NULL );
5223 	   assert( conshdlrdata->lbhash == NULL );
5224 	   assert( conshdlrdata->ubhash == NULL );
5225 	   assert( conshdlrdata->slackhash == NULL );
5226 	
5227 	   if ( conshdlrdata->maxaddlincons > 0 )
5228 	   {
5229 	      /* if problem was not yet transformed the array may need to be freed, because we did not call the EXIT callback */
5230 	      SCIPfreeBlockMemoryArrayNull(scip, &conshdlrdata->addlincons, conshdlrdata->maxaddlincons);
5231 	   }
5232 	   assert( conshdlrdata->addlincons == NULL );
5233 	   conshdlrdata->naddlincons = 0;
5234 	   conshdlrdata->maxaddlincons = 0;
5235 	
5236 	   SCIPfreeBlockMemory(scip, &conshdlrdata);
5237 	
5238 	   return SCIP_OKAY;
5239 	}
5240 	
5241 	
5242 	/** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
5243 	static
5244 	SCIP_DECL_CONSINITSOL(consInitsolIndicator)
5245 	{
5246 	   SCIP_CONSHDLRDATA* conshdlrdata;
5247 	   int c;
5248 	
5249 	   assert( scip != NULL );
5250 	   assert( conshdlr != NULL );
5251 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
5252 	
5253 	   if ( SCIPgetStatus(scip) == SCIP_STATUS_OPTIMAL || SCIPgetStatus(scip) == SCIP_STATUS_INFEASIBLE ||
5254 	        SCIPgetStatus(scip) == SCIP_STATUS_UNBOUNDED || SCIPgetStatus(scip) == SCIP_STATUS_INFORUNBD )
5255 	      return SCIP_OKAY;
5256 	
5257 	   SCIPdebugMsg(scip, "Initsol for indicator constraints.\n");
5258 	
5259 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
5260 	   assert( conshdlrdata != NULL );
5261 	   assert( conshdlrdata->slackhash == NULL );
5262 	
5263 	   SCIP_CALL( SCIPgetCharParam(scip, "separating/efficacynorm", &conshdlrdata->normtype) );
5264 	
5265 	   if ( conshdlrdata->sepaalternativelp )
5266 	   {
5267 	      /* generate hash for storing all slack variables (size is just a guess) */
5268 	      SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->slackhash, SCIPblkmem(scip), SCIPgetNVars(scip)) );
5269 	      assert( conshdlrdata->slackhash != NULL );
5270 	
5271 	      /* first initialize slack hash */
5272 	      for (c = 0; c < nconss; ++c)
5273 	      {
5274 	         SCIP_CONSDATA* consdata;
5275 	
5276 	         assert( conss != NULL );
5277 	         assert( conss[c] != NULL );
5278 	         assert( SCIPconsIsTransformed(conss[c]) );
5279 	
5280 	         consdata = SCIPconsGetData(conss[c]);
5281 	         assert( consdata != NULL );
5282 	
5283 	         assert( consdata->slackvar != NULL );
5284 	
5285 	         /* insert slack variable into hash */
5286 	         SCIP_CALL( SCIPhashmapInsertInt(conshdlrdata->slackhash, consdata->slackvar, INT_MAX) );
5287 	         assert( SCIPhashmapExists(conshdlrdata->slackhash, consdata->slackvar) );
5288 	         ++conshdlrdata->nslackvars;
5289 	      }
5290 	
5291 	      if ( conshdlrdata->genlogicor )
5292 	      {
5293 	         SCIP_CONSHDLR* logicorconshdlr;
5294 	         int logicorsepafreq;
5295 	         int sepafreq;
5296 	
5297 	         /* If we generate logicor constraints, but the separation frequency is not 1, output warning */
5298 	         logicorconshdlr = SCIPfindConshdlr(scip, "logicor");
5299 	         if ( logicorconshdlr == NULL )
5300 	         {
5301 	            SCIPerrorMessage("Logicor constraint handler not included, cannot generate constraints.\n");
5302 	            return SCIP_ERROR;
5303 	         }
5304 	         logicorsepafreq = SCIPconshdlrGetSepaFreq(logicorconshdlr);
5305 	         sepafreq = SCIPconshdlrGetSepaFreq(conshdlr);
5306 	         if ( (sepafreq != -1 || conshdlrdata->enforcecuts) && logicorsepafreq != 1 )
5307 	         {
5308 	            SCIPwarningMessage(scip, "For better performance set parameter 'constraints/logicor/sepafreq' to 1 if 'constraints/included/genlogicor' is true.\n");
5309 	         }
5310 	      }
5311 	   }
5312 	
5313 	   /* check each constraint */
5314 	   conshdlrdata->objothervarsonly = TRUE;
5315 	   for (c = 0; c < nconss; ++c)
5316 	   {
5317 	      SCIP_CONSDATA* consdata;
5318 	
5319 	      assert( conss != NULL );
5320 	      assert( conss[c] != NULL );
5321 	      assert( SCIPconsIsTransformed(conss[c]) );
5322 	
5323 	      consdata = SCIPconsGetData(conss[c]);
5324 	      assert( consdata != NULL );
5325 	      assert( consdata->binvar != NULL );
5326 	      assert( consdata->slackvar != NULL );
5327 	
5328 	      /* Presolving might replace a slack variable by an active variable. Thus, the objective of a slack variables might
5329 	       * be nonzero. However, we do not need to check slack variables here. */
5330 	      if ( ! SCIPisZero(scip, varGetObjDelta(consdata->binvar)) )
5331 	         conshdlrdata->objothervarsonly = FALSE;
5332 	
5333 	      /* deactivate */
5334 	      if ( ! consdata->linconsactive )
5335 	      {
5336 	         SCIP_CALL( SCIPdisableCons(scip, consdata->lincons) );
5337 	      }
5338 	      else
5339 	      {
5340 	         /* add constraint to alternative LP if not already done */
5341 	         if ( conshdlrdata->sepaalternativelp && consdata->colindex < 0 )
5342 	         {
5343 	            SCIP_CALL( addAltLPConstraint(scip, conshdlr, consdata->lincons, consdata->slackvar, 1.0, &consdata->colindex) );
5344 	            SCIPdebugMsg(scip, "Added column for <%s> to alternative LP with column index %d.\n", SCIPconsGetName(conss[c]),consdata->colindex);
5345 	#ifdef SCIP_OUTPUT
5346 	            SCIP_CALL( SCIPprintCons(scip, consdata->lincons, NULL) );
5347 	            SCIPinfoMessage(scip, NULL, ";\n");
5348 	#endif
5349 	         }
5350 	      }
5351 	
5352 	      /* add nlrow representation to NLP, if NLP had been constructed
5353 	       *
5354 	       * Note, that we did not tell SCIP in exitpre that we have something to add to the NLP, thus
5355 	       * indicators are only available in the NLP for MINLPs, but not for MIPs with indicators.
5356 	       */
5357 	      if ( SCIPisNLPConstructed(scip) && SCIPconsIsChecked(conss[c]) )
5358 	      {
5359 	         /* create nonlinear row binary variable * slack variable = 0 */
5360 	         SCIP_NLROW* nlrow;
5361 	         SCIP_EXPR* quadexpr;
5362 	         SCIP_EXPR* varexprs[2];
5363 	
5364 	         SCIP_CALL( SCIPcreateExprVar(scip, &varexprs[0], consdata->binvar, NULL, NULL) );
5365 	         SCIP_CALL( SCIPcreateExprVar(scip, &varexprs[1], consdata->slackvar, NULL, NULL) );
5366 	         SCIP_CALL( SCIPcreateExprProduct(scip, &quadexpr, 2, varexprs, 1.0, NULL, NULL) );
5367 	
5368 	         SCIP_CALL( SCIPcreateNlRow(scip, &nlrow, SCIPconsGetName(conss[c]), 0.0, 0, NULL, NULL, quadexpr, 0.0, 0.0, SCIP_EXPRCURV_UNKNOWN) );
5369 	
5370 	         SCIP_CALL( SCIPreleaseExpr(scip, &quadexpr) );
5371 	         SCIP_CALL( SCIPreleaseExpr(scip, &varexprs[1]) );
5372 	         SCIP_CALL( SCIPreleaseExpr(scip, &varexprs[0]) );
5373 	
5374 	         /* add row to NLP and forget about it */
5375 	         SCIP_CALL( SCIPaddNlRow(scip, nlrow) );
5376 	         SCIP_CALL( SCIPreleaseNlRow(scip, &nlrow) );
5377 	      }
5378 	   }
5379 	
5380 	   SCIPdebugMsg(scip, "Initialized %d indicator constraints.\n", nconss);
5381 	
5382 	   /* check additional constraints */
5383 	   if ( conshdlrdata->sepaalternativelp )
5384 	   {
5385 	      SCIP_CONS* cons;
5386 	      int colindex;
5387 	      int cnt = 0;
5388 	
5389 	      /* add stored linear constraints if they exist */
5390 	      if ( conshdlrdata->naddlincons > 0 )
5391 	      {
5392 	         for (c = 0; c < conshdlrdata->naddlincons; ++c)
5393 	         {
5394 	            cons = conshdlrdata->addlincons[c];
5395 	
5396 	            /* get transformed constraint - since it is needed only here, we do not store the information */
5397 	            if ( ! SCIPconsIsTransformed(cons) )
5398 	            {
5399 	               SCIP_CALL( SCIPgetTransformedCons(scip, conshdlrdata->addlincons[c], &cons) );
5400 	
5401 	               /* @todo check when exactly the transformed constraint does not exist - SCIPisActive() does not suffice */
5402 	               if ( cons == NULL )
5403 	                  continue;
5404 	            }
5405 	            SCIP_CALL( addAltLPConstraint(scip, conshdlr, cons, NULL, 0.0, &colindex) );
5406 	            ++cnt;
5407 	
5408 	#ifdef SCIP_OUTPUT
5409 	            SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5410 	            SCIPinfoMessage(scip, NULL, ";\n");
5411 	#endif
5412 	         }
5413 	         SCIPdebugMsg(scip, "Added %d additional columns to alternative LP.\n", cnt);
5414 	      }
5415 	      else
5416 	      {
5417 	         /* if no stored linear constraints are available, possibly collect other linear constraints; we only use linear
5418 	          * constraints, since most other constraints involve integral variables, and in this context we will likely
5419 	          * benefit much more from continuous variables. */
5420 	         if ( conshdlrdata->useotherconss )
5421 	         {
5422 	            const char* conshdlrname;
5423 	            SCIP_CONS** allconss;
5424 	            int nallconss;
5425 	
5426 	            nallconss = SCIPgetNConss(scip);
5427 	            allconss = SCIPgetConss(scip);
5428 	
5429 	            /* loop through all constraints */
5430 	            for (c = 0; c < nallconss; ++c)
5431 	            {
5432 	               /* get constraint */
5433 	               cons = allconss[c];
5434 	               assert( cons != NULL );
5435 	               assert( SCIPconsIsTransformed(cons) );
5436 	
5437 	               /* get constraint handler name */
5438 	               conshdlrname = SCIPconshdlrGetName(SCIPconsGetHdlr(cons));
5439 	
5440 	               /* check type of constraint (only take modifiable linear constraints) */
5441 	               if ( strcmp(conshdlrname, "linear") == 0 && ! SCIPconsIsModifiable(cons) )
5442 	               {
5443 	                  /* avoid adding linear constraints that correspond to indicator constraints */
5444 	                  if ( strncmp(SCIPconsGetName(cons), "indlin", 6) != 0 )
5445 	                  {
5446 	                     SCIP_CALL( addAltLPConstraint(scip, conshdlr, cons, NULL, 0.0, &colindex) );
5447 	                     SCIPdebugMsg(scip, "Added column for linear constraint <%s> to alternative LP with column index %d.\n", SCIPconsGetName(cons), colindex);
5448 	                     ++cnt;
5449 	                  }
5450 	               }
5451 	            }
5452 	            SCIPdebugMsg(scip, "Added %d additional columns from linear constraints to alternative LP.\n", cnt);
5453 	         }
5454 	      }
5455 	   }
5456 	
5457 	   /* initialize event handler if restart should be forced */
5458 	   if ( conshdlrdata->forcerestart )
5459 	   {
5460 	      SCIP_Bool* covered;
5461 	      SCIP_VAR** vars;
5462 	      int nvars;
5463 	      int j;
5464 	
5465 	      assert( conshdlrdata->eventhdlrrestart != NULL );
5466 	
5467 	      /* store number of initial constraints */
5468 	      conshdlrdata->ninitconss = SCIPconshdlrGetNActiveConss(conshdlr);
5469 	
5470 	      /* reset number of fixed binary variables */
5471 	      conshdlrdata->nbinvarszero = 0;
5472 	
5473 	      /* loop through variables */
5474 	      nvars = SCIPgetNVars(scip);
5475 	      vars = SCIPgetVars(scip);
5476 	
5477 	      conshdlrdata->objindicatoronly = FALSE;
5478 	      conshdlrdata->minabsobj = SCIP_REAL_MAX;
5479 	
5480 	      /* unmark all variables */
5481 	      SCIP_CALL( SCIPallocBufferArray(scip, &covered, nvars) );
5482 	      for (j = 0; j < nvars; ++j)
5483 	         covered[j] = FALSE;
5484 	
5485 	      /* mark indicator variables */
5486 	      for (c = 0; c < nconss; ++c)
5487 	      {
5488 	         SCIP_CONSDATA* consdata;
5489 	         int probindex;
5490 	
5491 	         assert( conss != NULL );
5492 	         assert( conss[c] != NULL );
5493 	
5494 	         /* avoid non-active indicator constraints */
5495 	         if ( ! SCIPconsIsActive(conss[c]) )
5496 	            continue;
5497 	
5498 	         consdata = SCIPconsGetData(conss[c]);
5499 	         assert( consdata != NULL );
5500 	         assert( consdata->binvar != NULL );
5501 	
5502 	         if ( SCIPvarIsNegated(consdata->binvar) )
5503 	         {
5504 	            assert( SCIPvarGetNegatedVar(consdata->binvar) != NULL );
5505 	            probindex = SCIPvarGetProbindex(SCIPvarGetNegatedVar(consdata->binvar));
5506 	         }
5507 	         else
5508 	            probindex = SCIPvarGetProbindex(consdata->binvar);
5509 	
5510 	         /* if presolving detected infeasibility it might be that the binary variables are not active */
5511 	         if ( probindex < 0 )
5512 	            continue;
5513 	
5514 	         assert( 0 <= probindex && probindex < nvars );
5515 	         covered[probindex] = TRUE;
5516 	      }
5517 	
5518 	      /* check all variables */
5519 	      for (j = 0; j < nvars; ++j)
5520 	      {
5521 	         SCIP_Real obj;
5522 	
5523 	         obj = SCIPvarGetObj(vars[j]);
5524 	         if ( ! SCIPisZero(scip, obj) )
5525 	         {
5526 	            if ( ! covered[j] )
5527 	               break;
5528 	            if ( ! SCIPisIntegral(scip, obj) )
5529 	               break;
5530 	            if ( REALABS(obj) < conshdlrdata->minabsobj )
5531 	               conshdlrdata->minabsobj = REALABS(obj);
5532 	         }
5533 	      }
5534 	
5535 	      /* if all variables have integral objective and only indicator variables have nonzero objective */
5536 	      if ( j >= nvars )
5537 	      {
5538 	         /* if there are variables with nonzero objective */
5539 	         if ( conshdlrdata->minabsobj < SCIP_REAL_MAX )
5540 	         {
5541 	            assert( SCIPisIntegral(scip, conshdlrdata->minabsobj) );
5542 	            assert( SCIPisGE(scip, conshdlrdata->minabsobj, 1.0) );
5543 	
5544 	            conshdlrdata->objindicatoronly = TRUE;
5545 	
5546 	            assert( conshdlrdata->eventhdlrrestart != NULL );
5547 	            SCIP_CALL( SCIPcatchEvent(scip, SCIP_EVENTTYPE_BESTSOLFOUND, conshdlrdata->eventhdlrrestart, (SCIP_EVENTDATA*) conshdlrdata, NULL) );
5548 	         }
5549 	      }
5550 	
5551 	      SCIPfreeBufferArray(scip, &covered);
5552 	   }
5553 	
5554 	   return SCIP_OKAY;
5555 	}
5556 	
5557 	
5558 	/** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
5559 	static
5560 	SCIP_DECL_CONSEXITSOL(consExitsolIndicator)
5561 	{  /*lint --e{715}*/
5562 	   SCIP_CONSHDLRDATA* conshdlrdata;
5563 	   int c;
5564 	
5565 	   assert( scip != NULL );
5566 	   assert( conshdlr != NULL );
5567 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
5568 	
5569 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
5570 	   assert( conshdlrdata != NULL );
5571 	
5572 	   if ( conshdlrdata->sepaalternativelp )
5573 	   {
5574 	      if ( conshdlrdata->slackhash != NULL )
5575 	      {
5576 	#ifdef SCIP_DEBUG
5577 	         SCIPinfoMessage(scip, NULL, "\nStatistics for cons_indicator slack hash:\n");
5578 	         SCIPhashmapPrintStatistics(conshdlrdata->slackhash, SCIPgetMessagehdlr(scip));
5579 	#endif
5580 	         SCIPhashmapFree(&conshdlrdata->slackhash);
5581 	      }
5582 	
5583 	      if ( conshdlrdata->altlp != NULL )
5584 	      {
5585 	         assert( conshdlrdata->varhash != NULL );
5586 	         assert( conshdlrdata->lbhash != NULL );
5587 	         assert( conshdlrdata->ubhash != NULL );
5588 	
5589 	#ifdef SCIP_DEBUG
5590 	         SCIPinfoMessage(scip, NULL, "\nStatistics for cons_indicator var hash:\n");
5591 	         SCIPhashmapPrintStatistics(conshdlrdata->varhash, SCIPgetMessagehdlr(scip));
5592 	         SCIPinfoMessage(scip, NULL, "\nStatistics for cons_indicator lower bound hash:\n");
5593 	         SCIPhashmapPrintStatistics(conshdlrdata->lbhash, SCIPgetMessagehdlr(scip));
5594 	         SCIPinfoMessage(scip, NULL, "\nStatistics for cons_indicator upper bound hash:\n");
5595 	         SCIPhashmapPrintStatistics(conshdlrdata->ubhash, SCIPgetMessagehdlr(scip));
5596 	#endif
5597 	
5598 	         SCIPhashmapFree(&conshdlrdata->varhash);
5599 	         SCIPhashmapFree(&conshdlrdata->lbhash);
5600 	         SCIPhashmapFree(&conshdlrdata->ubhash);
5601 	
5602 	         SCIP_CALL( SCIPlpiFree(&conshdlrdata->altlp) );
5603 	
5604 	         /* save the information that the columns have been deleted */
5605 	         for (c = 0; c < nconss; ++c)
5606 	         {
5607 	            SCIP_CONSDATA* consdata;
5608 	
5609 	            assert( conss != NULL );
5610 	            assert( conss[c] != NULL );
5611 	
5612 	            consdata = SCIPconsGetData(conss[c]);
5613 	            assert( consdata != NULL );
5614 	            consdata->colindex = -1;
5615 	         }
5616 	      }
5617 	   }
5618 	   else
5619 	   {
5620 	      assert( conshdlrdata->slackhash == NULL );
5621 	      assert( conshdlrdata->varhash == NULL );
5622 	      assert( conshdlrdata->lbhash == NULL );
5623 	      assert( conshdlrdata->ubhash == NULL );
5624 	   }
5625 	
5626 	   return SCIP_OKAY;
5627 	}
5628 	
5629 	
5630 	/** frees specific constraint data */
5631 	static
5632 	SCIP_DECL_CONSDELETE(consDeleteIndicator)
5633 	{
5634 	   assert( scip != NULL );
5635 	   assert( conshdlr != NULL );
5636 	   assert( cons != NULL );
5637 	   assert( consdata != NULL );
5638 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
5639 	
5640 	#ifdef SCIP_MORE_DEBUG
5641 	   SCIPdebugMsg(scip, "Deleting indicator constraint <%s>.\n", SCIPconsGetName(cons) );
5642 	#endif
5643 	
5644 	   /* drop events on transformed variables */
5645 	   if ( SCIPconsIsTransformed(cons) )
5646 	   {
5647 	      SCIP_CONSHDLRDATA* conshdlrdata;
5648 	
5649 	      /* get constraint handler data */
5650 	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
5651 	      assert( conshdlrdata != NULL );
5652 	
5653 	      if ( conshdlrdata->sepaalternativelp )
5654 	      {
5655 	         SCIP_CALL( deleteAltLPConstraint(scip, conshdlr, cons) );
5656 	      }
5657 	
5658 	      assert( (*consdata)->slackvar != NULL );
5659 	      assert( (*consdata)->binvar != NULL );
5660 	
5661 	      /* free events only in correct stages */
5662 	      if ( SCIPgetStage(scip) >= SCIP_STAGE_TRANSFORMING && SCIPgetStage(scip) <= SCIP_STAGE_EXITSOLVE )
5663 	      {
5664 	         if ( (*consdata)->linconsactive )
5665 	         {
5666 	            assert( conshdlrdata->eventhdlrbound != NULL );
5667 	            SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->binvar, SCIP_EVENTTYPE_BOUNDCHANGED, conshdlrdata->eventhdlrbound,
5668 	                  (SCIP_EVENTDATA*)*consdata, -1) );
5669 	            SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->slackvar, SCIP_EVENTTYPE_BOUNDCHANGED, conshdlrdata->eventhdlrbound,
5670 	                  (SCIP_EVENTDATA*)*consdata, -1) );
5671 	         }
5672 	         if ( conshdlrdata->forcerestart )
5673 	         {
5674 	            assert( conshdlrdata->eventhdlrrestart != NULL );
5675 	            SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->binvar, SCIP_EVENTTYPE_GBDCHANGED, conshdlrdata->eventhdlrrestart,
5676 	                  (SCIP_EVENTDATA*) conshdlrdata, -1) );
5677 	         }
5678 	      }
5679 	   }
5680 	
5681 	   /* Can there be cases where lincons is NULL, e.g., if presolve found the problem infeasible? */
5682 	   assert( (*consdata)->lincons != NULL );
5683 	
5684 	   /* release linear constraint and slack variable */
5685 	   SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->slackvar) );
5686 	   SCIP_CALL( SCIPreleaseCons(scip, &(*consdata)->lincons) );
5687 	
5688 	   SCIPfreeBlockMemory(scip, consdata);
5689 	
5690 	   return SCIP_OKAY;
5691 	}
5692 	
5693 	
5694 	/** transforms constraint data into data belonging to the transformed problem */
5695 	static
5696 	SCIP_DECL_CONSTRANS(consTransIndicator)
5697 	{
5698 	   SCIP_CONSDATA* consdata;
5699 	   SCIP_CONSHDLRDATA* conshdlrdata;
5700 	   SCIP_CONSDATA* sourcedata;
5701 	   char s[SCIP_MAXSTRLEN];
5702 	
5703 	   assert( scip != NULL );
5704 	   assert( conshdlr != NULL );
5705 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
5706 	   assert( sourcecons != NULL );
5707 	   assert( targetcons != NULL );
5708 	
5709 	   /* get constraint handler data */
5710 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
5711 	   assert( conshdlrdata != NULL );
5712 	   assert( conshdlrdata->eventhdlrbound != NULL );
5713 	
5714 	#ifdef SCIP_MORE_DEBUG
5715 	   SCIPdebugMsg(scip, "Transforming indicator constraint: <%s>.\n", SCIPconsGetName(sourcecons) );
5716 	#endif
5717 	
5718 	   /* get data of original constraint */
5719 	   sourcedata = SCIPconsGetData(sourcecons);
5720 	   assert( sourcedata != NULL );
5721 	   assert( sourcedata->binvar != NULL );
5722 	
5723 	   /* check for slackvar */
5724 	   if ( sourcedata->slackvar == NULL )
5725 	   {
5726 	      SCIPerrorMessage("The indicator constraint <%s> needs a slack variable.\n", SCIPconsGetName(sourcecons));
5727 	      return SCIP_INVALIDDATA;
5728 	   }
5729 	
5730 	   /* check for linear constraint */
5731 	   if ( sourcedata->lincons == NULL )
5732 	   {
5733 	      SCIPerrorMessage("The indicator constraint <%s> needs a linear constraint variable.\n", SCIPconsGetName(sourcecons));
5734 	      return SCIP_INVALIDDATA;
5735 	   }
5736 	   assert( sourcedata->lincons != NULL );
5737 	   assert( sourcedata->slackvar != NULL );
5738 	
5739 	   /* create constraint data */
5740 	   consdata = NULL;
5741 	   /* Note that the constraint has activeone = TRUE, since the binary variable has been negated already if needed. */
5742 	   SCIP_CALL( consdataCreate(scip, conshdlr, conshdlrdata, SCIPconsGetName(sourcecons), &consdata, conshdlrdata->eventhdlrbound,
5743 	         conshdlrdata->eventhdlrrestart, sourcedata->binvar, TRUE, sourcedata->lessthanineq, sourcedata->slackvar, sourcedata->lincons, sourcedata->linconsactive) );
5744 	   consdata->activeone = sourcedata->activeone;
5745 	   assert( consdata != NULL );
5746 	
5747 	   /* capture slack variable and linear constraint */
5748 	   SCIP_CALL( SCIPcaptureVar(scip, consdata->slackvar) );
5749 	   SCIP_CALL( SCIPcaptureCons(scip, consdata->lincons) );
5750 	
5751 	   /* create transformed constraint with the same flags */
5752 	   (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons));
5753 	   SCIP_CALL( SCIPcreateCons(scip, targetcons, s, conshdlr, consdata,
5754 	         SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
5755 	         SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
5756 	         SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
5757 	         SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
5758 	         SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
5759 	
5760 	   /* make sure that binary variable hash exists */
5761 	   if ( conshdlrdata->sepaalternativelp )
5762 	   {
5763 	      if ( conshdlrdata->binvarhash == NULL )
5764 	      {
5765 	         SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->binvarhash, SCIPblkmem(scip), SCIPgetNOrigVars(scip)) );
5766 	      }
5767 	
5768 	      /* check whether binary variable is present: note that a binary variable might appear several times, but this seldomly happens. */
5769 	      assert( conshdlrdata->binvarhash != NULL );
5770 	      if ( ! SCIPhashmapExists(conshdlrdata->binvarhash, (void*) consdata->binvar) )
5771 	      {
5772 	         SCIP_CALL( SCIPhashmapInsert(conshdlrdata->binvarhash, (void*) consdata->binvar, (void*) (*targetcons)) );
5773 	      }
5774 	   }
5775 	
5776 	   return SCIP_OKAY;
5777 	}
5778 	
5779 	
5780 	/** presolving initialization method of constraint handler (called when presolving is about to begin) */
5781 	static
5782 	SCIP_DECL_CONSINITPRE(consInitpreIndicator)
5783 	{  /*lint --e{715}*/
5784 	   SCIP_CONSHDLRDATA* conshdlrdata;
5785 	   int c;
5786 	
5787 	   assert( scip != NULL );
5788 	   assert( conshdlr != NULL );
5789 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
5790 	
5791 	   if ( SCIPgetStatus(scip) != SCIP_STATUS_UNKNOWN )
5792 	      return SCIP_OKAY;
5793 	
5794 	   SCIPdebugMsg(scip, "Initpre method for indicator constraints.\n");
5795 	
5796 	   /* check each constraint and get transformed linear constraint */
5797 	   for (c = 0; c < nconss; ++c)
5798 	   {
5799 	      SCIP_CONSDATA* consdata;
5800 	
5801 	      assert( conss != NULL );
5802 	      assert( conss[c] != NULL );
5803 	      assert( SCIPconsIsTransformed(conss[c]) );
5804 	
5805 	      consdata = SCIPconsGetData(conss[c]);
5806 	      assert( consdata != NULL );
5807 	
5808 	      /* if not happened already, get transformed linear constraint */
5809 	      assert( consdata->lincons != NULL );
5810 	      assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(consdata->lincons)), "linear") == 0 );
5811 	
5812 	      /* in a restart the linear constraint might already be transformed */
5813 	      if ( ! SCIPconsIsTransformed(consdata->lincons) )
5814 	      {
5815 	         SCIP_CONS* translincons;
5816 	
5817 	         SCIP_CALL( SCIPgetTransformedCons(scip, consdata->lincons, &translincons) );
5818 	         assert( translincons != NULL );
5819 	
5820 	         SCIP_CALL( SCIPreleaseCons(scip, &consdata->lincons) );
5821 	         SCIP_CALL( SCIPcaptureCons(scip, translincons) );
5822 	         consdata->lincons = translincons;
5823 	      }
5824 	   }
5825 	
5826 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
5827 	   assert( conshdlrdata != NULL );
5828 	
5829 	   /* reset flag, in case presolve was called for some problem before */
5830 	   conshdlrdata->addedcouplingcons = FALSE;
5831 	
5832 	   return SCIP_OKAY;
5833 	}
5834 	
5835 	
5836 	/** presolving method of constraint handler
5837 	 *
5838 	 *  For an indicator constraint with binary variable \f$y\f$ and slack variable \f$s\f$ the coupling
5839 	 *  inequality \f$s \le M (1-y)\f$ (equivalently: \f$s + M y \le M\f$) is inserted, where \f$M\f$ is
5840 	 *  an upper bound on the value of \f$s\f$. If \f$M\f$ is too large the inequality is not
5841 	 *  inserted. Depending on the parameter @a addcouplingcons we add a variable upper bound or a row
5842 	 *  (in consInitlpIndicator()).
5843 	 *
5844 	 *  @warning We can never delete linear constraints, because we need them to get the right values
5845 	 *  for the slack variables!
5846 	 */
5847 	static
5848 	SCIP_DECL_CONSPRESOL(consPresolIndicator)
5849 	{  /*lint --e{715}*/
5850 	   SCIP_CONSHDLRDATA* conshdlrdata;
5851 	   SCIP_Bool noReductions;
5852 	   SCIPdebug( int oldnfixedvars = *nfixedvars; )
5853 	   SCIPdebug( int oldndelconss = *ndelconss; )
5854 	   int c;
5855 	
5856 	   assert( scip != NULL );
5857 	   assert( conshdlr != NULL );
5858 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
5859 	   assert( result != NULL );
5860 	
5861 	   *result = SCIP_DIDNOTRUN;
5862 	   /* get constraint handler data */
5863 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
5864 	   assert( conshdlrdata != NULL );
5865 	
5866 	   SCIPdebugMsg(scip, "Presolving indicator constraints.\n");
5867 	
5868 	   /* only run if success is possible */
5869 	   if ( nrounds == 0 || nnewfixedvars > 0 || nnewchgbds > 0 || nnewaggrvars > 0 )
5870 	   {
5871 	      *result = SCIP_DIDNOTFIND;
5872 	
5873 	      /* check each constraint */
5874 	      for (c = 0; c < nconss; ++c)
5875 	      {
5876 	         SCIP_CONSDATA* consdata;
5877 	         SCIP_CONS* cons;
5878 	         SCIP_Bool success;
5879 	         SCIP_Bool cutoff;
5880 	
5881 	         assert( conss != NULL );
5882 	         assert( conss[c] != NULL );
5883 	         cons = conss[c];
5884 	         consdata = SCIPconsGetData(cons);
5885 	         assert( consdata != NULL );
5886 	         assert( consdata->binvar != NULL );
5887 	         assert( ! SCIPconsIsModifiable(cons) );
5888 	
5889 	#ifdef SCIP_MORE_DEBUG
5890 	         SCIPdebugMsg(scip, "Presolving indicator constraint <%s>.\n", SCIPconsGetName(cons) );
5891 	#endif
5892 	
5893 	         /* do nothing if the linear constraint is not active */
5894 	         if ( ! consdata->linconsactive )
5895 	            continue;
5896 	
5897 	         assert( consdata->lincons != NULL );
5898 	         assert( consdata->slackvar != NULL );
5899 	         assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(consdata->lincons)), "linear") == 0 );
5900 	         assert( SCIPconsIsTransformed(consdata->lincons) );
5901 	
5902 	         /* add implications if not yet done */
5903 	         if ( ! consdata->implicationadded )
5904 	         {
5905 	            int nbnds = 0;
5906 	            SCIP_CALL( SCIPaddVarImplication(scip, consdata->binvar, TRUE, consdata->slackvar, SCIP_BOUNDTYPE_UPPER, 0.0,
5907 	                  &cutoff, &nbnds) );
5908 	            *nchgbds += nbnds;
5909 	
5910 	            /* cutoff/infeasible might be true if preprocessing was truncated */
5911 	            /* note: nbdchgs == 0 is not necessarily true, because preprocessing might be truncated. */
5912 	            consdata->implicationadded = TRUE;
5913 	            if ( cutoff )
5914 	            {
5915 	               *result = SCIP_CUTOFF;
5916 	               return SCIP_OKAY;
5917 	            }
5918 	         }
5919 	
5920 	         /* check type of slack variable if not yet done */
5921 	         if ( ! consdata->slacktypechecked )
5922 	         {
5923 	            consdata->slacktypechecked = TRUE;
5924 	            /* check if slack variable can be made implicit integer. */
5925 	            if ( SCIPvarGetType(consdata->slackvar) == SCIP_VARTYPE_CONTINUOUS )
5926 	            {
5927 	               SCIP_Real* vals;
5928 	               SCIP_VAR** vars;
5929 	               SCIP_VAR* slackvar;
5930 	               SCIP_Bool foundslackvar = FALSE;
5931 	               int nvars;
5932 	               int j;
5933 	
5934 	               assert( consdata->lincons != NULL );
5935 	               vars = SCIPgetVarsLinear(scip, consdata->lincons);
5936 	               vals = SCIPgetValsLinear(scip, consdata->lincons);
5937 	               nvars = SCIPgetNVarsLinear(scip, consdata->lincons);
5938 	               slackvar = consdata->slackvar;
5939 	               assert( slackvar != NULL );
5940 	
5941 	               for (j = 0; j < nvars; ++j)
5942 	               {
5943 	                  if ( vars[j] == slackvar )
5944 	                     foundslackvar = TRUE;
5945 	                  else
5946 	                  {
5947 	                     if ( ! SCIPvarIsIntegral(vars[j]) || ! SCIPisIntegral(scip, vals[j]))
5948 	                        break;
5949 	                  }
5950 	               }
5951 	               /* something is strange if the slack variable does not appear in the linear constraint (possibly because it is an artificial constraint) */
5952 	               if ( j == nvars && foundslackvar )
5953 	               {
5954 	                  SCIP_Bool infeasible;
5955 	                  SCIP_Real lb;
5956 	                  SCIP_Real ub;
5957 	
5958 	                  lb = SCIPvarGetLbGlobal(consdata->slackvar);
5959 	                  ub = SCIPvarGetUbGlobal(consdata->slackvar);
5960 	                  if ( (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub)) )
5961 	                  {
5962 	                     SCIP_CALL( SCIPchgVarType(scip, consdata->slackvar, SCIP_VARTYPE_IMPLINT, &infeasible) );
5963 	                     /* don't assert feasibility here because the presolver should detect infeasibility */
5964 	                  }
5965 	                  else
5966 	                  {
5967 	                     /* It can happen that the bounds of the slack variable have been changed to be non-integral in
5968 	                      * previous presolving steps. We then might get a problem with tightening the bounds. In this case,
5969 	                      * we just leave the slack variable to be continuous. */
5970 	                     SCIPdebugMsg(scip, "Cannot change type of slack variable (<%s>) to IMPLINT, since global bound is non-integral: (%g, %g).\n",
5971 	                        SCIPvarGetName(consdata->slackvar), SCIPvarGetLbGlobal(consdata->slackvar), SCIPvarGetUbGlobal(consdata->slackvar));
5972 	                  }
5973 	               }
5974 	            }
5975 	         }
5976 	
5977 	         /* perform one presolving round */
5978 	         SCIP_CALL( presolRoundIndicator(scip, conshdlrdata, cons, consdata,
5979 	               conshdlrdata->dualreductions && SCIPallowStrongDualReds(scip), &cutoff, &success, ndelconss, nfixedvars) );
5980 	
5981 	         if ( cutoff )
5982 	         {
5983 	            *result = SCIP_CUTOFF;
5984 	            return SCIP_OKAY;
5985 	         }
5986 	         if ( success )
5987 	            *result = SCIP_SUCCESS;
5988 	      }
5989 	   }
5990 	
5991 	   /* determine whether other methods have found reductions */
5992 	   noReductions = nnewfixedvars == 0 && nnewaggrvars == 0 && nnewchgvartypes == 0 && nnewchgbds == 0
5993 	      && nnewdelconss == 0 && nnewchgcoefs == 0 && nnewchgsides == 0;
5994 	
5995 	   /* add variable upper bounds after bounds are likely to be strengthened */
5996 	   if ( noReductions && *result != SCIP_SUCCESS && conshdlrdata->addcouplingcons && ! conshdlrdata->addedcouplingcons )
5997 	   {
5998 	      int ngen;
5999 	
6000 	      /* create variable upper bounds, possibly removing indicator constraints */
6001 	      SCIP_CALL( createVarUbs(scip, conshdlrdata, conss, nconss, &ngen) );
6002 	
6003 	      if ( ngen > 0 )
6004 	      {
6005 	         *result = SCIP_SUCCESS;
6006 	         *nupgdconss += ngen;
6007 	         if ( conshdlrdata->removeindicators )
6008 	            *ndelconss += ngen;
6009 	      }
6010 	      conshdlrdata->addedcouplingcons = TRUE;
6011 	   }
6012 	
6013 	   SCIPdebug( SCIPdebugMsg(scip, "Presolved %d constraints (fixed %d variables, removed 0 variables, and deleted %d constraints).\n",
6014 	      nconss, *nfixedvars - oldnfixedvars, *ndelconss - oldndelconss); )
6015 	
6016 	   return SCIP_OKAY; /*lint !e438*/
6017 	}
6018 	
6019 	
6020 	/** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved)
6021 	 *
6022 	 *  For an indicator constraint with binary variable \f$y\f$ and slack variable \f$s\f$ the coupling
6023 	 *  inequality \f$s \le M (1-y)\f$ (equivalently: \f$s + M y \le M\f$) is inserted, where \f$M\f$ is
6024 	 *  an upper bound on the value of \f$s\f$. If \f$M\f$ is too large the inequality is not inserted.
6025 	 */
6026 	static
6027 	SCIP_DECL_CONSINITLP(consInitlpIndicator)
6028 	{
6029 	   int c;
6030 	   SCIP_CONSHDLRDATA* conshdlrdata;
6031 	
6032 	   assert( scip != NULL );
6033 	   assert( conshdlr != NULL );
6034 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6035 	
6036 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
6037 	   assert( conshdlrdata != NULL );
6038 	
6039 	   *infeasible = FALSE;
6040 	
6041 	   /* check whether coupling constraints should be added */
6042 	   if ( ! conshdlrdata->addcoupling )
6043 	      return SCIP_OKAY;
6044 	
6045 	   /* check whether coupling constraints have been added already */
6046 	   if ( conshdlrdata->addcouplingcons && conshdlrdata->addedcouplingcons )
6047 	      return SCIP_OKAY;
6048 	
6049 	   SCIPdebugMsg(scip, "Handle initial rows for %d indicator constraints.\n", nconss);
6050 	
6051 	   /* check each constraint */
6052 	   for (c = 0; c < nconss && !(*infeasible); ++c)
6053 	   {
6054 	      SCIP_CONSDATA* consdata;
6055 	      SCIP_Real ub;
6056 	
6057 	      assert( conss != NULL );
6058 	      assert( conss[c] != NULL );
6059 	      consdata = SCIPconsGetData(conss[c]);
6060 	      assert( consdata != NULL );
6061 	
6062 	      /* do not add inequalities if there are no linear constraints (no slack variable available) */
6063 	      if ( ! consdata->linconsactive )
6064 	         continue;
6065 	
6066 	      /* get upper bound for slack variable in linear constraint */
6067 	      ub = SCIPvarGetUbGlobal(consdata->slackvar);
6068 	      assert( ! SCIPisNegative(scip, ub) );
6069 	
6070 	      /* insert corresponding row if helpful and coefficient is not too large */
6071 	      if ( ub <= conshdlrdata->maxcouplingvalue )
6072 	      {
6073 	         char name[50];
6074 	
6075 	#ifndef NDEBUG
6076 	         (void) SCIPsnprintf(name, 50, "couple%d", c);
6077 	#else
6078 	         name[0] = '\0';
6079 	#endif
6080 	
6081 	         /* add variable upper bound if required */
6082 	         if ( conshdlrdata->addcouplingcons )
6083 	         {
6084 	            SCIP_CONS* cons;
6085 	
6086 	            assert( ! conshdlrdata->addedcouplingcons );
6087 	
6088 	            SCIPdebugMsg(scip, "Insert coupling varbound constraint for indicator constraint <%s> (coeff: %f).\n", SCIPconsGetName(conss[c]), ub);
6089 	
6090 	            SCIP_CALL( SCIPcreateConsVarbound(scip, &cons, name, consdata->slackvar, consdata->binvar, ub, -SCIPinfinity(scip), ub,
6091 	                  TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE) );
6092 	
6093 	            SCIP_CALL( SCIPaddCons(scip, cons) );
6094 	            SCIP_CALL( SCIPreleaseCons(scip, &cons) );
6095 	         }
6096 	         else
6097 	         {
6098 	            SCIP_ROW* row;
6099 	
6100 	            SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conss[c], name, -SCIPinfinity(scip), ub, FALSE, FALSE, FALSE) );
6101 	            SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
6102 	
6103 	            SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->slackvar, 1.0) );
6104 	            SCIP_CALL( SCIPaddVarToRow(scip, row, consdata->binvar, ub) );
6105 	            SCIP_CALL( SCIPflushRowExtensions(scip, row) );
6106 	
6107 	            SCIPdebugMsg(scip, "Insert coupling inequality for indicator constraint <%s> (coeff: %f).\n", SCIPconsGetName(conss[c]), ub);
6108 	#ifdef SCIP_OUTPUT
6109 	            SCIP_CALL( SCIPprintRow(scip, row, NULL) );
6110 	#endif
6111 	            SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
6112 	            SCIP_CALL( SCIPreleaseRow(scip, &row));
6113 	         }
6114 	      }
6115 	   }
6116 	
6117 	   return SCIP_OKAY;
6118 	}
6119 	
6120 	
6121 	/** separation method of constraint handler for LP solutions */
6122 	static
6123 	SCIP_DECL_CONSSEPALP(consSepalpIndicator)
6124 	{  /*lint --e{715}*/
6125 	   assert( scip != NULL );
6126 	   assert( conshdlr != NULL );
6127 	   assert( conss != NULL );
6128 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6129 	   assert( result != NULL );
6130 	
6131 	   /* perform separation */
6132 	   SCIP_CALL( separateIndicators(scip, conshdlr, nconss, nusefulconss, conss, NULL, SCIP_TYPE_SEPALP, result) );
6133 	
6134 	   return SCIP_OKAY;
6135 	}
6136 	
6137 	
6138 	/** separation method of constraint handler for arbitrary primal solutions */
6139 	static
6140 	SCIP_DECL_CONSSEPASOL(consSepasolIndicator)
6141 	{  /*lint --e{715}*/
6142 	   assert( scip != NULL );
6143 	   assert( conshdlr != NULL );
6144 	   assert( conss != NULL );
6145 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6146 	   assert( result != NULL );
6147 	
6148 	   /* perform separation */
6149 	   SCIP_CALL( separateIndicators(scip, conshdlr, nconss, nusefulconss, conss, sol, SCIP_TYPE_SEPASOL, result) );
6150 	
6151 	   return SCIP_OKAY;
6152 	}
6153 	
6154 	
6155 	/** constraint enforcing method of constraint handler for LP solutions */
6156 	static
6157 	SCIP_DECL_CONSENFOLP(consEnfolpIndicator)
6158 	{  /*lint --e{715}*/
6159 	   SCIP_CONSHDLRDATA* conshdlrdata;
6160 	
6161 	   assert( scip != NULL );
6162 	   assert( conshdlr != NULL );
6163 	   assert( conss != NULL );
6164 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6165 	   assert( result != NULL );
6166 	
6167 	   if ( solinfeasible )
6168 	   {
6169 	      *result = SCIP_FEASIBLE;
6170 	      return SCIP_OKAY;
6171 	   }
6172 	
6173 	   /* get constraint handler data */
6174 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
6175 	   assert( conshdlrdata != NULL );
6176 	
6177 	   SCIP_CALL( enforceIndicators(scip, conshdlr, nconss, conss, NULL, SCIP_TYPE_ENFOLP, conshdlrdata->genlogicor, result) );
6178 	
6179 	   return SCIP_OKAY;
6180 	}
6181 	
6182 	
6183 	/** constraint enforcing method of constraint handler for relaxation solutions */
6184 	static
6185 	SCIP_DECL_CONSENFORELAX(consEnforelaxIndicator)
6186 	{  /*lint --e{715}*/
6187 	   SCIP_CONSHDLRDATA* conshdlrdata;
6188 	
6189 	   assert( scip != NULL );
6190 	   assert( conshdlr != NULL );
6191 	   assert( conss != NULL );
6192 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6193 	   assert( result != NULL );
6194 	
6195 	   if ( solinfeasible )
6196 	   {
6197 	      *result = SCIP_FEASIBLE;
6198 	      return SCIP_OKAY;
6199 	   }
6200 	
6201 	   /* get constraint handler data */
6202 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
6203 	   assert( conshdlrdata != NULL );
6204 	
6205 	   SCIP_CALL( enforceIndicators(scip, conshdlr, nconss, conss, sol, SCIP_TYPE_ENFORELAX, conshdlrdata->genlogicor, result) );
6206 	
6207 	   return SCIP_OKAY;
6208 	}
6209 	
6210 	
6211 	/** constraint enforcing method of constraint handler for pseudo solutions */
6212 	static
6213 	SCIP_DECL_CONSENFOPS(consEnfopsIndicator)
6214 	{  /*lint --e{715}*/
6215 	   assert( scip != NULL );
6216 	   assert( conshdlr != NULL );
6217 	   assert( conss != NULL );
6218 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6219 	   assert( result != NULL );
6220 	
6221 	   if ( solinfeasible )
6222 	   {
6223 	      *result = SCIP_FEASIBLE;
6224 	      return SCIP_OKAY;
6225 	   }
6226 	
6227 	   if ( objinfeasible )
6228 	   {
6229 	      *result = SCIP_DIDNOTRUN;
6230 	      return SCIP_OKAY;
6231 	   }
6232 	
6233 	   SCIP_CALL( enforceIndicators(scip, conshdlr, nconss, conss, NULL, SCIP_TYPE_ENFOPS, TRUE, result) );
6234 	
6235 	   return SCIP_OKAY;
6236 	}
6237 	
6238 	
6239 	/** feasibility check method of constraint handler for integral solutions */
6240 	static
6241 	SCIP_DECL_CONSCHECK(consCheckIndicator)
6242 	{  /*lint --e{715}*/
6243 	   SCIP_SOL* trysol = NULL;
6244 	   SCIP_CONSHDLRDATA* conshdlrdata;
6245 	   SCIP_Bool someLinconsNotActive;
6246 	   SCIP_Bool changedSol;
6247 	   int c;
6248 	
6249 	   assert( scip != NULL );
6250 	   assert( conshdlr != NULL );
6251 	   assert( conss != NULL );
6252 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6253 	   assert( result != NULL );
6254 	
6255 	   SCIPdebugMsg(scip, "Checking %d indicator constraints <%s>.\n", nconss, SCIPconshdlrGetName(conshdlr) );
6256 	
6257 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
6258 	   assert( conshdlrdata != NULL );
6259 	
6260 	   /* try to repair solution below, if it makes sense (will send solution to trysol heuristic in any case (see below) */
6261 	   if ( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM && SCIPgetStage(scip) < SCIP_STAGE_SOLVED && conshdlrdata->trysolutions && conshdlrdata->heurtrysol != NULL )
6262 	   {
6263 	      SCIP_CALL( SCIPcreateSolCopy(scip, &trysol, sol) );
6264 	      assert( trysol != NULL );
6265 	   }
6266 	
6267 	   /* check each constraint */
6268 	   *result = SCIP_FEASIBLE;
6269 	   changedSol = FALSE;
6270 	   someLinconsNotActive = FALSE;
6271 	   for (c = 0; c < nconss; ++c)
6272 	   {
6273 	      SCIP_CONSDATA* consdata;
6274 	
6275 	      assert( conss[c] != NULL );
6276 	      consdata = SCIPconsGetData(conss[c]);
6277 	      assert( consdata != NULL );
6278 	      assert( consdata->binvar != NULL );
6279 	
6280 	      /* if the linear constraint has not been generated, we do nothing */
6281 	      if ( ! consdata->linconsactive )
6282 	      {
6283 	         someLinconsNotActive = TRUE;
6284 	         continue;
6285 	      }
6286 	
6287 	      assert( consdata->slackvar != NULL );
6288 	      /* if printreason is true it can happen that non-integral solutions are checked */
6289 	      assert( checkintegrality || SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, consdata->binvar)) );
6290 	
6291 	      /* if constraint is infeasible */
6292 	      if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->binvar)) &&
6293 	           ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->slackvar)) )
6294 	      {
6295 	         SCIP_Real absviol = REALABS(SCIPgetSolVal(scip, sol, consdata->slackvar));
6296 	         SCIP_Real relviol = SCIPrelDiff(absviol, 0.0);
6297 	         if( sol != NULL )
6298 	            SCIPupdateSolConsViolation(scip, sol, absviol, relviol);
6299 	
6300 	         SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
6301 	         *result = SCIP_INFEASIBLE;
6302 	
6303 	         if ( printreason )
6304 	         {
6305 	            SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) );
6306 	            SCIPinfoMessage(scip, NULL, ";\nviolation:  <%s> = %g and <%s> = %.15g\n",
6307 	               SCIPvarGetName(consdata->binvar), SCIPgetSolVal(scip, sol, consdata->binvar),
6308 	               SCIPvarGetName(consdata->slackvar), SCIPgetSolVal(scip, sol, consdata->slackvar));
6309 	         }
6310 	
6311 	         /* try to make solution feasible if it makes sense - otherwise exit */
6312 	         if ( trysol != NULL )
6313 	         {
6314 	            SCIP_Bool changed;
6315 	            SCIP_CALL( SCIPmakeIndicatorFeasible(scip, conss[c], trysol, &changed) );
6316 	            changedSol = changedSol || changed;
6317 	         }
6318 	         else
6319 	         {
6320 	            SCIPdebugMsg(scip, "Indicator constraint %s is not feasible.\n", SCIPconsGetName(conss[c]));
6321 	
6322 	            if( !completely )
6323 	               return SCIP_OKAY;
6324 	         }
6325 	      }
6326 	      else
6327 	      {
6328 	         if ( trysol != NULL )
6329 	         {
6330 	            SCIP_Bool changed;
6331 	            SCIP_CALL( SCIPmakeIndicatorFeasible(scip, conss[c], trysol, &changed) );
6332 	            changedSol = changedSol || changed;
6333 	         }
6334 	      }
6335 	   }
6336 	
6337 	   /* if some linear constraints are not active, we need to check feasibility via the alternative polyhedron */
6338 	   if ( someLinconsNotActive )
6339 	   {
6340 	      SCIP_LPI* lp;
6341 	      SCIP_Bool infeasible;
6342 	      SCIP_Bool error;
6343 	      SCIP_Bool* S;
6344 	
6345 	      lp = conshdlrdata->altlp;
6346 	      assert( conshdlrdata->sepaalternativelp );
6347 	
6348 	      /* the check maybe called before we have build the alternative polyhedron -> return SCIP_INFEASIBLE */
6349 	      if ( lp != NULL )
6350 	      {
6351 	#ifndef NDEBUG
6352 	         SCIP_CALL( checkLPBoundsClean(scip, lp, nconss, conss) );
6353 	#endif
6354 	
6355 	         /* change coefficients of bounds in alternative LP */
6356 	         if ( conshdlrdata->updatebounds )
6357 	         {
6358 	            SCIP_CALL( updateFirstRowGlobal(scip, conshdlrdata) );
6359 	         }
6360 	
6361 	         /* scale first row if necessary */
6362 	         SCIP_CALL( scaleFirstRow(scip, conshdlrdata) );
6363 	
6364 	         /* set objective function to current solution */
6365 	         SCIP_CALL( setAltLPObjZero(scip, lp, nconss, conss) );
6366 	
6367 	         SCIP_CALL( SCIPallocBufferArray(scip, &S, nconss) );
6368 	
6369 	         /* set up variables fixed to 1 */
6370 	         for (c = 0; c < nconss; ++c)
6371 	         {
6372 	            SCIP_CONSDATA* consdata;
6373 	
6374 	            assert( conss[c] != NULL );
6375 	            consdata = SCIPconsGetData(conss[c]);
6376 	            assert( consdata != NULL );
6377 	
6378 	            /* if printreason is true it can happen that non-integral solutions are checked */
6379 	            assert( checkintegrality || SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, consdata->binvar)) );
6380 	            if ( SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->binvar)) )
6381 	               S[c] = TRUE;
6382 	            else
6383 	               S[c] = FALSE;
6384 	         }
6385 	
6386 	         /* fix the variables in S */
6387 	         SCIP_CALL( fixAltLPVariables(scip, lp, nconss, conss, S) );
6388 	
6389 	         /* check feasibility */
6390 	         SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_FROMSCRATCH, TRUE) );
6391 	         SCIP_CALL( checkAltLPInfeasible(scip, lp, conshdlrdata->maxconditionaltlp, TRUE, &infeasible, &error) );
6392 	         SCIP_CALL_PARAM( SCIPlpiSetIntpar(lp, SCIP_LPPAR_FROMSCRATCH, FALSE) );
6393 	
6394 	         if ( error )
6395 	            return SCIP_LPERROR;
6396 	
6397 	         if ( ! infeasible )
6398 	            *result = SCIP_INFEASIBLE;
6399 	
6400 	         /* reset bounds */
6401 	         SCIP_CALL( unfixAltLPVariables(scip, lp, nconss, conss, S) );
6402 	
6403 	#ifndef NDEBUG
6404 	         SCIP_CALL( checkLPBoundsClean(scip, lp, nconss, conss) );
6405 	#endif
6406 	
6407 	         SCIPfreeBufferArray(scip, &S);
6408 	      }
6409 	      else
6410 	         *result = SCIP_INFEASIBLE;
6411 	   }
6412 	   else
6413 	   {
6414 	      /* tell heur_trysol about solution - it will pass it to SCIP */
6415 	      if ( trysol != NULL && changedSol )
6416 	      {
6417 	         assert( conshdlrdata->heurtrysol != NULL );
6418 	         SCIP_CALL( SCIPheurPassSolTrySol(scip, conshdlrdata->heurtrysol, trysol) );
6419 	      }
6420 	   }
6421 	
6422 	   if ( trysol != NULL )
6423 	      SCIP_CALL( SCIPfreeSol(scip, &trysol) );
6424 	
6425 	   if ( *result == SCIP_INFEASIBLE )
6426 	   {
6427 	      SCIPdebugMsg(scip, "Indicator constraints are not feasible.\n");
6428 	      return SCIP_OKAY;
6429 	   }
6430 	
6431 	   /* at this point we are feasible */
6432 	   SCIPdebugMsg(scip, "Indicator constraints are feasible.\n");
6433 	
6434 	   return SCIP_OKAY;
6435 	}
6436 	
6437 	
6438 	/** domain propagation method of constraint handler */
6439 	static
6440 	SCIP_DECL_CONSPROP(consPropIndicator)
6441 	{  /*lint --e{715}*/
6442 	   SCIP_CONSHDLRDATA* conshdlrdata;
6443 	   int ngen;
6444 	   int c;
6445 	
6446 	   assert( scip != NULL );
6447 	   assert( conshdlr != NULL );
6448 	   assert( conss != NULL );
6449 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6450 	   assert( result != NULL );
6451 	   *result = SCIP_DIDNOTRUN;
6452 	
6453 	   assert( SCIPisTransformed(scip) );
6454 	
6455 	   SCIPdebugMsg(scip, "Start propagation of constraint handler <%s>.\n", SCIPconshdlrGetName(conshdlr));
6456 	   ngen = 0;
6457 	
6458 	   /* get constraint handler data */
6459 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
6460 	   assert( conshdlrdata != NULL );
6461 	
6462 	   /* check each constraint */
6463 	   for (c = 0; c < nconss; ++c)
6464 	   {
6465 	      SCIP_CONS* cons;
6466 	      SCIP_CONSDATA* consdata;
6467 	      SCIP_Bool cutoff;
6468 	      int cnt;
6469 	
6470 	      *result = SCIP_DIDNOTFIND;
6471 	      assert( conss[c] != NULL );
6472 	      cons = conss[c];
6473 	      consdata = SCIPconsGetData(cons);
6474 	      assert( consdata != NULL );
6475 	
6476 	#ifdef SCIP_MORE_DEBUG
6477 	      SCIPdebugMsg(scip, "Propagating indicator constraint <%s>.\n", SCIPconsGetName(cons) );
6478 	#endif
6479 	
6480 	      *result = SCIP_DIDNOTFIND;
6481 	
6482 	      SCIP_CALL( propIndicator(scip, cons, consdata, conshdlrdata->dualreductions && SCIPallowStrongDualReds(scip),
6483 	            conshdlrdata->addopposite, &cutoff, &cnt) );
6484 	
6485 	      if ( cutoff )
6486 	      {
6487 	         *result = SCIP_CUTOFF;
6488 	         return SCIP_OKAY;
6489 	      }
6490 	      ngen += cnt;
6491 	   }
6492 	   SCIPdebugMsg(scip, "Propagated %d domains in constraint handler <%s>.\n", ngen, SCIPconshdlrGetName(conshdlr));
6493 	   if ( ngen > 0 )
6494 	      *result = SCIP_REDUCEDDOM;
6495 	
6496 	   return SCIP_OKAY;
6497 	}
6498 	
6499 	
6500 	/** propagation conflict resolving method of constraint handler
6501 	 *
6502 	 *  We check which bound changes were the reason for infeasibility. We use that @a inferinfo is 0 if
6503 	 *  the binary variable has bounds that fix it to be nonzero (these bounds are the reason). Likewise
6504 	 *  @a inferinfo is 1 if the slack variable has bounds that fix it to be nonzero.
6505 	 */
6506 	static
6507 	SCIP_DECL_CONSRESPROP(consRespropIndicator)
6508 	{  /*lint --e{715}*/
6509 	   SCIP_CONSDATA* consdata;
6510 	
6511 	   assert( scip != NULL );
6512 	   assert( cons != NULL );
6513 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6514 	   assert( infervar != NULL );
6515 	   assert( bdchgidx != NULL );
6516 	   assert( result != NULL );
6517 	
6518 	   *result = SCIP_DIDNOTFIND;
6519 	   SCIPdebugMsg(scip, "Propagation resolution method of indicator constraint <%s>.\n", SCIPconsGetName(cons));
6520 	
6521 	   consdata = SCIPconsGetData(cons);
6522 	   assert( consdata != NULL );
6523 	   assert( inferinfo == 0 || inferinfo == 1 || inferinfo == 2 );
6524 	   assert( consdata->linconsactive );
6525 	
6526 	   /* if the binary variable was the reason */
6527 	   if ( inferinfo == 0 )
6528 	   {
6529 	      assert( SCIPgetVarLbAtIndex(scip, consdata->binvar, bdchgidx, FALSE) > 0.5 );
6530 	      assert( infervar != consdata->binvar );
6531 	
6532 	      SCIP_CALL( SCIPaddConflictLb(scip, consdata->binvar, bdchgidx) );
6533 	   }
6534 	   else if ( inferinfo == 1 )
6535 	   {
6536 	      /* if the slack variable fixed to a positive value was the reason */
6537 	      assert( infervar != consdata->slackvar );
6538 	      /* Use a weaker comparison to SCIPvarGetLbAtIndex here (i.e., SCIPisPositive instead of SCIPisFeasPositive),
6539 	       * because SCIPvarGetLbAtIndex might differ from the local bound at time bdchgidx by epsilon. */
6540 	      assert( SCIPisPositive(scip, SCIPgetVarLbAtIndex(scip, consdata->slackvar, bdchgidx, FALSE)) );
6541 	      SCIP_CALL( SCIPaddConflictLb(scip, consdata->slackvar, bdchgidx) );
6542 	   }
6543 	   else
6544 	   {
6545 	      assert( inferinfo == 2 );
6546 	      assert( SCIPisFeasZero(scip, SCIPgetVarUbAtIndex(scip, consdata->slackvar, bdchgidx, FALSE)) );
6547 	      assert( SCIPconshdlrGetData(conshdlr)->dualreductions && SCIPallowStrongDualReds(scip) && SCIPallowWeakDualReds(scip) );
6548 	      SCIP_CALL( SCIPaddConflictUb(scip, consdata->slackvar, bdchgidx) );
6549 	   }
6550 	   *result = SCIP_SUCCESS;
6551 	
6552 	   return SCIP_OKAY;
6553 	}
6554 	
6555 	
6556 	/** variable rounding lock method of constraint handler
6557 	 *
6558 	 *  The up-rounding of the binary and slack variable may violate the constraint. If the linear
6559 	 *  constraint is not active, we lock all variables in the depending constraint - otherwise they
6560 	 *  will be fixed by dual presolving methods.
6561 	 */
6562 	static
6563 	SCIP_DECL_CONSLOCK(consLockIndicator)
6564 	{
6565 	   SCIP_CONSDATA* consdata;
6566 	
6567 	   assert( scip != NULL );
6568 	   assert( conshdlr != NULL );
6569 	   assert( cons != NULL );
6570 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6571 	   consdata = SCIPconsGetData(cons);
6572 	   assert( consdata != NULL );
6573 	   assert( consdata->binvar != NULL );
6574 	
6575 	#ifdef SCIP_MORE_DEBUG
6576 	   SCIPdebugMsg(scip, "%socking constraint <%s>.\n", (nlocksneg < 0) || (nlockspos < 0) ? "Unl" : "L", SCIPconsGetName(cons));
6577 	#endif
6578 	
6579 	   SCIP_CALL( SCIPaddVarLocksType(scip, consdata->binvar, locktype, nlocksneg, nlockspos) );
6580 	
6581 	   if ( consdata->linconsactive )
6582 	   {
6583 	      assert( consdata->slackvar != NULL );
6584 	
6585 	      SCIP_CALL( SCIPaddVarLocksType(scip, consdata->slackvar, locktype, nlocksneg, nlockspos) );
6586 	   }
6587 	   else
6588 	   {
6589 	      SCIP_VAR** linvars;
6590 	      SCIP_Real* linvals;
6591 	      SCIP_Bool haslhs;
6592 	      SCIP_Bool hasrhs;
6593 	      int nlinvars;
6594 	      int j;
6595 	
6596 	      assert( consdata->lincons != NULL );
6597 	      assert( consdata->slackvar == NULL );
6598 	
6599 	      nlinvars = SCIPgetNVarsLinear(scip, consdata->lincons);
6600 	      linvars = SCIPgetVarsLinear(scip, consdata->lincons);
6601 	      linvals = SCIPgetValsLinear(scip, consdata->lincons);
6602 	      haslhs = ! SCIPisInfinity(scip, REALABS(SCIPgetLhsLinear(scip, consdata->lincons)));
6603 	      hasrhs = ! SCIPisInfinity(scip, REALABS(SCIPgetRhsLinear(scip, consdata->lincons)));
6604 	
6605 	      for (j = 0; j < nlinvars; ++j)
6606 	      {
6607 	         assert( ! SCIPisZero(scip, linvals[j]) );
6608 	         if ( SCIPisPositive(scip, linvals[j]) )
6609 	         {
6610 	            if ( haslhs )
6611 	            {
6612 	               SCIP_CALL( SCIPaddVarLocksType(scip, linvars[j], locktype, nlockspos, nlocksneg) );
6613 	            }
6614 	            if ( hasrhs )
6615 	            {
6616 	               SCIP_CALL( SCIPaddVarLocksType(scip, linvars[j], locktype, nlocksneg, nlockspos) );
6617 	            }
6618 	         }
6619 	         else
6620 	         {
6621 	            if ( haslhs )
6622 	            {
6623 	               SCIP_CALL( SCIPaddVarLocksType(scip, linvars[j], locktype, nlocksneg, nlockspos) );
6624 	            }
6625 	            if ( hasrhs )
6626 	            {
6627 	               SCIP_CALL( SCIPaddVarLocksType(scip, linvars[j], locktype, nlockspos, nlocksneg) );
6628 	            }
6629 	         }
6630 	      }
6631 	   }
6632 	
6633 	   return SCIP_OKAY;
6634 	}
6635 	
6636 	
6637 	/** constraint display method of constraint handler */
6638 	static
6639 	SCIP_DECL_CONSPRINT(consPrintIndicator)
6640 	{
6641 	   SCIP_CONSDATA* consdata;
6642 	   SCIP_VAR* binvar;
6643 	   int rhs;
6644 	
6645 	   assert( scip != NULL );
6646 	   assert( conshdlr != NULL );
6647 	   assert( cons != NULL );
6648 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6649 	
6650 	   consdata = SCIPconsGetData(cons);
6651 	   assert( consdata != NULL );
6652 	   assert( consdata->binvar != NULL );
6653 	
6654 	   binvar = consdata->binvar;
6655 	   rhs = 1;
6656 	   if ( SCIPvarGetStatus(binvar) == SCIP_VARSTATUS_NEGATED )
6657 	   {
6658 	      rhs = 0;
6659 	      binvar = SCIPvarGetNegatedVar(binvar);
6660 	   }
6661 	   SCIPinfoMessage(scip, file, "<%s> = %d", SCIPvarGetName(binvar), rhs);
6662 	
6663 	   assert( consdata->slackvar != NULL );
6664 	   assert( consdata->lincons != NULL );
6665 	   SCIPinfoMessage(scip, file, " -> <%s> = 0", SCIPvarGetName(consdata->slackvar));
6666 	   SCIPinfoMessage(scip, file, " (<%s>)", SCIPconsGetName(consdata->lincons));
6667 	
6668 	   return SCIP_OKAY;
6669 	}
6670 	
6671 	
6672 	/** constraint copying method of constraint handler */
6673 	static
6674 	SCIP_DECL_CONSCOPY(consCopyIndicator)
6675 	{  /*lint --e{715}*/
6676 	   SCIP_CONSDATA* sourceconsdata;
6677 	   SCIP_CONS* targetlincons = NULL;
6678 	   SCIP_VAR* targetbinvar = NULL;
6679 	   SCIP_VAR* targetslackvar = NULL;
6680 	   SCIP_CONS* sourcelincons;
6681 	   SCIP_CONSHDLR* conshdlrlinear;
6682 	   const char* consname;
6683 	
6684 	   assert( scip != NULL );
6685 	   assert( sourcescip != NULL );
6686 	   assert( sourcecons != NULL );
6687 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(sourcecons)), CONSHDLR_NAME) == 0 );
6688 	
6689 	   *valid = TRUE;
6690 	
6691 	   if ( name != NULL )
6692 	      consname = name;
6693 	   else
6694 	      consname = SCIPconsGetName(sourcecons);
6695 	
6696 	#ifdef SCIP_MORE_DEBUG
6697 	   SCIPdebugMsg(scip, "Copying indicator constraint <%s> ...\n", consname);
6698 	#endif
6699 	
6700 	   if ( modifiable )
6701 	   {
6702 	      SCIPwarningMessage(scip, "cannot create modifiable indicator constraint when trying to copy constraint <%s>,\n", SCIPconsGetName(sourcecons));
6703 	      *valid = FALSE;
6704 	      return SCIP_OKAY;
6705 	   }
6706 	
6707 	   sourceconsdata = SCIPconsGetData(sourcecons);
6708 	   assert( sourceconsdata != NULL );
6709 	
6710 	   /* get linear constraint */
6711 	   sourcelincons = sourceconsdata->lincons;
6712 	
6713 	   /* if the constraint has been deleted -> create empty constraint (multi-aggregation might still contain slack variable, so indicator is valid) */
6714 	   if ( SCIPconsIsDeleted(sourcelincons) )
6715 	   {
6716 	      SCIPdebugMsg(scip, "Linear constraint <%s> deleted! Create empty linear constraint.\n", SCIPconsGetName(sourceconsdata->lincons));
6717 	
6718 	      SCIP_CALL( SCIPcreateConsLinear(scip, &targetlincons, "dummy", 0, NULL, NULL, 0.0, SCIPinfinity(scip),
6719 	            FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
6720 	      SCIP_CALL( SCIPaddCons(scip, targetlincons) );
6721 	   }
6722 	   else
6723 	   {
6724 	      /* get copied version of linear constraint */
6725 	      assert( sourcelincons != NULL );
6726 	      conshdlrlinear = SCIPfindConshdlr(sourcescip, "linear");
6727 	      assert( conshdlrlinear != NULL );
6728 	
6729 	      /* if copying scip after transforming the original instance before presolving, we need to correct the linear
6730 	       * constraint pointer */
6731 	      if ( SCIPisTransformed(sourcescip) && ! SCIPconsIsTransformed(sourcelincons) )
6732 	      {
6733 	         SCIP_CONS* translincons;
6734 	
6735 	         /* adjust the linear constraint in the original constraint (no need to release translincons) */
6736 	         SCIP_CALL( SCIPgetTransformedCons(sourcescip, sourcelincons, &translincons) );
6737 	         assert( translincons != NULL );
6738 	         SCIP_CALL( SCIPreleaseCons(sourcescip, &sourceconsdata->lincons) );
6739 	         SCIP_CALL( SCIPcaptureCons(sourcescip, translincons) );
6740 	         sourceconsdata->lincons = translincons;
6741 	         sourcelincons = translincons;
6742 	      }
6743 	
6744 	      SCIP_CALL( SCIPgetConsCopy(sourcescip, scip, sourcelincons, &targetlincons, conshdlrlinear, varmap, consmap, SCIPconsGetName(sourcelincons),
6745 	            SCIPconsIsInitial(sourcelincons), SCIPconsIsSeparated(sourcelincons), SCIPconsIsEnforced(sourcelincons), SCIPconsIsChecked(sourcelincons),
6746 	            SCIPconsIsPropagated(sourcelincons), SCIPconsIsLocal(sourcelincons), SCIPconsIsModifiable(sourcelincons), SCIPconsIsDynamic(sourcelincons),
6747 	            SCIPconsIsRemovable(sourcelincons), SCIPconsIsStickingAtNode(sourcelincons), global, valid) );
6748 	   }
6749 	
6750 	   /* find copied variable corresponding to binvar */
6751 	   if ( *valid )
6752 	   {
6753 	      SCIP_VAR* sourcebinvar;
6754 	
6755 	      sourcebinvar = sourceconsdata->binvar;
6756 	      assert( sourcebinvar != NULL );
6757 	
6758 	      SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcebinvar, &targetbinvar, varmap, consmap, global, valid) );
6759 	   }
6760 	
6761 	   /* find copied variable corresponding to slackvar */
6762 	   if ( *valid )
6763 	   {
6764 	      SCIP_VAR* sourceslackvar;
6765 	
6766 	      sourceslackvar = sourceconsdata->slackvar;
6767 	      assert( sourceslackvar != NULL );
6768 	
6769 	      SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourceslackvar, &targetslackvar, varmap, consmap, global, valid) );
6770 	   }
6771 	
6772 	   /* create indicator constraint */
6773 	   if ( *valid )
6774 	   {
6775 	      assert( targetlincons != NULL );
6776 	      assert( targetbinvar != NULL );
6777 	      assert( targetslackvar != NULL );
6778 	
6779 	      /* creates indicator constraint (and captures the linear constraint) */
6780 	      /* Note that the copied constraint has activeone = TRUE, since the target binary variable already was negated if needed. */
6781 	      SCIP_CALL( SCIPcreateConsIndicatorGenericLinCons(scip, cons, consname, targetbinvar, targetlincons, targetslackvar, TRUE,
6782 	            initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
6783 	   }
6784 	   else
6785 	   {
6786 	      SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "could not copy linear constraint <%s>\n", SCIPconsGetName(sourcelincons));
6787 	   }
6788 	
6789 	   /* release copied linear constraint */
6790 	   if ( targetlincons != NULL )
6791 	   {
6792 	      SCIP_CALL( SCIPreleaseCons(scip, &targetlincons) );
6793 	   }
6794 	
6795 	   return SCIP_OKAY;
6796 	}
6797 	
6798 	
6799 	/** constraint parsing method of constraint handler */
6800 	static
6801 	SCIP_DECL_CONSPARSE(consParseIndicator)
6802 	{  /*lint --e{715}*/
6803 	   char binvarname[1024];
6804 	   char slackvarname[1024];
6805 	   char linconsname[1024];
6806 	   SCIP_VAR* binvar;
6807 	   SCIP_VAR* slackvar;
6808 	   SCIP_CONS* lincons;
6809 	   int zeroone;
6810 	   int nargs;
6811 	
6812 	   *success = TRUE;
6813 	
6814 	   /* read indicator constraint */
6815 	   /* coverity[secure_coding] */
6816 	   nargs = sscanf(str, " <%1023[^>]> = %d -> <%1023[^>]> = 0 (<%1023[^>]>)", binvarname, &zeroone, slackvarname, linconsname);
6817 	
6818 	   /* downward compatible: accept missing linear constraint at end */
6819 	   if ( nargs != 3 && nargs != 4 )
6820 	   {
6821 	      SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error: expected the following form: <var> = [0|1] -> <var> = 0 (<lincons>).\n%s\n", str);
6822 	      *success = FALSE;
6823 	      return SCIP_OKAY;
6824 	   }
6825 	
6826 	   if ( zeroone != 0 && zeroone != 1 )
6827 	   {
6828 	      SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error: expected the following form: <var> = [0|1] -> <var> = 0.\n%s\n", str);
6829 	      *success = FALSE;
6830 	      return SCIP_OKAY;
6831 	   }
6832 	
6833 	   /* get binary variable */
6834 	   binvar = SCIPfindVar(scip, binvarname);
6835 	   if ( binvar == NULL )
6836 	   {
6837 	      SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown variable <%s>\n", binvarname);
6838 	      *success = FALSE;
6839 	      return SCIP_OKAY;
6840 	   }
6841 	   /* check whether we need the complemented variable */
6842 	   if ( zeroone == 0 )
6843 	      SCIP_CALL( SCIPgetNegatedVar(scip, binvar, &binvar) );
6844 	
6845 	   /* get slack variable */
6846 	   slackvar = SCIPfindVar(scip, slackvarname);
6847 	   if ( slackvar == NULL )
6848 	   {
6849 	      SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown variable <%s>\n", slackvarname);
6850 	      *success = FALSE;
6851 	      return SCIP_OKAY;
6852 	   }
6853 	
6854 	   /* determine linear constraint */
6855 	   if ( nargs == 4 )
6856 	   {
6857 	      lincons = SCIPfindCons(scip, linconsname);
6858 	      if ( lincons == NULL )
6859 	      {
6860 	         SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown constraint <%s>\n", linconsname);
6861 	         *success = FALSE;
6862 	         return SCIP_OKAY;
6863 	      }
6864 	      if ( strncmp(SCIPconshdlrGetName(SCIPconsGetHdlr(lincons)), "linear", 6) != 0 )
6865 	      {
6866 	         SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "constraint <%s> is not linear\n", linconsname);
6867 	         *success = FALSE;
6868 	         return SCIP_OKAY;
6869 	      }
6870 	   }
6871 	   else
6872 	   {
6873 	      const char* posstr;
6874 	
6875 	      /* for backward compability try to determine name of linear constraint from variables names */
6876 	      assert( nargs == 3 );
6877 	
6878 	      /* find matching linear constraint */
6879 	      posstr = strstr(slackvarname, "indslack");
6880 	      if ( posstr == NULL )
6881 	      {
6882 	         SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "strange slack variable name: <%s>\n", slackvarname);
6883 	         *success = FALSE;
6884 	         return SCIP_OKAY;
6885 	      }
6886 	
6887 	      /* overwrite binvarname: set up name for linear constraint */
6888 	      (void) SCIPsnprintf(binvarname, 1023, "indlin%s", posstr+8);
6889 	
6890 	      lincons = SCIPfindCons(scip, binvarname);
6891 	      if ( lincons == NULL )
6892 	      {
6893 	         /* if not found - check without indlin */
6894 	         (void) SCIPsnprintf(binvarname, 1023, "%s", posstr+9);
6895 	         lincons = SCIPfindCons(scip, binvarname);
6896 	
6897 	         if ( lincons == NULL )
6898 	         {
6899 	            /* if not found - check without indrhs or indlhs */
6900 	            (void) SCIPsnprintf(binvarname, 1023, "%s", posstr+16);
6901 	            lincons = SCIPfindCons(scip, binvarname);
6902 	
6903 	            if( lincons == NULL )
6904 	            {
6905 	               SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "while parsing indicator constraint <%s>: unknown linear constraint <indlin%s>, <%s> or <%s>.\n",
6906 	                  name, posstr+8, posstr+9, posstr+16);
6907 	               *success = FALSE;
6908 	               return SCIP_OKAY;
6909 	            }
6910 	         }
6911 	      }
6912 	   }
6913 	   assert( lincons != NULL );
6914 	
6915 	   /* check correct linear constraint */
6916 	   if ( ! SCIPisInfinity(scip, -SCIPgetLhsLinear(scip, lincons)) && ! SCIPisInfinity(scip, SCIPgetRhsLinear(scip, lincons)) )
6917 	   {
6918 	      SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "while parsing indicator constraint <%s>: linear constraint is ranged or equation.\n", name);
6919 	      *success = FALSE;
6920 	      return SCIP_OKAY;
6921 	   }
6922 	
6923 	   /* create indicator constraint */
6924 	   SCIP_CALL( SCIPcreateConsIndicatorLinCons(scip, cons, name, binvar, lincons, slackvar,
6925 	         initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
6926 	
6927 	   return SCIP_OKAY;
6928 	}
6929 	
6930 	
6931 	/** constraint enabling notification method of constraint handler */
6932 	static
6933 	SCIP_DECL_CONSENABLE(consEnableIndicator)
6934 	{
6935 	   SCIP_CONSHDLRDATA* conshdlrdata;
6936 	   SCIP_CONSDATA* consdata;
6937 	
6938 	   assert( scip != NULL );
6939 	   assert( conshdlr != NULL );
6940 	   assert( cons != NULL );
6941 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6942 	
6943 	#ifdef SCIP_MORE_DEBUG
6944 	   SCIPdebugMsg(scip, "Enabling constraint <%s>.\n", SCIPconsGetName(cons));
6945 	#endif
6946 	
6947 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
6948 	   assert( conshdlrdata != NULL );
6949 	
6950 	   consdata = SCIPconsGetData(cons);
6951 	   assert( consdata != NULL );
6952 	
6953 	   if ( conshdlrdata->altlp != NULL )
6954 	   {
6955 	      assert( conshdlrdata->sepaalternativelp );
6956 	
6957 	      if ( consdata->colindex >= 0 )
6958 	      {
6959 	         SCIP_CALL( unfixAltLPVariable(conshdlrdata->altlp, consdata->colindex) );
6960 	      }
6961 	   }
6962 	
6963 	   return SCIP_OKAY;
6964 	}
6965 	
6966 	
6967 	/** constraint disabling notification method of constraint handler */
6968 	static
6969 	SCIP_DECL_CONSDISABLE(consDisableIndicator)
6970 	{
6971 	   SCIP_CONSHDLRDATA* conshdlrdata;
6972 	
6973 	   assert( scip != NULL );
6974 	   assert( conshdlr != NULL );
6975 	   assert( cons != NULL );
6976 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
6977 	
6978 	#ifdef SCIP_MORE_DEBUG
6979 	   SCIPdebugMsg(scip, "Disabling constraint <%s>.\n", SCIPconsGetName(cons));
6980 	#endif
6981 	
6982 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
6983 	   assert( conshdlrdata != NULL );
6984 	
6985 	   if ( conshdlrdata->altlp != NULL )
6986 	   {
6987 	      SCIP_CONSDATA* consdata;
6988 	
6989 	      consdata = SCIPconsGetData(cons);
6990 	      assert( consdata != NULL );
6991 	      assert( conshdlrdata->sepaalternativelp );
6992 	
6993 	      if ( consdata->colindex >= 0 )
6994 	      {
6995 	         SCIP_CALL( fixAltLPVariable(conshdlrdata->altlp, consdata->colindex) );
6996 	      }
6997 	   }
6998 	
6999 	   return SCIP_OKAY;
7000 	}
7001 	
7002 	
7003 	/** constraint method of constraint handler which returns the variables (if possible) */
7004 	static
7005 	SCIP_DECL_CONSGETVARS(consGetVarsIndicator)
7006 	{  /*lint --e{715}*/
7007 	   SCIP_CONSDATA* consdata;
7008 	   int nvars = 0;
7009 	
7010 	   assert( scip != NULL );
7011 	   assert( cons != NULL );
7012 	   assert( vars != NULL );
7013 	   assert( success != NULL );
7014 	
7015 	   if ( varssize < 0 )
7016 	      return SCIP_INVALIDDATA;
7017 	   assert( varssize >= 0 );
7018 	
7019 	   (*success) = TRUE;
7020 	
7021 	   /* if indicator constraint is already deleted */
7022 	   if ( SCIPconsIsDeleted(cons) )
7023 	      return SCIP_OKAY;
7024 	
7025 	   consdata = SCIPconsGetData(cons);
7026 	   assert( consdata != NULL );
7027 	   assert( consdata->lincons != NULL );
7028 	
7029 	   if ( consdata->binvar != NULL )
7030 	   {
7031 	      assert( varssize > 0 );
7032 	      vars[nvars++] = consdata->binvar;
7033 	   }
7034 	   if ( consdata->slackvar != NULL )
7035 	   {
7036 	      assert( varssize > nvars );
7037 	      vars[nvars++] = consdata->slackvar;
7038 	   }
7039 	
7040 	   /* if linear constraint of indicator is already deleted */
7041 	   if ( SCIPconsIsDeleted(consdata->lincons) )
7042 	      return SCIP_OKAY;
7043 	
7044 	   SCIP_CALL( SCIPgetConsVars(scip, consdata->lincons, &(vars[nvars]), varssize - nvars, success) );
7045 	
7046 	   return SCIP_OKAY;
7047 	}
7048 	
7049 	
7050 	/** constraint method of constraint handler which returns the number of variables (if possible) */
7051 	static
7052 	SCIP_DECL_CONSGETNVARS(consGetNVarsIndicator)
7053 	{  /*lint --e{715}*/
7054 	   SCIP_CONSDATA* consdata;
7055 	   int nlinvars;
7056 	
7057 	   assert( scip != NULL );
7058 	   assert( cons != NULL );
7059 	   assert( nvars != NULL );
7060 	   assert( success != NULL );
7061 	
7062 	   (*success) = TRUE;
7063 	   *nvars = 0;
7064 	
7065 	   /* if indicator constraint is already deleted */
7066 	   if ( SCIPconsIsDeleted(cons) )
7067 	      return SCIP_OKAY;
7068 	
7069 	   consdata = SCIPconsGetData(cons);
7070 	   assert( consdata != NULL );
7071 	   assert( consdata->lincons != NULL );
7072 	
7073 	   if ( consdata->binvar != NULL )
7074 	      ++(*nvars);
7075 	   if ( consdata->slackvar != NULL )
7076 	      ++(*nvars);
7077 	
7078 	   /* if linear constraint of indicator is already deleted */
7079 	   if ( SCIPconsIsDeleted(consdata->lincons) )
7080 	      return SCIP_OKAY;
7081 	
7082 	   SCIP_CALL( SCIPgetConsNVars(scip, consdata->lincons, &nlinvars, success) );
7083 	
7084 	   if ( *success )
7085 	   {
7086 	      assert( nlinvars >= 0 );
7087 	      *nvars += nlinvars;
7088 	   }
7089 	
7090 	   return SCIP_OKAY;
7091 	}
7092 	
7093 	
7094 	/** constraint handler method to suggest dive bound changes during the generic diving algorithm */
7095 	static
7096 	SCIP_DECL_CONSGETDIVEBDCHGS(consGetDiveBdChgsIndicator)
7097 	{
7098 	   SCIP_CONS** indconss;
7099 	   int nindconss;
7100 	   int c;
7101 	   SCIP_VAR* bestvar = NULL;
7102 	   SCIP_Bool bestvarroundup = FALSE;
7103 	   SCIP_Real bestscore = SCIP_REAL_MIN;
7104 	
7105 	   assert(scip != NULL);
7106 	   assert(conshdlr != NULL);
7107 	   assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
7108 	   assert(diveset != NULL);
7109 	   assert(success != NULL);
7110 	   assert(infeasible != NULL);
7111 	
7112 	   *success = FALSE;
7113 	   *infeasible = FALSE;
7114 	
7115 	   indconss = SCIPconshdlrGetConss(conshdlr);
7116 	   nindconss = SCIPconshdlrGetNConss(conshdlr);
7117 	
7118 	   /* loop over indicator constraints and score indicator variables with already integral solution value  */
7119 	   for (c = 0; c < nindconss; ++c)
7120 	   {
7121 	      /* check whether constraint is violated */
7122 	      if( SCIPisViolatedIndicator(scip, indconss[c], sol) )
7123 	      {
7124 	         SCIP_VAR* binvar;
7125 	         SCIP_Real solval;
7126 	
7127 	         binvar = SCIPgetBinaryVarIndicator(indconss[c]);
7128 	         solval = SCIPgetSolVal(scip, sol, binvar);
7129 	
7130 	         /* we only treat indicator variables with integral solution values that are not yet fixed */
7131 	         if( SCIPisFeasIntegral(scip, solval) && SCIPvarGetLbLocal(binvar) < SCIPvarGetUbLocal(binvar) - 0.5 )
7132 	         {
7133 	            SCIP_Real score;
7134 	            SCIP_Bool roundup;
7135 	
7136 	            SCIP_CALL( SCIPgetDivesetScore(scip, diveset, SCIP_DIVETYPE_INTEGRALITY, binvar, solval, 0.0,
7137 	                  &score, &roundup) );
7138 	
7139 	            /* best candidate maximizes the score */
7140 	            if( score > bestscore )
7141 	            {
7142 	               bestscore = score;
7143 	               *success = TRUE;
7144 	               bestvar = binvar;
7145 	               bestvarroundup = roundup;
7146 	            }
7147 	         }
7148 	      }
7149 	   }
7150 	
7151 	   assert(! *success || bestvar != NULL);
7152 	
7153 	   if( *success )
7154 	   {
7155 	      /* if the diving score voted for fixing the best variable to 1.0, we add this as the preferred bound change */
7156 	      SCIP_CALL( SCIPaddDiveBoundChange(scip, bestvar, SCIP_BRANCHDIR_UPWARDS, 1.0, bestvarroundup) );
7157 	      SCIP_CALL( SCIPaddDiveBoundChange(scip, bestvar, SCIP_BRANCHDIR_DOWNWARDS, 0.0, ! bestvarroundup) );
7158 	   }
7159 	
7160 	   return SCIP_OKAY;
7161 	}
7162 	
7163 	/* ---------------- Constraint specific interface methods ---------------- */
7164 	
7165 	/** creates the handler for indicator constraints and includes it in SCIP */
7166 	SCIP_RETCODE SCIPincludeConshdlrIndicator(
7167 	   SCIP*                 scip                /**< SCIP data structure */
7168 	   )
7169 	{
7170 	   SCIP_CONFLICTHDLRDATA* conflicthdlrdata;
7171 	   SCIP_CONFLICTHDLR* conflicthdlr;
7172 	   SCIP_CONSHDLRDATA* conshdlrdata;
7173 	   SCIP_CONSHDLR* conshdlr;
7174 	
7175 	   /* create constraint handler data (used in conflicthdlrdata) */
7176 	   SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
7177 	
7178 	   /* create event handler for bound change events */
7179 	   conshdlrdata->eventhdlrbound = NULL;
7180 	   SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &(conshdlrdata->eventhdlrbound),  EVENTHDLR_BOUND_NAME, EVENTHDLR_BOUND_DESC,
7181 	         eventExecIndicatorBound, NULL) );
7182 	   assert(conshdlrdata->eventhdlrbound != NULL);
7183 	
7184 	   /* create event handler for restart events */
7185 	   conshdlrdata->eventhdlrrestart = NULL;
7186 	   SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &(conshdlrdata->eventhdlrrestart), EVENTHDLR_RESTART_NAME, EVENTHDLR_RESTART_DESC,
7187 	         eventExecIndicatorRestart, NULL) );
7188 	   assert( conshdlrdata->eventhdlrrestart != NULL );
7189 	
7190 	   conshdlrdata->heurtrysol = NULL;
7191 	   conshdlrdata->sepaalternativelp = DEFAULT_SEPAALTERNATIVELP;
7192 	   conshdlrdata->nolinconscont = DEFAULT_NOLINCONSCONT;
7193 	   conshdlrdata->forcerestart = DEFAULT_FORCERESTART;
7194 	   conshdlrdata->binvarhash = NULL;
7195 	
7196 	   /* initialize constraint handler data */
7197 	   initConshdlrData(scip, conshdlrdata);
7198 	
7199 	   /* the following three variables cannot be initialized in the above method, because initConshdlrData() is also called
7200 	    * in the CONSINIT callback, but these variables might be used even before the is ccallback is called, so we would
7201 	    * lose the data added before calling this callback */
7202 	   conshdlrdata->addlincons = NULL;
7203 	   conshdlrdata->naddlincons = 0;
7204 	   conshdlrdata->maxaddlincons = 0;
7205 	
7206 	   /* include constraint handler */
7207 	   SCIP_CALL( SCIPincludeConshdlrBasic(scip, &conshdlr, CONSHDLR_NAME, CONSHDLR_DESC,
7208 	         CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY, CONSHDLR_EAGERFREQ, CONSHDLR_NEEDSCONS,
7209 	         consEnfolpIndicator, consEnfopsIndicator, consCheckIndicator, consLockIndicator,
7210 	         conshdlrdata) );
7211 	
7212 	   assert( conshdlr != NULL );
7213 	
7214 	   /* set non-fundamental callbacks via specific setter functions */
7215 	   SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyIndicator, consCopyIndicator) );
7216 	   SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteIndicator) );
7217 	   SCIP_CALL( SCIPsetConshdlrDisable(scip, conshdlr, consDisableIndicator) );
7218 	   SCIP_CALL( SCIPsetConshdlrEnable(scip, conshdlr, consEnableIndicator) );
7219 	   SCIP_CALL( SCIPsetConshdlrGetDiveBdChgs(scip, conshdlr, consGetDiveBdChgsIndicator) );
7220 	   SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitIndicator) );
7221 	   SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolIndicator) );
7222 	   SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeIndicator) );
7223 	   SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsIndicator) );
7224 	   SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsIndicator) );
7225 	   SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitIndicator) );
7226 	   SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreIndicator) );
7227 	   SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolIndicator) );
7228 	   SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpIndicator) );
7229 	   SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseIndicator) );
7230 	   SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolIndicator, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
7231 	   SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintIndicator) );
7232 	   SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropIndicator, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
7233 	         CONSHDLR_PROP_TIMING) );
7234 	   SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropIndicator) );
7235 	   SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpIndicator, consSepasolIndicator, CONSHDLR_SEPAFREQ,
7236 	         CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
7237 	   SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransIndicator) );
7238 	   SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxIndicator) );
7239 	
7240 	   /* add upgrading method */
7241 	   if ( SCIPfindConshdlr(scip, "linear") != NULL )
7242 	   {
7243 	      /* include the linear constraint upgrade in the linear constraint handler */
7244 	      SCIP_CALL( SCIPincludeLinconsUpgrade(scip, linconsUpgdIndicator, LINCONSUPGD_PRIORITY, CONSHDLR_NAME) );
7245 	   }
7246 	
7247 	   /* create conflict handler data */
7248 	   SCIP_CALL( SCIPallocBlockMemory(scip, &conflicthdlrdata) );
7249 	   conflicthdlrdata->conshdlrdata = conshdlrdata;
7250 	   conflicthdlrdata->conshdlr = conshdlr;
7251 	   assert( conflicthdlrdata->conshdlr != NULL );
7252 	
7253 	   /* create conflict handler for indicator constraints */
7254 	   SCIP_CALL( SCIPincludeConflicthdlrBasic(scip, &conflicthdlr, CONFLICTHDLR_NAME, CONFLICTHDLR_DESC, CONFLICTHDLR_PRIORITY,
7255 	         conflictExecIndicator, conflicthdlrdata) );
7256 	
7257 	   SCIP_CALL( SCIPsetConflicthdlrFree(scip, conflicthdlr, conflictFreeIndicator) );
7258 	
7259 	   /* add indicator constraint handler parameters */
7260 	   SCIP_CALL( SCIPaddBoolParam(scip,
7261 	         "constraints/indicator/branchindicators",
7262 	         "Branch on indicator constraints in enforcing?",
7263 	         &conshdlrdata->branchindicators, TRUE, DEFAULT_BRANCHINDICATORS, NULL, NULL) );
7264 	
7265 	   SCIP_CALL( SCIPaddBoolParam(scip,
7266 	         "constraints/indicator/genlogicor",
7267 	         "Generate logicor constraints instead of cuts?",
7268 	         &conshdlrdata->genlogicor, TRUE, DEFAULT_GENLOGICOR, NULL, NULL) );
7269 	
7270 	   SCIP_CALL( SCIPaddBoolParam(scip,
7271 	         "constraints/indicator/addcoupling",
7272 	         "Add coupling constraints or rows if big-M is small enough?",
7273 	         &conshdlrdata->addcoupling, TRUE, DEFAULT_ADDCOUPLING, NULL, NULL) );
7274 	
7275 	   SCIP_CALL( SCIPaddRealParam(scip,
7276 	         "constraints/indicator/maxcouplingvalue",
7277 	         "maximum coefficient for binary variable in coupling constraint",
7278 	         &conshdlrdata->maxcouplingvalue, TRUE, DEFAULT_MAXCOUPLINGVALUE, 0.0, 1e9, NULL, NULL) );
7279 	
7280 	   SCIP_CALL( SCIPaddBoolParam(scip,
7281 	         "constraints/indicator/addcouplingcons",
7282 	         "Add initial variable upper bound constraints, if 'addcoupling' is true?",
7283 	         &conshdlrdata->addcouplingcons, TRUE, DEFAULT_ADDCOUPLINGCONS, NULL, NULL) );
7284 	
7285 	   SCIP_CALL( SCIPaddBoolParam(scip,
7286 	         "constraints/indicator/sepacouplingcuts",
7287 	         "Should the coupling inequalities be separated dynamically?",
7288 	         &conshdlrdata->sepacouplingcuts, TRUE, DEFAULT_SEPACOUPLINGCUTS, NULL, NULL) );
7289 	
7290 	   SCIP_CALL( SCIPaddBoolParam(scip,
7291 	         "constraints/indicator/sepacouplinglocal",
7292 	         "Allow to use local bounds in order to separate coupling inequalities?",
7293 	         &conshdlrdata->sepacouplinglocal, TRUE, DEFAULT_SEPACOUPLINGLOCAL, NULL, NULL) );
7294 	
7295 	   SCIP_CALL( SCIPaddRealParam(scip,
7296 	         "constraints/indicator/sepacouplingvalue",
7297 	         "maximum coefficient for binary variable in separated coupling constraint",
7298 	         &conshdlrdata->sepacouplingvalue, TRUE, DEFAULT_SEPACOUPLINGVALUE, 0.0, 1e9, NULL, NULL) );
7299 	
7300 	   SCIP_CALL( SCIPaddBoolParam(scip,
7301 	         "constraints/indicator/sepaperspective",
7302 	         "Separate cuts based on perspective formulation?",
7303 	         &conshdlrdata->sepaperspective, TRUE, DEFAULT_SEPAPERSPECTIVE, NULL, NULL) );
7304 	
7305 	   SCIP_CALL( SCIPaddBoolParam(scip,
7306 	         "constraints/indicator/sepapersplocal",
7307 	         "Allow to use local bounds in order to separate perspective cuts?",
7308 	         &conshdlrdata->sepapersplocal, TRUE, DEFAULT_SEPAPERSPLOCAL, NULL, NULL) );
7309 	
7310 	   SCIP_CALL( SCIPaddIntParam(scip,
7311 	         "constraints/indicator/maxsepanonviolated",
7312 	         "maximal number of separated non violated IISs, before separation is stopped",
7313 	         &conshdlrdata->maxsepanonviolated, FALSE, DEFAULT_MAXSEPANONVIOLATED, 0, INT_MAX, NULL, NULL) );
7314 	
7315 	   SCIP_CALL( SCIPaddBoolParam(scip,
7316 	         "constraints/indicator/updatebounds",
7317 	         "Update bounds of original variables for separation?",
7318 	         &conshdlrdata->updatebounds, TRUE, DEFAULT_UPDATEBOUNDS, NULL, NULL) );
7319 	
7320 	   SCIP_CALL( SCIPaddRealParam(scip,
7321 	         "constraints/indicator/maxconditionaltlp",
7322 	         "maximum estimated condition of the solution basis matrix of the alternative LP to be trustworthy (0.0 to disable check)",
7323 	         &conshdlrdata->maxconditionaltlp, TRUE, DEFAULT_MAXCONDITIONALTLP, 0.0, SCIP_REAL_MAX, NULL, NULL) );
7324 	
7325 	   SCIP_CALL( SCIPaddIntParam(scip,
7326 	         "constraints/indicator/maxsepacuts",
7327 	         "maximal number of cuts separated per separation round",
7328 	         &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
7329 	
7330 	   SCIP_CALL( SCIPaddIntParam(scip,
7331 	         "constraints/indicator/maxsepacutsroot",
7332 	         "maximal number of cuts separated per separation round in the root node",
7333 	         &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
7334 	
7335 	   SCIP_CALL( SCIPaddBoolParam(scip,
7336 	         "constraints/indicator/removeindicators",
7337 	         "Remove indicator constraint if corresponding variable bound constraint has been added?",
7338 	         &conshdlrdata->removeindicators, TRUE, DEFAULT_REMOVEINDICATORS, NULL, NULL) );
7339 	
7340 	   SCIP_CALL( SCIPaddBoolParam(scip,
7341 	         "constraints/indicator/generatebilinear",
7342 	         "Do not generate indicator constraint, but a bilinear constraint instead?",
7343 	         &conshdlrdata->generatebilinear, TRUE, DEFAULT_GENERATEBILINEAR, NULL, NULL) );
7344 	
7345 	   SCIP_CALL( SCIPaddBoolParam(scip,
7346 	         "constraints/indicator/scaleslackvar",
7347 	         "Scale slack variable coefficient at construction time?",
7348 	         &conshdlrdata->scaleslackvar, TRUE, DEFAULT_SCALESLACKVAR, NULL, NULL) );
7349 	
7350 	   SCIP_CALL( SCIPaddBoolParam(scip,
7351 	         "constraints/indicator/trysolutions",
7352 	         "Try to make solutions feasible by setting indicator variables?",
7353 	         &conshdlrdata->trysolutions, TRUE, DEFAULT_TRYSOLUTIONS, NULL, NULL) );
7354 	
7355 	   SCIP_CALL( SCIPaddBoolParam(scip,
7356 	         "constraints/indicator/enforcecuts",
7357 	         "In enforcing try to generate cuts (only if sepaalternativelp is true)?",
7358 	         &conshdlrdata->enforcecuts, TRUE, DEFAULT_ENFORCECUTS, NULL, NULL) );
7359 	
7360 	   SCIP_CALL( SCIPaddBoolParam(scip,
7361 	         "constraints/indicator/dualreductions",
7362 	         "Should dual reduction steps be performed?",
7363 	         &conshdlrdata->dualreductions, TRUE, DEFAULT_DUALREDUCTIONS, NULL, NULL) );
7364 	
7365 	   SCIP_CALL( SCIPaddBoolParam(scip,
7366 	         "constraints/indicator/addopposite",
7367 	         "Add opposite inequality in nodes in which the binary variable has been fixed to 0?",
7368 	         &conshdlrdata->addopposite, TRUE, DEFAULT_ADDOPPOSITE, NULL, NULL) );
7369 	
7370 	   SCIP_CALL( SCIPaddBoolParam(scip,
7371 	         "constraints/indicator/conflictsupgrade",
7372 	         "Try to upgrade bounddisjunction conflicts by replacing slack variables?",
7373 	         &conshdlrdata->conflictsupgrade, TRUE, DEFAULT_CONFLICTSUPGRADE, NULL, NULL) );
7374 	
7375 	   SCIP_CALL( SCIPaddRealParam(scip,
7376 	         "constraints/indicator/restartfrac",
7377 	         "fraction of binary variables that need to be fixed before restart occurs (in forcerestart)",
7378 	         &conshdlrdata->restartfrac, TRUE, DEFAULT_RESTARTFRAC, 0.0, 1.0, NULL, NULL) );
7379 	
7380 	   SCIP_CALL( SCIPaddBoolParam(scip,
7381 	         "constraints/indicator/useotherconss",
7382 	         "Collect other constraints to alternative LP?",
7383 	         &conshdlrdata->useotherconss, TRUE, DEFAULT_USEOTHERCONSS, NULL, NULL) );
7384 	
7385 	   SCIP_CALL( SCIPaddBoolParam(scip,
7386 	         "constraints/indicator/useobjectivecut",
7387 	         "Use objective cut with current best solution to alternative LP?",
7388 	         &conshdlrdata->useobjectivecut, TRUE, DEFAULT_USEOBJECTIVECUT, NULL, NULL) );
7389 	
7390 	   SCIP_CALL( SCIPaddBoolParam(scip,
7391 	         "constraints/indicator/trysolfromcover",
7392 	         "Try to construct a feasible solution from a cover?",
7393 	         &conshdlrdata->trysolfromcover, TRUE, DEFAULT_TRYSOLFROMCOVER, NULL, NULL) );
7394 	
7395 	   SCIP_CALL( SCIPaddBoolParam(scip,
7396 	         "constraints/indicator/upgradelinear",
7397 	         "Try to upgrade linear constraints to indicator constraints?",
7398 	         &conshdlrdata->upgradelinear, TRUE, DEFAULT_UPGRADELINEAR, NULL, NULL) );
7399 	
7400 	   /* parameters that should not be changed after problem stage: */
7401 	   SCIP_CALL( SCIPaddBoolParam(scip,
7402 	         "constraints/indicator/sepaalternativelp",
7403 	         "Separate using the alternative LP?",
7404 	         &conshdlrdata->sepaalternativelp_, TRUE, DEFAULT_SEPAALTERNATIVELP, paramChangedIndicator, NULL) );
7405 	
7406 	   SCIP_CALL( SCIPaddBoolParam(scip,
7407 	         "constraints/indicator/forcerestart",
7408 	         "Force restart if absolute gap is 1 or enough binary variables have been fixed?",
7409 	         &conshdlrdata->forcerestart_, TRUE, DEFAULT_FORCERESTART, paramChangedIndicator, NULL) );
7410 	
7411 	   SCIP_CALL( SCIPaddBoolParam(scip,
7412 	         "constraints/indicator/nolinconscont",
7413 	         "Decompose problem (do not generate linear constraint if all variables are continuous)?",
7414 	         &conshdlrdata->nolinconscont_, TRUE, DEFAULT_NOLINCONSCONT, paramChangedIndicator, NULL) );
7415 	
7416 	   return SCIP_OKAY;
7417 	}
7418 	
7419 	/** creates and captures an indicator constraint
7420 	 *
7421 	 *  @note @a binvar is checked to be binary only later. This enables a change of the type in
7422 	 *  procedures reading an instance.
7423 	 *
7424 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
7425 	 */
7426 	SCIP_RETCODE SCIPcreateConsIndicator(
7427 	   SCIP*                 scip,               /**< SCIP data structure */
7428 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint (indicator or quadratic) */
7429 	   const char*           name,               /**< name of constraint */
7430 	   SCIP_VAR*             binvar,             /**< binary indicator variable (or NULL) */
7431 	   int                   nvars,              /**< number of variables in the inequality */
7432 	   SCIP_VAR**            vars,               /**< array with variables of inequality (or NULL) */
7433 	   SCIP_Real*            vals,               /**< values of variables in inequality (or NULL) */
7434 	   SCIP_Real             rhs,                /**< rhs of the inequality */
7435 	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP? Usually set to TRUE. */
7436 	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
7437 	                                              *   Usually set to TRUE. */
7438 	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
7439 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7440 	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
7441 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7442 	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
7443 	                                              *   Usually set to TRUE. */
7444 	   SCIP_Bool             local,              /**< is constraint only valid locally?
7445 	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
7446 	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
7447 	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
7448 	                                              *   are separated as constraints. */
7449 	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
7450 	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
7451 	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
7452 	                                              *   if it may be moved to a more global node?
7453 	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
7454 	   )
7455 	{
7456 	   return SCIPcreateConsIndicatorGeneric(scip, cons, name, binvar, nvars, vars, vals, rhs, TRUE, TRUE, initial,
7457 	                                         separate, enforce, check, propagate, local, dynamic, removable, stickingatnode);
7458 	}
7459 	
7460 	/** creates and captures a indicator constraint in a more generic version.
7461 	 *
7462 	 *  The key difference from SCIPcreateConsIndicator() is the activeone and lessthanineq Booleans.
7463 	 *  If \f$z = o\f$, with \f$o\f$ the activeone flag, then:
7464 	 *  if lessthanineq then \f$a^T x \leq b\f$ holds, else the passed vectors are assumed to be of the form \f$a^T x \geq b\f$.
7465 	 *  The underlying linear constraint is always created as a less-than inequality.
7466 	 */
7467 	SCIP_RETCODE SCIPcreateConsIndicatorGeneric(
7468 	   SCIP*                 scip,               /**< SCIP data structure */
7469 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint (indicator or quadratic) */
7470 	   const char*           name,               /**< name of constraint */
7471 	   SCIP_VAR*             binvar,             /**< binary indicator variable (or NULL) */
7472 	   int                   nvars,              /**< number of variables in the inequality */
7473 	   SCIP_VAR**            vars,               /**< array with variables of inequality (or NULL) */
7474 	   SCIP_Real*            vals,               /**< values of variables in inequality (or NULL) */
7475 	   SCIP_Real             rhs,                /**< rhs of the inequality */
7476 	   SCIP_Bool             activeone,          /**< is the constraint active when the binary is 1? */
7477 	   SCIP_Bool             lessthanineq,       /**< is the linear constraint a less than RHS (TRUE) or greater than RHS (FALSE)? */
7478 	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP? Usually set to TRUE. */
7479 	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
7480 	                                              *   Usually set to TRUE. */
7481 	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
7482 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7483 	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
7484 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7485 	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
7486 	                                              *   Usually set to TRUE. */
7487 	   SCIP_Bool             local,              /**< is constraint only valid locally?
7488 	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
7489 	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
7490 	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
7491 	                                              *   are separated as constraints. */
7492 	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
7493 	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
7494 	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
7495 	                                              *   if it may be moved to a more global node?
7496 	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
7497 	   )
7498 	{
7499 	   SCIP_CONSHDLR* conshdlr;
7500 	   SCIP_CONSHDLRDATA* conshdlrdata;
7501 	   SCIP_CONSDATA* consdata;
7502 	   SCIP_CONS* lincons;
7503 	   SCIP_VAR* slackvar;
7504 	   SCIP_Bool modifiable = FALSE;
7505 	   SCIP_Bool linconsactive;
7506 	   SCIP_VARTYPE slackvartype;
7507 	   SCIP_Real absvalsum = 0.0;
7508 	   char s[SCIP_MAXSTRLEN];
7509 	   SCIP_Real* valscopy;
7510 	   int j;
7511 	
7512 	   if ( nvars < 0 )
7513 	   {
7514 	      SCIPerrorMessage("Indicator constraint <%s> needs nonnegative number of variables in linear constraint.\n", name);
7515 	      return SCIP_INVALIDDATA;
7516 	   }
7517 	
7518 	   /* find the indicator constraint handler */
7519 	   conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
7520 	   if ( conshdlr == NULL )
7521 	   {
7522 	      SCIPerrorMessage("<%s> constraint handler not found\n", CONSHDLR_NAME);
7523 	      return SCIP_PLUGINNOTFOUND;
7524 	   }
7525 	
7526 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
7527 	   assert( conshdlrdata != NULL );
7528 	
7529 	   if ( conshdlrdata->nolinconscont && ! conshdlrdata->sepaalternativelp )
7530 	   {
7531 	      SCIPerrorMessage("constraint handler <%s>: need parameter <sepaalternativelp> to be true if parameter <nolinconscont> is true.\n", CONSHDLR_NAME);
7532 	      return SCIP_INVALIDDATA;
7533 	   }
7534 	
7535 	   if ( conshdlrdata->nolinconscont && conshdlrdata->generatebilinear )
7536 	   {
7537 	      SCIPerrorMessage("constraint handler <%s>: parameters <nolinconscont> and <generatebilinear> cannot both be true.\n", CONSHDLR_NAME);
7538 	      return SCIP_INVALIDDATA;
7539 	   }
7540 	
7541 	   valscopy = NULL;
7542 	   if ( lessthanineq )
7543 	      valscopy = vals;
7544 	   else
7545 	   {
7546 	      /* flip coefficients and RHS of indicator */
7547 	      SCIP_CALL( SCIPallocBufferArray(scip, &valscopy, nvars) );
7548 	      for (j = 0; j < nvars; ++j)
7549 	         valscopy[j] = -vals[j];
7550 	      rhs = -rhs;
7551 	   }
7552 	   assert( nvars == 0 || valscopy != NULL );
7553 	
7554 	   /* check if slack variable can be made implicit integer */
7555 	   slackvartype = SCIP_VARTYPE_IMPLINT;
7556 	   for (j = 0; j < nvars; ++j)
7557 	   {
7558 	      if ( conshdlrdata->scaleslackvar )
7559 	         absvalsum += REALABS(valscopy[j]);
7560 	      if ( ! SCIPvarIsIntegral(vars[j]) || ! SCIPisIntegral(scip, valscopy[j]) )
7561 	      {
7562 	         slackvartype = SCIP_VARTYPE_CONTINUOUS;
7563 	         if ( ! conshdlrdata->scaleslackvar )
7564 	            break;
7565 	      }
7566 	   }
7567 	
7568 	   /* create slack variable */
7569 	   (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "indslack_%s", name);
7570 	   SCIP_CALL( SCIPcreateVar(scip, &slackvar, s, 0.0, SCIPinfinity(scip), 0.0, slackvartype, TRUE, FALSE,
7571 	         NULL, NULL, NULL, NULL, NULL) );
7572 	
7573 	   SCIP_CALL( SCIPaddVar(scip, slackvar) );
7574 	
7575 	   /* mark slack variable not to be multi-aggregated */
7576 	   SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, slackvar) );
7577 	
7578 	   /* if the problem should be decomposed if only non-integer variables are present */
7579 	   linconsactive = TRUE;
7580 	   if ( conshdlrdata->nolinconscont )
7581 	   {
7582 	      SCIP_Bool onlyCont = TRUE;
7583 	
7584 	      assert( ! conshdlrdata->generatebilinear );
7585 	
7586 	      /* check whether call variables are non-integer */
7587 	      for (j = 0; j < nvars; ++j)
7588 	      {
7589 	         SCIP_VARTYPE vartype;
7590 	
7591 	         vartype = SCIPvarGetType(vars[j]);
7592 	         if ( vartype != SCIP_VARTYPE_CONTINUOUS && vartype != SCIP_VARTYPE_IMPLINT )
7593 	         {
7594 	            onlyCont = FALSE;
7595 	            break;
7596 	         }
7597 	      }
7598 	
7599 	      if ( onlyCont )
7600 	         linconsactive = FALSE;
7601 	   }
7602 	
7603 	   /* create linear constraint */
7604 	   (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "indlin_%s", name);
7605 	
7606 	   /* if the linear constraint should be activated (lincons is captured) */
7607 	   if ( linconsactive )
7608 	   {
7609 	      /* the constraint is initial if initial is true, enforced, separated, and checked */
7610 	      SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, s, nvars, vars, valscopy, -SCIPinfinity(scip), rhs,
7611 	            initial, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
7612 	   }
7613 	   else
7614 	   {
7615 	      /* create non-active linear constraint, which is neither initial, nor enforced, nor separated, nor checked */
7616 	      SCIP_CALL( SCIPcreateConsLinear(scip, &lincons, s, nvars, vars, valscopy, -SCIPinfinity(scip), rhs,
7617 	            FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
7618 	   }
7619 	
7620 	   if ( ! lessthanineq )
7621 	      SCIPfreeBufferArray(scip, &valscopy);
7622 	
7623 	   /* mark linear constraint not to be upgraded - otherwise we loose control over it */
7624 	   SCIPconsAddUpgradeLocks(lincons, 1);
7625 	   assert( SCIPconsGetNUpgradeLocks(lincons) > 0 );
7626 	
7627 	   /* add slack variable */
7628 	   if ( conshdlrdata->scaleslackvar && nvars > 0 )
7629 	   {
7630 	      absvalsum = absvalsum/((SCIP_Real) nvars);
7631 	      if ( slackvartype == SCIP_VARTYPE_IMPLINT )
7632 	         absvalsum = SCIPceil(scip, absvalsum);
7633 	      if ( SCIPisZero(scip, absvalsum) )
7634 	         absvalsum = 1.0;
7635 	      SCIP_CALL( SCIPaddCoefLinear(scip, lincons, slackvar, -absvalsum) );
7636 	   }
7637 	   else
7638 	   {
7639 	      SCIP_CALL( SCIPaddCoefLinear(scip, lincons, slackvar, -1.0) );
7640 	   }
7641 	   SCIP_CALL( SCIPaddCons(scip, lincons) );
7642 	
7643 	   /* check whether we should generate a bilinear constraint instead of an indicator constraint */
7644 	   if ( conshdlrdata->generatebilinear )
7645 	   {
7646 	      SCIP_Real val = 1.0;
7647 	      SCIP_VAR* binvarinternal;
7648 	
7649 	      /* if active on 0, the binary variable is reversed */
7650 	      if ( activeone )
7651 	         binvarinternal = binvar;
7652 	      else
7653 	      {
7654 	         SCIP_CALL ( SCIPgetNegatedVar(scip, binvar, &binvarinternal) );
7655 	      }
7656 	
7657 	      /* create a quadratic constraint with a single bilinear term - note that cons is used */
7658 	      SCIP_CALL( SCIPcreateConsQuadraticNonlinear(scip, cons, name, 0, NULL, NULL, 1, &binvarinternal, &slackvar, &val, 0.0, 0.0,
7659 	            TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7660 	   }
7661 	   else
7662 	   {
7663 	      /* create constraint data */
7664 	      consdata = NULL;
7665 	      SCIP_CALL( consdataCreate(scip, conshdlr, conshdlrdata, name, &consdata, conshdlrdata->eventhdlrbound, conshdlrdata->eventhdlrrestart,
7666 	            binvar, activeone, lessthanineq, slackvar, lincons, linconsactive) );
7667 	      assert( consdata != NULL );
7668 	      /* do not need to capture slack variable and linear constraint here */
7669 	
7670 	      /* create constraint */
7671 	      SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
7672 	            local, modifiable, dynamic, removable, stickingatnode) );
7673 	
7674 	      if ( SCIPisTransformed(scip) )
7675 	      {
7676 	         /* make sure that binary variable hash exists */
7677 	         if ( conshdlrdata->sepaalternativelp )
7678 	         {
7679 	            SCIP_VAR* binvarinternal;
7680 	
7681 	            if ( conshdlrdata->binvarhash == NULL )
7682 	            {
7683 	               SCIP_CALL( SCIPhashmapCreate(&conshdlrdata->binvarhash, SCIPblkmem(scip), SCIPgetNOrigVars(scip)) );
7684 	            }
7685 	
7686 	            /* if active on 0, the binary variable is reversed */
7687 	            if ( activeone )
7688 	               binvarinternal = binvar;
7689 	            else
7690 	            {
7691 	               SCIP_CALL ( SCIPgetNegatedVar(scip, binvar, &binvarinternal) );
7692 	            }
7693 	
7694 	            /* check whether binary variable is present: note that a binary variable might appear several times, but this seldomly happens. */
7695 	            assert( conshdlrdata->binvarhash != NULL );
7696 	            if ( ! SCIPhashmapExists(conshdlrdata->binvarhash, (void*) binvarinternal) )
7697 	            {
7698 	               SCIP_CALL( SCIPhashmapInsert(conshdlrdata->binvarhash, (void*) binvarinternal, (void*) (*cons)) );
7699 	            }
7700 	         }
7701 	      }
7702 	   }
7703 	
7704 	   return SCIP_OKAY;
7705 	}
7706 	
7707 	/** creates and captures an indicator constraint in its most basic version, i. e., all constraint flags are set to their
7708 	 *  basic value as explained for the method SCIPcreateConsIndicator(); all flags can be set via
7709 	 *  SCIPsetConsFLAGNAME-methods in scip.h
7710 	 *
7711 	 *  @see SCIPcreateConsIndicator() for information about the basic constraint flag configuration
7712 	 *
7713 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
7714 	 */
7715 	SCIP_RETCODE SCIPcreateConsBasicIndicator(
7716 	   SCIP*                 scip,               /**< SCIP data structure */
7717 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint (indicator or quadratic) */
7718 	   const char*           name,               /**< name of constraint */
7719 	   SCIP_VAR*             binvar,             /**< binary indicator variable (or NULL) */
7720 	   int                   nvars,              /**< number of variables in the inequality */
7721 	   SCIP_VAR**            vars,               /**< array with variables of inequality (or NULL) */
7722 	   SCIP_Real*            vals,               /**< values of variables in inequality (or NULL) */
7723 	   SCIP_Real             rhs                 /**< rhs of the inequality */
7724 	   )
7725 	{
7726 	   assert( scip != NULL );
7727 	
7728 	   SCIP_CALL( SCIPcreateConsIndicator(scip, cons, name, binvar, nvars, vars, vals, rhs,
7729 	         TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7730 	
7731 	   return SCIP_OKAY;
7732 	}
7733 	
7734 	/** creates and captures an indicator constraint with given linear constraint and slack variable
7735 	 *  in a generic version, i. e., with a flag activeone indicating whether the constraint is active on
7736 	 *  value 1 or 0 of the binary variable.
7737 	
7738 	 *  @note @a binvar is checked to be binary only later. This enables a change of the type in
7739 	 *  procedures reading an instance.
7740 	 *
7741 	 *  @note we assume that @a slackvar actually appears in @a lincons and we also assume that it takes
7742 	 *  the role of a slack variable!
7743 	 *
7744 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
7745 	 *
7746 	 *  @see SCIPcreateConsIndicatorLinCons() for information about the basic constraint flag configuration
7747 	 */
7748 	SCIP_RETCODE SCIPcreateConsIndicatorGenericLinCons(
7749 	   SCIP*                 scip,               /**< SCIP data structure */
7750 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
7751 	   const char*           name,               /**< name of constraint */
7752 	   SCIP_VAR*             binvar,             /**< binary indicator variable (or NULL) */
7753 	   SCIP_CONS*            lincons,            /**< linear constraint */
7754 	   SCIP_VAR*             slackvar,           /**< slack variable */
7755 	   SCIP_Bool             activeone,          /**< is the constraint active when the binary is 1? */
7756 	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP? Usually set to TRUE. */
7757 	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
7758 	                                              *   Usually set to TRUE. */
7759 	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
7760 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7761 	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
7762 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7763 	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
7764 	                                              *   Usually set to TRUE. */
7765 	   SCIP_Bool             local,              /**< is constraint only valid locally?
7766 	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
7767 	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
7768 	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
7769 	                                              *   are separated as constraints. */
7770 	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
7771 	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
7772 	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
7773 	                                              *   if it may be moved to a more global node?
7774 	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
7775 	   )
7776 	{
7777 	   SCIP_CONSHDLR* conshdlr;
7778 	   SCIP_CONSHDLRDATA* conshdlrdata;
7779 	   SCIP_CONSDATA* consdata = NULL;
7780 	   SCIP_Bool modifiable = FALSE;
7781 	   SCIP_Bool linconsactive = TRUE;
7782 	
7783 	   assert( scip != NULL );
7784 	   assert( lincons != NULL );
7785 	   assert( slackvar != NULL );
7786 	
7787 	   /* check whether lincons is really a linear constraint */
7788 	   conshdlr = SCIPconsGetHdlr(lincons);
7789 	   if ( strcmp(SCIPconshdlrGetName(conshdlr), "linear") != 0 )
7790 	   {
7791 	      SCIPerrorMessage("Lincons constraint is not linear.\n");
7792 	      return SCIP_INVALIDDATA;
7793 	   }
7794 	
7795 	   /* find the indicator constraint handler */
7796 	   conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
7797 	   if ( conshdlr == NULL )
7798 	   {
7799 	      SCIPerrorMessage("<%s> constraint handler not found.\n", CONSHDLR_NAME);
7800 	      return SCIP_PLUGINNOTFOUND;
7801 	   }
7802 	
7803 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
7804 	   assert( conshdlrdata != NULL );
7805 	
7806 	   if ( conshdlrdata->nolinconscont && ! conshdlrdata->sepaalternativelp )
7807 	   {
7808 	      SCIPerrorMessage("constraint handler <%s>: need parameter <sepaalternativelp> to be true if parameter <nolinconscont> is true.\n", CONSHDLR_NAME);
7809 	      return SCIP_INVALIDDATA;
7810 	   }
7811 	
7812 	   /* mark slack variable not to be multi-aggregated */
7813 	   SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, slackvar) );
7814 	
7815 	   /* if the problem should be decomposed (only if all variables are continuous) */
7816 	   if ( conshdlrdata->nolinconscont )
7817 	   {
7818 	      SCIP_Bool onlyCont = TRUE;
7819 	      int v;
7820 	      int nvars;
7821 	      SCIP_VAR** vars;
7822 	
7823 	      nvars = SCIPgetNVarsLinear(scip, lincons);
7824 	      vars = SCIPgetVarsLinear(scip, lincons);
7825 	
7826 	      /* check whether call variables are non-integer */
7827 	      for (v = 0; v < nvars; ++v)
7828 	      {
7829 	         SCIP_VARTYPE vartype;
7830 	
7831 	         vartype = SCIPvarGetType(vars[v]);
7832 	         if ( vartype != SCIP_VARTYPE_CONTINUOUS && vartype != SCIP_VARTYPE_IMPLINT )
7833 	         {
7834 	            onlyCont = FALSE;
7835 	            break;
7836 	         }
7837 	      }
7838 	
7839 	      if ( onlyCont )
7840 	         linconsactive = FALSE;
7841 	   }
7842 	
7843 	   /* mark linear constraint not to be upgraded - otherwise we loose control over it */
7844 	   SCIPconsAddUpgradeLocks(lincons, 1);
7845 	   assert( SCIPconsGetNUpgradeLocks(lincons) > 0 );
7846 	
7847 	   /* check whether we should generate a bilinear constraint instead of an indicator constraint */
7848 	   if ( conshdlrdata->generatebilinear )
7849 	   {
7850 	      SCIP_Real val = 1.0;
7851 	
7852 	      /* if active on 0, the binary variable is reversed */
7853 	      SCIP_VAR* binvarinternal;
7854 	      if ( activeone )
7855 	      {
7856 	         binvarinternal = binvar;
7857 	      }
7858 	      else
7859 	      {
7860 	         SCIP_CALL ( SCIPgetNegatedVar(scip, binvar, &binvarinternal) );
7861 	      }
7862 	
7863 	      /* create a quadratic constraint with a single bilinear term - note that cons is used */
7864 	      SCIP_CALL( SCIPcreateConsQuadraticNonlinear(scip, cons, name, 0, NULL, NULL, 1, &binvarinternal, &slackvar, &val, 0.0, 0.0,
7865 	            TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7866 	   }
7867 	   else
7868 	   {
7869 	      /* create constraint data */
7870 	      SCIP_CALL( consdataCreate(scip, conshdlr, conshdlrdata, name, &consdata, conshdlrdata->eventhdlrbound, conshdlrdata->eventhdlrrestart,
7871 	            binvar, activeone, TRUE, slackvar, lincons, linconsactive) );
7872 	      assert( consdata != NULL );
7873 	
7874 	      /* create constraint */
7875 	      SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
7876 	            local, modifiable, dynamic, removable, stickingatnode) );
7877 	   }
7878 	
7879 	   /* capture slack variable and linear constraint */
7880 	   SCIP_CALL( SCIPcaptureVar(scip, slackvar) );
7881 	   SCIP_CALL( SCIPcaptureCons(scip, lincons) );
7882 	
7883 	   return SCIP_OKAY;
7884 	}
7885 	
7886 	/** creates and captures an indicator constraint with given linear constraint and slack variable
7887 	 *
7888 	 *  @note @a binvar is checked to be binary only later. This enables a change of the type in
7889 	 *  procedures reading an instance.
7890 	 *
7891 	 *  @note we assume that @a slackvar actually appears in @a lincons and we also assume that it takes
7892 	 *  the role of a slack variable!
7893 	 *
7894 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
7895 	 */
7896 	SCIP_RETCODE SCIPcreateConsIndicatorLinCons(
7897 	   SCIP*                 scip,               /**< SCIP data structure */
7898 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
7899 	   const char*           name,               /**< name of constraint */
7900 	   SCIP_VAR*             binvar,             /**< binary indicator variable (or NULL) */
7901 	   SCIP_CONS*            lincons,            /**< linear constraint */
7902 	   SCIP_VAR*             slackvar,           /**< slack variable */
7903 	   SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP? Usually set to TRUE. */
7904 	   SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
7905 	                                              *   Usually set to TRUE. */
7906 	   SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
7907 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7908 	   SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
7909 	                                              *   TRUE for model constraints, FALSE for additional, redundant constraints. */
7910 	   SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
7911 	                                              *   Usually set to TRUE. */
7912 	   SCIP_Bool             local,              /**< is constraint only valid locally?
7913 	                                              *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
7914 	   SCIP_Bool             dynamic,            /**< is constraint subject to aging?
7915 	                                              *   Usually set to FALSE. Set to TRUE for own cuts which
7916 	                                              *   are separated as constraints. */
7917 	   SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
7918 	                                              *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
7919 	   SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
7920 	                                              *   if it may be moved to a more global node?
7921 	                                              *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
7922 	   )
7923 	{
7924 	   return SCIPcreateConsIndicatorGenericLinCons(scip, cons, name, binvar, lincons, slackvar, TRUE, initial, separate,
7925 	                                         enforce, check, propagate, local, dynamic, removable, stickingatnode);
7926 	}
7927 	
7928 	
7929 	/** creates and captures an indicator constraint with given linear constraint and slack variable
7930 	 *  in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
7931 	 *  method SCIPcreateConsIndicator(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
7932 	 *
7933 	 *  @note @a binvar is checked to be binary only later. This enables a change of the type in
7934 	 *  procedures reading an instance.
7935 	 *
7936 	 *  @note we assume that @a slackvar actually appears in @a lincons and we also assume that it takes
7937 	 *  the role of a slack variable!
7938 	 *
7939 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
7940 	 *
7941 	 *  @see SCIPcreateConsIndicatorLinCons() for information about the basic constraint flag configuration
7942 	 *
7943 	 *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
7944 	 */
7945 	SCIP_RETCODE SCIPcreateConsBasicIndicatorLinCons(
7946 	   SCIP*                 scip,               /**< SCIP data structure */
7947 	   SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
7948 	   const char*           name,               /**< name of constraint */
7949 	   SCIP_VAR*             binvar,             /**< binary indicator variable (or NULL) */
7950 	   SCIP_CONS*            lincons,            /**< linear constraint */
7951 	   SCIP_VAR*             slackvar            /**< slack variable */
7952 	   )
7953 	{
7954 	   assert( scip != NULL );
7955 	
7956 	   SCIP_CALL( SCIPcreateConsIndicatorLinCons(scip, cons, name, binvar, lincons, slackvar,
7957 	         TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
7958 	
7959 	   return SCIP_OKAY;
7960 	}
7961 	
7962 	
7963 	/** adds variable to the inequality of the indicator constraint */
7964 	SCIP_RETCODE SCIPaddVarIndicator(
7965 	   SCIP*                 scip,               /**< SCIP data structure */
7966 	   SCIP_CONS*            cons,               /**< indicator constraint */
7967 	   SCIP_VAR*             var,                /**< variable to add to the inequality */
7968 	   SCIP_Real             val                 /**< value of variable */
7969 	   )
7970 	{
7971 	   SCIP_CONSDATA* consdata;
7972 	
7973 	   assert( cons != NULL );
7974 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0 );
7975 	
7976 	   consdata = SCIPconsGetData(cons);
7977 	   assert( consdata != NULL );
7978 	
7979 	   /* if linear inequality is flipped, variable is added with negative coefficient */
7980 	   if ( !consdata->lessthanineq )
7981 	      val = -val;
7982 	
7983 	   SCIP_CALL( SCIPaddCoefLinear(scip, consdata->lincons, var, val) );
7984 	
7985 	   /* possibly adapt variable type */
7986 	   if ( SCIPvarGetType(consdata->slackvar) != SCIP_VARTYPE_CONTINUOUS && (! SCIPvarIsIntegral(var) || ! SCIPisIntegral(scip, val) ) )
7987 	   {
7988 	      SCIP_Bool infeasible;
7989 	
7990 	      SCIP_CALL( SCIPchgVarType(scip, consdata->slackvar, SCIP_VARTYPE_CONTINUOUS, &infeasible) );
7991 	      assert( ! infeasible );
7992 	   }
7993 	
7994 	   return SCIP_OKAY;
7995 	}
7996 	
7997 	
7998 	/** gets the linear constraint corresponding to the indicator constraint (may be NULL) */
7999 	SCIP_CONS* SCIPgetLinearConsIndicator(
8000 	   SCIP_CONS*            cons                /**< indicator constraint */
8001 	   )
8002 	{
8003 	   SCIP_CONSDATA* consdata;
8004 	
8005 	   assert( cons != NULL );
8006 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0 );
8007 	
8008 	   consdata = SCIPconsGetData(cons);
8009 	   assert( consdata != NULL );
8010 	
8011 	   return consdata->lincons;
8012 	}
8013 	
8014 	
8015 	/** sets the linear constraint corresponding to the indicator constraint (may be NULL) */
8016 	SCIP_RETCODE SCIPsetLinearConsIndicator(
8017 	   SCIP*                 scip,               /**< SCIP data structure */
8018 	   SCIP_CONS*            cons,               /**< indicator constraint */
8019 	   SCIP_CONS*            lincons             /**< linear constraint */
8020 	   )
8021 	{
8022 	   SCIP_CONSHDLR* conshdlr;
8023 	   SCIP_CONSHDLRDATA* conshdlrdata;
8024 	   SCIP_CONSDATA* consdata;
8025 	
8026 	   if ( SCIPgetStage(scip) != SCIP_STAGE_PROBLEM )
8027 	   {
8028 	      SCIPerrorMessage("Cannot set linear constraint in SCIP stage <%d>\n", SCIPgetStage(scip) );
8029 	      return SCIP_INVALIDCALL;
8030 	   }
8031 	
8032 	   assert( cons != NULL );
8033 	   conshdlr = SCIPconsGetHdlr(cons);
8034 	
8035 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
8036 	   conshdlrdata = SCIPconshdlrGetData(conshdlr);
8037 	   assert( conshdlrdata != NULL );
8038 	
8039 	   consdata = SCIPconsGetData(cons);
8040 	   assert( consdata != NULL );
8041 	
8042 	   /* free old linear constraint */
8043 	   assert( consdata->lincons != NULL );
8044 	   SCIP_CALL( SCIPdelCons(scip, consdata->lincons) );
8045 	   SCIP_CALL( SCIPreleaseCons(scip, &(consdata->lincons) ) );
8046 	
8047 	   assert( lincons != NULL );
8048 	   consdata->lincons = lincons;
8049 	   consdata->linconsactive = TRUE;
8050 	   SCIP_CALL( SCIPcaptureCons(scip, lincons) );
8051 	
8052 	   /* if the problem should be decomposed if only non-integer variables are present */
8053 	   if ( conshdlrdata->nolinconscont )
8054 	   {
8055 	      SCIP_Bool onlyCont;
8056 	      int v;
8057 	      int nvars;
8058 	      SCIP_VAR** vars;
8059 	
8060 	      onlyCont = TRUE;
8061 	      nvars = SCIPgetNVarsLinear(scip, lincons);
8062 	      vars = SCIPgetVarsLinear(scip, lincons);
8063 	      assert( vars != NULL );
8064 	
8065 	      /* check whether call variables are non-integer */
8066 	      for (v = 0; v < nvars; ++v)
8067 	      {
8068 	         SCIP_VARTYPE vartype;
8069 	
8070 	         vartype = SCIPvarGetType(vars[v]);
8071 	         if ( vartype != SCIP_VARTYPE_CONTINUOUS && vartype != SCIP_VARTYPE_IMPLINT )
8072 	         {
8073 	            onlyCont = FALSE;
8074 	            break;
8075 	         }
8076 	      }
8077 	
8078 	      if ( onlyCont )
8079 	         consdata->linconsactive = FALSE;
8080 	   }
8081 	
8082 	   return SCIP_OKAY;
8083 	}
8084 	
8085 	/** gets activation value of an indicator constraint, TRUE for active on 1, FALSE for active on 0 */
8086 	SCIP_Bool SCIPgetActiveOnIndicator(
8087 	   SCIP_CONS*            cons                /**< indicator constraint */
8088 	   )
8089 	{
8090 	   SCIP_CONSDATA* consdata;
8091 	
8092 	   assert( cons != NULL );
8093 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0 );
8094 	
8095 	   consdata = SCIPconsGetData(cons);
8096 	   assert( consdata != NULL );
8097 	
8098 	   return consdata->activeone;
8099 	}
8100 	
8101 	
8102 	/** gets binary variable corresponding to indicator constraint */
8103 	SCIP_VAR* SCIPgetBinaryVarIndicator(
8104 	   SCIP_CONS*            cons                /**< indicator constraint */
8105 	   )
8106 	{
8107 	   SCIP_CONSDATA* consdata;
8108 	
8109 	   assert( cons != NULL );
8110 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0 );
8111 	
8112 	   consdata = SCIPconsGetData(cons);
8113 	   assert( consdata != NULL );
8114 	
8115 	   return consdata->binvar;
8116 	}
8117 	
8118 	/** similar to SCIPgetBinaryVarIndicator but returns the original binary variable passed by the user. */
8119 	SCIP_VAR* SCIPgetBinaryVarIndicatorGeneric(
8120 	   SCIP_CONS*            cons                /**< indicator constraint */
8121 	   )
8122 	{
8123 	   SCIP_CONSDATA* consdata;
8124 	   SCIP_VAR* binvar;
8125 	
8126 	   assert(cons != NULL);
8127 	   assert(strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0);
8128 	
8129 	   consdata = SCIPconsGetData(cons);
8130 	   assert(consdata != NULL);
8131 	   binvar = consdata->binvar;
8132 	
8133 	   if ( ! consdata->activeone )
8134 	      binvar = SCIPvarGetNegationVar(binvar);
8135 	   assert(binvar != NULL);
8136 	
8137 	   return binvar;
8138 	}
8139 	
8140 	/** sets binary indicator variable for indicator constraint */
8141 	SCIP_RETCODE SCIPsetBinaryVarIndicator(
8142 	   SCIP*                 scip,               /**< SCIP data structure */
8143 	   SCIP_CONS*            cons,               /**< indicator constraint */
8144 	   SCIP_VAR*             binvar              /**< binary variable to add to the inequality */
8145 	   )
8146 	{
8147 	   SCIP_CONSDATA* consdata;
8148 	
8149 	   assert( cons != NULL );
8150 	   assert( binvar != NULL );
8151 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0 );
8152 	
8153 	   consdata = SCIPconsGetData(cons);
8154 	   assert( consdata != NULL );
8155 	
8156 	   /* check type */
8157 	   if ( SCIPvarGetType(binvar) != SCIP_VARTYPE_BINARY )
8158 	   {
8159 	      SCIPerrorMessage("Indicator variable <%s> is not binary %d.\n", SCIPvarGetName(binvar), SCIPvarGetType(binvar));
8160 	      return SCIP_ERROR;
8161 	   }
8162 	
8163 	   /* check previous binary variable */
8164 	   if ( consdata->binvar != NULL )
8165 	   {
8166 	      /* to allow replacement of binary variables, we would need to drop events etc. */
8167 	      SCIPerrorMessage("Cannot replace binary variable <%s> for indicator constraint <%s>.\n", SCIPvarGetName(binvar), SCIPconsGetName(cons));
8168 	      return SCIP_INVALIDCALL;
8169 	   }
8170 	
8171 	   /* if we are transformed, obtain transformed variables and catch events */
8172 	   if ( SCIPconsIsTransformed(cons) )
8173 	   {
8174 	      SCIP_VAR* var;
8175 	      SCIP_CONSHDLR* conshdlr;
8176 	      SCIP_CONSHDLRDATA* conshdlrdata;
8177 	
8178 	      /* make sure we have a transformed binary variable */
(2) Event copy_paste_error: "var" in "&var" looks like a copy-paste error.
(3) Event remediation: Should it say "binvar" instead?
Also see events: [original]
8179 	      SCIP_CALL( SCIPgetTransformedVar(scip, binvar, &var) );
8180 	      assert( var != NULL );
8181 	      if ( ! consdata->activeone )
(1) Event original: "&var" looks like the original copy.
Also see events: [copy_paste_error][remediation]
8182 	         SCIP_CALL( SCIPgetNegatedVar(scip, var, &var) );
8183 	
8184 	      consdata->binvar = var;
8185 	
8186 	      conshdlr = SCIPconsGetHdlr(cons);
8187 	      assert( conshdlr != NULL );
8188 	      assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
8189 	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
8190 	      assert( conshdlrdata != NULL );
8191 	      assert( conshdlrdata->eventhdlrbound != NULL );
8192 	      assert( conshdlrdata->eventhdlrrestart != NULL );
8193 	
8194 	      /* catch local bound change events on binary variable */
8195 	      if ( consdata->linconsactive )
8196 	      {
8197 	         SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, conshdlrdata->eventhdlrbound, (SCIP_EVENTDATA*) consdata, NULL) );
8198 	      }
8199 	
8200 	      /* catch global bound change events on binary variable */
8201 	      if ( conshdlrdata->forcerestart )
8202 	      {
8203 	         SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_GBDCHANGED, conshdlrdata->eventhdlrrestart, (SCIP_EVENTDATA*) conshdlrdata, NULL) );
8204 	      }
8205 	
8206 	      /* if binary variable is fixed to be nonzero */
8207 	      if ( SCIPvarGetLbLocal(var) > 0.5 )
8208 	         ++(consdata->nfixednonzero);
8209 	   }
8210 	   else
8211 	   {
8212 	      if ( ! consdata->activeone )
8213 	         SCIP_CALL( SCIPgetNegatedVar(scip, binvar, &binvar) );
8214 	      consdata->binvar = binvar;
8215 	   }
8216 	
8217 	   return SCIP_OKAY;
8218 	}
8219 	
8220 	/** gets slack variable corresponding to indicator constraint */
8221 	SCIP_VAR* SCIPgetSlackVarIndicator(
8222 	   SCIP_CONS*            cons                /**< indicator constraint */
8223 	   )
8224 	{
8225 	   SCIP_CONSDATA* consdata;
8226 	
8227 	   assert( cons != NULL );
8228 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0 );
8229 	
8230 	   consdata = SCIPconsGetData(cons);
8231 	   assert( consdata != NULL );
8232 	
8233 	   return consdata->slackvar;
8234 	}
8235 	
8236 	
8237 	/** sets upper bound for slack variable corresponding to indicator constraint
8238 	 *
8239 	 *  Use with care if you know that the maximal violation of the corresponding constraint is at most @p ub. This bound
8240 	 *  might be improved automatically during the solution process.
8241 	 *
8242 	 *  @pre This method should only be called if SCIP is in one of the following stages:
8243 	 *       - \ref SCIP_STAGE_INIT
8244 	 *       - \ref SCIP_STAGE_PROBLEM
8245 	 */
8246 	SCIP_RETCODE SCIPsetSlackVarUb(
8247 	   SCIP*                 scip,               /**< SCIP data structure */
8248 	   SCIP_CONS*            cons,               /**< indicator constraint */
8249 	   SCIP_Real             ub                  /**< upper bound for slack variable */
8250 	   )
8251 	{
8252 	   SCIP_CONSDATA* consdata;
8253 	
8254 	   assert( scip != NULL );
8255 	   assert( cons != NULL );
8256 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0 );
8257 	
8258 	   consdata = SCIPconsGetData(cons);
8259 	   assert( consdata != NULL );
8260 	
8261 	   if ( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM )
8262 	      return SCIP_OKAY;
8263 	
8264 	   assert( consdata->slackvar != NULL );
8265 	   SCIP_CALL( SCIPchgVarUb(scip, consdata->slackvar, ub) );
8266 	
8267 	   return SCIP_OKAY;
8268 	}
8269 	
8270 	
8271 	/** checks whether indicator constraint is violated w.r.t. sol */
8272 	SCIP_Bool SCIPisViolatedIndicator(
8273 	   SCIP*                 scip,               /**< SCIP data structure */
8274 	   SCIP_CONS*            cons,               /**< indicator constraint */
8275 	   SCIP_SOL*             sol                 /**< solution, or NULL to use current node's solution */
8276 	   )
8277 	{
8278 	   SCIP_CONSDATA* consdata;
8279 	
8280 	   assert( cons != NULL );
8281 	
8282 	   /* deleted constraints should always be satisfied */
8283 	   if ( SCIPconsIsDeleted(cons) )
8284 	      return FALSE;
8285 	
8286 	   consdata = SCIPconsGetData(cons);
8287 	   assert( consdata != NULL );
8288 	
8289 	   if ( consdata->linconsactive )
8290 	   {
8291 	      assert( consdata->slackvar != NULL );
8292 	      assert( consdata->binvar != NULL );
8293 	      return(
8294 	         SCIPisFeasPositive(scip, SCIPgetSolVal(scip, sol, consdata->slackvar)) &&
8295 	         SCIPisFeasPositive(scip, SCIPgetSolVal(scip, sol, consdata->binvar)) );
8296 	   }
8297 	
8298 	   /* @todo: check how this can be decided for linconsactive == FALSE */
8299 	   return TRUE;
8300 	}
8301 	
8302 	
8303 	/** based on values of other variables, computes slack and binary variable to turn constraint feasible
8304 	 *
8305 	 *  It will also clean up the solution, i.e., shift slack variable, as follows:
8306 	 *
8307 	 *  If the inequality is \f$a^T x + \gamma\, s \leq \beta\f$, the value of the slack variable
8308 	 *  \f$s\f$ to achieve equality is
8309 	 *  \f[
8310 	 *      s^* = \frac{\beta - a^T x^*}{\gamma},
8311 	 *  \f]
8312 	 *  where \f$x^*\f$ is the given solution. In case of \f$a^T x + \gamma\, s \geq \alpha\f$, we
8313 	 *  arrive at
8314 	 *  \f[
8315 	 *      s^* = \frac{\alpha - a^T x^*}{\gamma}.
8316 	 *  \f]
8317 	 *  The typical values of \f$\gamma\f$ in the first case is -1 and +1 in the second case.
8318 	 *
8319 	 *  Now, let \f$\sigma\f$ be the sign of \f$\gamma\f$ in the first case and \f$-\gamma\f$ in the
8320 	 *  second case. Thus, if \f$\sigma > 0\f$ and \f$s^* < 0\f$, the inequality cannot be satisfied by
8321 	 *  a nonnegative value for the slack variable; in this case, we have to leave the values as they
8322 	 *  are. If \f$\sigma < 0\f$ and \f$s^* > 0\f$, the solution violates the indicator constraint (we
8323 	 *  can set the slack variable to value \f$s^*\f$). If \f$\sigma < 0\f$ and \f$s^* \leq 0\f$ or
8324 	 *  \f$\sigma > 0\f$ and \f$s^* \geq 0\f$, the constraint is satisfied, and we can set the slack
8325 	 *  variable to 0.
8326 	 */
8327 	SCIP_RETCODE SCIPmakeIndicatorFeasible(
8328 	   SCIP*                 scip,               /**< SCIP data structure */
8329 	   SCIP_CONS*            cons,               /**< indicator constraint */
8330 	   SCIP_SOL*             sol,                /**< solution */
8331 	   SCIP_Bool*            changed             /**< pointer to store whether the solution has been changed */
8332 	   )
8333 	{
8334 	   SCIP_CONSDATA* consdata;
8335 	   SCIP_CONS* lincons;
8336 	   SCIP_VAR** linvars;
8337 	   SCIP_Real* linvals;
8338 	   SCIP_VAR* slackvar;
8339 	   SCIP_VAR* binvar;
8340 	   SCIP_Real slackcoef;
8341 	   SCIP_Real sum;
8342 	   SCIP_Real val;
8343 	   int nlinvars;
8344 	   int sigma;
8345 	   int v;
8346 	
8347 	   assert( cons != NULL );
8348 	   assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) == 0 );
8349 	   assert( sol != NULL );
8350 	   assert( changed != NULL );
8351 	
8352 	   *changed = FALSE;
8353 	
8354 	   /* avoid deleted indicator constraints, e.g., due to preprocessing */
8355 	   if ( ! SCIPconsIsActive(cons) && SCIPgetStage(scip) >= SCIP_STAGE_INITPRESOLVE )
8356 	      return SCIP_OKAY;
8357 	
8358 	   assert( cons != NULL );
8359 	   consdata = SCIPconsGetData(cons);
8360 	   assert( consdata != NULL );
8361 	
8362 	   /* if the linear constraint is not present, we cannot do anything */
8363 	   if ( ! consdata->linconsactive )
8364 	      return SCIP_OKAY;
8365 	
8366 	   lincons = consdata->lincons;
8367 	   assert( lincons != NULL );
8368 	
8369 	   /* avoid non-active linear constraints, e.g., due to preprocessing */
8370 	   if ( SCIPconsIsActive(lincons) || SCIPgetStage(scip) < SCIP_STAGE_INITPRESOLVE )
8371 	   {
8372 	      slackvar = consdata->slackvar;
8373 	      binvar = consdata->binvar;
8374 	      assert( slackvar != NULL );
8375 	      assert( binvar != NULL );
8376 	
8377 	      nlinvars = SCIPgetNVarsLinear(scip, lincons);
8378 	      linvars = SCIPgetVarsLinear(scip, lincons);
8379 	      linvals = SCIPgetValsLinear(scip, lincons);
8380 	
8381 	      /* compute value of regular variables */
8382 	      sum = 0.0;
8383 	      slackcoef = 0.0;
8384 	      for (v = 0; v < nlinvars; ++v)
8385 	      {
8386 	         SCIP_VAR* var;
8387 	         var = linvars[v];
8388 	         if ( var != slackvar )
8389 	            sum += linvals[v] * SCIPgetSolVal(scip, sol, var);
8390 	         else
8391 	            slackcoef = linvals[v];
8392 	      }
8393 	
8394 	      /* do nothing if slack variable does not appear */
8395 	      if ( SCIPisFeasZero(scip, slackcoef) )
8396 	         return SCIP_OKAY;
8397 	
8398 	      assert( ! SCIPisZero(scip, slackcoef) );
8399 	      assert( slackcoef != 0.0 );  /* to satisfy lint */
8400 	      assert( SCIPisInfinity(scip, -SCIPgetLhsLinear(scip, lincons)) || SCIPisInfinity(scip, SCIPgetRhsLinear(scip, lincons)) );
8401 	      assert( SCIPisFeasGE(scip, SCIPvarGetLbLocal(slackvar), 0.0) );
8402 	
8403 	      val = SCIPgetRhsLinear(scip, lincons);
8404 	      sigma = 1;
8405 	      if ( SCIPisInfinity(scip, val) )
8406 	      {
8407 	         val = SCIPgetLhsLinear(scip, lincons);
8408 	         assert( ! SCIPisInfinity(scip, REALABS(val)) );
8409 	         sigma = -1;
8410 	      }
8411 	      /* compute value of slack that would achieve equality */
8412 	      val = (val - sum)/slackcoef;
8413 	
8414 	      /* compute direction into which slack variable would be infeasible */
8415 	      if ( slackcoef < 0 )
8416 	         sigma *= -1;
8417 	
8418 	      /* filter out cases in which no sensible change is possible */
8419 	      if ( sigma > 0 && SCIPisFeasNegative(scip, val) )
8420 	         return SCIP_OKAY;
8421 	
8422 	      /* check if linear constraint w/o slack variable is violated */
8423 	      if ( sigma < 0 && SCIPisFeasPositive(scip, val) )
8424 	      {
8425 	         /* the original constraint is violated */
8426 	         if ( ! SCIPisFeasEQ(scip, SCIPgetSolVal(scip, sol, slackvar), val) )
8427 	         {
8428 	            SCIP_CALL( SCIPsetSolVal(scip, sol, slackvar, val) );
8429 	            *changed = TRUE;
8430 	         }
8431 	         /* check whether binary variable is fixed or its negated variable is fixed */
8432 	         if ( SCIPvarGetStatus(binvar) != SCIP_VARSTATUS_FIXED &&
8433 	            ( SCIPvarGetStatus(binvar) != SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(SCIPvarGetNegationVar(binvar)) != SCIP_VARSTATUS_FIXED ) )
8434 	         {
8435 	            if ( ! SCIPisFeasEQ(scip, SCIPgetSolVal(scip, sol, binvar), 0.0) )
8436 	            {
8437 	               SCIP_CALL( SCIPsetSolVal(scip, sol, binvar, 0.0) );
8438 	               *changed = TRUE;
8439 	            }
8440 	         }
8441 	      }
8442 	      else
8443 	      {
8444 	         assert( SCIPisFeasGE(scip, val * ((SCIP_Real) sigma), 0.0) );
8445 	
8446 	         /* the original constraint is satisfied - we can set the slack variable to 0 (slackvar
8447 	          * should only occur in this indicator constraint) */
8448 	         if ( ! SCIPisFeasEQ(scip, SCIPgetSolVal(scip, sol, slackvar), 0.0) && SCIPisFeasPositive(scip, SCIPvarGetLbLocal(slackvar)) )
8449 	         {
8450 	            SCIP_CALL( SCIPsetSolVal(scip, sol, slackvar, 0.0) );
8451 	            *changed = TRUE;
8452 	         }
8453 	
8454 	         /* check whether binary variable is fixed or its negated variable is fixed */
8455 	         if ( SCIPvarGetStatus(binvar) != SCIP_VARSTATUS_FIXED &&
8456 	            ( SCIPvarGetStatus(binvar) != SCIP_VARSTATUS_NEGATED || SCIPvarGetStatus(SCIPvarGetNegationVar(binvar)) != SCIP_VARSTATUS_FIXED ) )
8457 	         {
8458 	            SCIP_Real obj;
8459 	            obj = varGetObjDelta(binvar);
8460 	
8461 	            /* check objective for possibly setting binary variable */
8462 	            if ( obj <= 0 )
8463 	            {
8464 	               /* setting variable to 1 does not increase objective - check whether we can set it to 1 */
8465 	               if ( ! SCIPisFeasEQ(scip, SCIPgetSolVal(scip, sol, binvar), 1.0) )
8466 	               {
8467 	                  /* check whether variable only occurs in the current constraint */
8468 	                  if ( SCIPvarGetNLocksUpType(binvar, SCIP_LOCKTYPE_MODEL) <= 1 )
8469 	                  {
8470 	                     SCIP_CALL( SCIPsetSolVal(scip, sol, binvar, 1.0) );
8471 	                     *changed = TRUE;
8472 	                     /* make sure that the other case does not occur if obj = 0: prefer variables set to 1 */
8473 	                     obj = -1.0;
8474 	                  }
8475 	               }
8476 	               else
8477 	               {
8478 	                  /* make sure that the other case does not occur if obj = 0: prefer variables set to 1 */
8479 	                  obj = -1.0;
8480 	               }
8481 	            }
8482 	            if ( obj >= 0 )
8483 	            {
8484 	               /* setting variable to 0 does not increase objective -> check whether variable only occurs in the current constraint
8485 	                * note: binary variables are only locked up */
8486 	               if ( SCIPvarGetNLocksDownType(binvar, SCIP_LOCKTYPE_MODEL) <= 0
8487 	                  && ! SCIPisFeasEQ(scip, SCIPgetSolVal(scip, sol, binvar), 0.0) )
8488 	               {
8489 	                  SCIP_CALL( SCIPsetSolVal(scip, sol, binvar, 0.0) );
8490 	                  *changed = TRUE;
8491 	               }
8492 	            }
8493 	         }
8494 	      }
8495 	   }
8496 	
8497 	   return SCIP_OKAY;
8498 	}
8499 	
8500 	
8501 	/** based on values of other variables, computes slack and binary variable to turn all constraints feasible */
8502 	SCIP_RETCODE SCIPmakeIndicatorsFeasible(
8503 	   SCIP*                 scip,               /**< SCIP data structure */
8504 	   SCIP_CONSHDLR*        conshdlr,           /**< indicator constraint handler */
8505 	   SCIP_SOL*             sol,                /**< solution */
8506 	   SCIP_Bool*            changed             /**< pointer to store whether the solution has been changed */
8507 	   )
8508 	{
8509 	   SCIP_CONS** conss;
8510 	   int nconss;
8511 	   int c;
8512 	
8513 	   assert( conshdlr != NULL );
8514 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
8515 	   assert( sol != NULL );
8516 	   assert( changed != NULL );
8517 	
8518 	   *changed = FALSE;
8519 	
8520 	   /* only run after or in presolving */
8521 	   if ( SCIPgetStage(scip) < SCIP_STAGE_INITPRESOLVE )
8522 	      return SCIP_OKAY;
8523 	
8524 	   conss = SCIPconshdlrGetConss(conshdlr);
8525 	   nconss = SCIPconshdlrGetNConss(conshdlr);
8526 	
8527 	   for (c = 0; c < nconss; ++c)
8528 	   {
8529 	      SCIP_CONSDATA* consdata;
8530 	      SCIP_Bool chg = FALSE;
8531 	      assert( conss[c] != NULL );
8532 	
8533 	      consdata = SCIPconsGetData(conss[c]);
8534 	      assert( consdata != NULL );
8535 	
8536 	      /* if the linear constraint is not present, we stop */
8537 	      if ( ! consdata->linconsactive )
8538 	         break;
8539 	
8540 	      SCIP_CALL( SCIPmakeIndicatorFeasible(scip, conss[c], sol, &chg) );
8541 	      *changed = *changed || chg;
8542 	   }
8543 	
8544 	   return SCIP_OKAY;
8545 	}
8546 	
8547 	
8548 	/** adds additional linear constraint that is not connected with an indicator constraint, but can be used for separation */
8549 	SCIP_RETCODE SCIPaddLinearConsIndicator(
8550 	   SCIP*                 scip,               /**< SCIP data structure */
8551 	   SCIP_CONSHDLR*        conshdlr,           /**< indicator constraint handler */
8552 	   SCIP_CONS*            lincons             /**< linear constraint */
8553 	   )
8554 	{
8555 	   assert( scip != NULL );
8556 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
8557 	   assert( lincons != NULL );
8558 	
8559 	   /* do not add locally valid constraints (this would require much more bookkeeping) */
8560 	   if ( ! SCIPconsIsLocal(lincons) && ! SCIPconsIsModifiable(lincons) )
8561 	   {
8562 	      SCIP_CONSHDLRDATA* conshdlrdata;
8563 	
8564 	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
8565 	      assert( conshdlrdata != NULL );
8566 	
8567 	      SCIP_CALL( consdataEnsureAddLinConsSize(scip, conshdlr, conshdlrdata->naddlincons+1) );
8568 	      assert( conshdlrdata->naddlincons+1 <= conshdlrdata->maxaddlincons );
8569 	
8570 	      conshdlrdata->addlincons[conshdlrdata->naddlincons++] = lincons;
8571 	   }
8572 	
8573 	   return SCIP_OKAY;
8574 	}
8575 	
8576 	
8577 	/** adds additional row that is not connected with an indicator constraint, but can be used for separation
8578 	 *
8579 	 *  @note The row is directly added to the alternative polyhedron and is not stored.
8580 	 */
8581 	SCIP_RETCODE SCIPaddRowIndicator(
8582 	   SCIP*                 scip,               /**< SCIP data structure */
8583 	   SCIP_CONSHDLR*        conshdlr,           /**< indicator constraint handler */
8584 	   SCIP_ROW*             row                 /**< row to add */
8585 	   )
8586 	{
8587 	   assert( scip != NULL );
8588 	   assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
8589 	   assert( row != NULL );
8590 	
8591 	   /* skip local cuts (local cuts would require to dynamically add and remove columns from the alternative polyhedron */
8592 	   if ( ! SCIProwIsLocal(row) )
8593 	   {
8594 	      int colindex;
8595 	      SCIP_CONSHDLRDATA* conshdlrdata;
8596 	
8597 	      conshdlrdata = SCIPconshdlrGetData(conshdlr);
8598 	      assert( conshdlrdata != NULL );
8599 	
8600 	      /* do not add rows if we do not separate */
8601 	      if ( ! conshdlrdata->sepaalternativelp )
8602 	         return SCIP_OKAY;
8603 	
8604 	      SCIPdebugMsg(scip, "Adding row <%s> to alternative LP.\n", SCIProwGetName(row));
8605 	
8606 	      /* add row directly to alternative polyhedron */
8607 	      SCIP_CALL( addAltLPRow(scip, conshdlr, row, 0.0, &colindex) );
8608 	   }
8609 	
8610 	   return SCIP_OKAY;
8611 	}
8612