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