1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /*                                                                           */
3 /*                  This file is part of the program and library             */
4 /*         SCIP --- Solving Constraint Integer Programs                      */
5 /*                                                                           */
6 /*    Copyright (C) 2002-2021 Konrad-Zuse-Zentrum                            */
7 /*                            fuer Informationstechnik Berlin                */
8 /*                                                                           */
9 /*  SCIP is distributed under the terms of the ZIB Academic License.         */
10 /*                                                                           */
11 /*  You should have received a copy of the ZIB Academic License              */
12 /*  along with SCIP; see the file COPYING. If not visit scipopt.org.         */
13 /*                                                                           */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file   cons_linear.c
17  * @ingroup DEFPLUGINS_CONS
18  * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
19  * @author Tobias Achterberg
20  * @author Timo Berthold
21  * @author Marc Pfetsch
22  * @author Kati Wolter
23  * @author Michael Winkler
24  * @author Gerald Gamrath
25  * @author Domenico Salvagnin
26  *
27  *  Linear constraints are separated with a high priority, because they are easy
28  *  to separate. Instead of using the global cut pool, the same effect can be
29  *  implemented by adding linear constraints to the root node, such that they are
30  *  separated each time, the linear constraints are separated. A constraint
31  *  handler, which generates linear constraints in this way should have a lower
32  *  separation priority than the linear constraint handler, and it should have a
33  *  separation frequency that is a multiple of the frequency of the linear
34  *  constraint handler. In this way, it can be avoided to separate the same cut
35  *  twice, because if a separation run of the handler is always preceded by a
36  *  separation of the linear constraints, the priorily added constraints are
37  *  always satisfied.
38  *
39  *  Linear constraints are enforced and checked with a very low priority. Checking
40  *  of (many) linear constraints is much more involved than checking the solution
41  *  values for integrality. Because we are separating the linear constraints quite
42  *  often, it is only necessary to enforce them for integral solutions. A constraint
43  *  handler which generates pool cuts in its enforcing method should have an
44  *  enforcing priority smaller than that of the linear constraint handler to avoid
45  *  regenerating constraints which already exist.
46  */
47 
48 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
49 
50 #include "blockmemshell/memory.h"
51 #include "scip/cons_knapsack.h"
52 #include "scip/cons_linear.h"
53 #include "scip/cons_nonlinear.h"
54 #include "scip/cons_quadratic.h"
55 #include "scip/debug.h"
56 #include "scip/pub_conflict.h"
57 #include "scip/pub_cons.h"
58 #include "scip/pub_event.h"
59 #include "scip/pub_lp.h"
60 #include "scip/pub_message.h"
61 #include "scip/pub_misc.h"
62 #include "scip/pub_misc_sort.h"
63 #include "scip/pub_var.h"
64 #include "scip/scip_branch.h"
65 #include "scip/scip_conflict.h"
66 #include "scip/scip_cons.h"
67 #include "scip/scip_copy.h"
68 #include "scip/scip_cut.h"
69 #include "scip/scip_event.h"
70 #include "scip/scip_general.h"
71 #include "scip/scip_lp.h"
72 #include "scip/scip_mem.h"
73 #include "scip/scip_message.h"
74 #include "scip/scip_numerics.h"
75 #include "scip/scip_param.h"
76 #include "scip/scip_prob.h"
77 #include "scip/scip_probing.h"
78 #include "scip/scip_sol.h"
79 #include "scip/scip_solvingstats.h"
80 #include "scip/scip_tree.h"
81 #include "scip/scip_var.h"
82 #include <ctype.h>
83 #include <string.h>
84 #if defined(_WIN32) || defined(_WIN64)
85 #else
86 #include <strings.h> /*lint --e{766}*/
87 #endif
88 
89 
90 #define CONSHDLR_NAME          "linear"
91 #define CONSHDLR_DESC          "linear constraints of the form  lhs <= a^T x <= rhs"
92 #define CONSHDLR_SEPAPRIORITY   +100000 /**< priority of the constraint handler for separation */
93 #define CONSHDLR_ENFOPRIORITY  -1000000 /**< priority of the constraint handler for constraint enforcing */
94 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
95 #define CONSHDLR_SEPAFREQ             0 /**< frequency for separating cuts; zero means to separate only in the root node */
96 #define CONSHDLR_PROPFREQ             1 /**< frequency for propagating domains; zero means only preprocessing propagation */
97 #define CONSHDLR_EAGERFREQ          100 /**< frequency for using all instead of only the useful constraints in separation,
98                                          *   propagation and enforcement, -1 for no eager evaluations, 0 for first only */
99 #define CONSHDLR_MAXPREROUNDS        -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
100 #define CONSHDLR_DELAYSEPA        FALSE /**< should separation method be delayed, if other separators found cuts? */
101 #define CONSHDLR_DELAYPROP        FALSE /**< should propagation method be delayed, if other propagators found reductions? */
102 #define CONSHDLR_NEEDSCONS         TRUE /**< should the constraint handler be skipped, if no constraints are available? */
103 
104 #define CONSHDLR_PRESOLTIMING    (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
105 #define CONSHDLR_PROP_TIMING     SCIP_PROPTIMING_BEFORELP
106 
107 #define EVENTHDLR_NAME         "linear"
108 #define EVENTHDLR_DESC         "bound change event handler for linear constraints"
109 
110 #define CONFLICTHDLR_NAME      "linear"
111 #define CONFLICTHDLR_DESC      "conflict handler creating linear constraints"
112 #define CONFLICTHDLR_PRIORITY  -1000000
113 
114 #define DEFAULT_TIGHTENBOUNDSFREQ       1 /**< multiplier on propagation frequency, how often the bounds are tightened */
115 #define DEFAULT_MAXROUNDS               5 /**< maximal number of separation rounds per node (-1: unlimited) */
116 #define DEFAULT_MAXROUNDSROOT          -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
117 #define DEFAULT_MAXSEPACUTS            50 /**< maximal number of cuts separated per separation round */
118 #define DEFAULT_MAXSEPACUTSROOT       200 /**< maximal number of cuts separated per separation round in root node */
119 #define DEFAULT_PRESOLPAIRWISE       TRUE /**< should pairwise constraint comparison be performed in presolving? */
120 #define DEFAULT_PRESOLUSEHASHING     TRUE /**< should hash table be used for detecting redundant constraints in advance */
121 #define DEFAULT_NMINCOMPARISONS    200000 /**< number for minimal pairwise presolving comparisons */
122 #define DEFAULT_MINGAINPERNMINCOMP  1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
123                                            *   comparison round */
124 #define DEFAULT_SORTVARS             TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
125                                            *  propagation? */
126 #define DEFAULT_CHECKRELMAXABS      FALSE /**< should the violation for a constraint with side 0.0 be checked relative
127                                            *   to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
128 #define DEFAULT_MAXAGGRNORMSCALE      0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
129                                            *   (0.0: disable constraint aggregation) */
130 #define DEFAULT_MAXEASYACTIVITYDELTA  1e6 /**< maximum activity delta to run easy propagation on linear constraint
131                                            *   (faster, but numerically less stable) */
132 #define DEFAULT_MAXCARDBOUNDDIST      0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
133                                            *   to best node's dual bound for separating knapsack cardinality cuts */
134 #define DEFAULT_SEPARATEALL         FALSE /**< should all constraints be subject to cardinality cut generation instead of only
135                                            *   the ones with non-zero dual value? */
136 #define DEFAULT_AGGREGATEVARIABLES   TRUE /**< should presolving search for redundant variables in equations */
137 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
138 #define DEFAULT_DUALPRESOLVING       TRUE /**< should dual presolving steps be performed? */
139 #define DEFAULT_SINGLETONSTUFFING    TRUE /**< should stuffing of singleton continuous variables be performed? */
140 #define DEFAULT_SINGLEVARSTUFFING   FALSE /**< should single variable stuffing be performed, which tries to fulfill
141                                            *   constraints using the cheapest variable? */
142 #define DEFAULT_DETECTCUTOFFBOUND    TRUE /**< should presolving try to detect constraints parallel to the objective
143                                            *   function defining an upper bound and prevent these constraints from
144                                            *   entering the LP */
145 #define DEFAULT_DETECTLOWERBOUND     TRUE /**< should presolving try to detect constraints parallel to the objective
146                                            *   function defining a lower bound and prevent these constraints from
147                                            *   entering the LP */
148 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
149                                             *   objective function */
150 #define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
151 #define DEFAULT_RANGEDROWARTCONS     TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
152 #define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
153 #define DEFAULT_RANGEDROWFREQ           1 /**< frequency for applying ranged row propagation */
154 
155 #define DEFAULT_MULTAGGRREMOVE      FALSE /**< should multi-aggregations only be performed if the constraint can be
156                                            *   removed afterwards? */
157 #define DEFAULT_MAXMULTAGGRQUOT     1e+03 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
158 #define DEFAULT_MAXDUALMULTAGGRQUOT 1e+20 /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for multiaggregation */
159 #define DEFAULT_EXTRACTCLIQUES       TRUE /**< should cliques be extracted? */
160 
161 #define MAXDNOM                   10000LL /**< maximal denominator for simple rational fixed values */
162 #define MAXSCALEDCOEF                   0 /**< maximal coefficient value after scaling */
163 #define MAXSCALEDCOEFINTEGER            0 /**< maximal coefficient value after scaling if all variables are of integral
164                                            *   type
165                                            */
166 
167 #define MAXVALRECOMP                1e+06 /**< maximal abolsute value we trust without recomputing the activity */
168 #define MINVALRECOMP                1e-05 /**< minimal abolsute value we trust without recomputing the activity */
169 
170 
171 #define QUADCONSUPGD_PRIORITY     1000000 /**< priority of the constraint handler for upgrading of quadratic constraints */
172 #define NONLINCONSUPGD_PRIORITY   1000000 /**< priority of the constraint handler for upgrading of nonlinear constraints */
173 
174 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
175  *       maybe in fullDualPresolve(), see convertLongEquality()
176  */
177 
178 
179 /** constraint data for linear constraints */
180 struct SCIP_ConsData
181 {
182    SCIP_Real             lhs;                /**< left hand side of row (for ranged rows) */
183    SCIP_Real             rhs;                /**< right hand side of row */
184    SCIP_Real             maxabsval;          /**< maximum absolute value of all coefficients */
185    SCIP_Real             minabsval;          /**< minimal absolute value of all coefficients */
186    SCIP_Real             minactivity;        /**< minimal value w.r.t. the variable's local bounds for the constraint's
187                                               *   activity, ignoring the coefficients contributing with infinite value */
188    SCIP_Real             maxactivity;        /**< maximal value w.r.t. the variable's local bounds for the constraint's
189                                               *   activity, ignoring the coefficients contributing with infinite value */
190    SCIP_Real             lastminactivity;    /**< last minimal activity which was computed by complete summation
191                                               *   over all contributing values */
192    SCIP_Real             lastmaxactivity;    /**< last maximal activity which was computed by complete summation
193                                               *   over all contributing values */
194    SCIP_Real             glbminactivity;     /**< minimal value w.r.t. the variable's global bounds for the constraint's
195                                               *   activity, ignoring the coefficients contributing with infinite value */
196    SCIP_Real             glbmaxactivity;     /**< maximal value w.r.t. the variable's global bounds for the constraint's
197                                               *   activity, ignoring the coefficients contributing with infinite value */
198    SCIP_Real             lastglbminactivity; /**< last global minimal activity which was computed by complete summation
199                                               *   over all contributing values */
200    SCIP_Real             lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
201                                               *   over all contributing values */
202    SCIP_Real             maxactdelta;        /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
203    SCIP_VAR*             maxactdeltavar;     /**< variable with maximal activity contribution, or NULL if invalid */
204    uint64_t              possignature;       /**< bit signature of coefficients that may take a positive value */
205    uint64_t              negsignature;       /**< bit signature of coefficients that may take a negative value */
206    SCIP_ROW*             row;                /**< LP row, if constraint is already stored in LP row format */
207    SCIP_VAR**            vars;               /**< variables of constraint entries */
208    SCIP_Real*            vals;               /**< coefficients of constraint entries */
209    SCIP_EVENTDATA**      eventdata;          /**< event data for bound change events of the variables */
210    int                   minactivityneginf;  /**< number of coefficients contributing with neg. infinite value to minactivity */
211    int                   minactivityposinf;  /**< number of coefficients contributing with pos. infinite value to minactivity */
212    int                   maxactivityneginf;  /**< number of coefficients contributing with neg. infinite value to maxactivity */
213    int                   maxactivityposinf;  /**< number of coefficients contributing with pos. infinite value to maxactivity */
214    int                   minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
215    int                   minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
216    int                   maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
217    int                   maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
218    int                   glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
219    int                   glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
220    int                   glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
221    int                   glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
222    int                   glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
223    int                   glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
224    int                   glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
225    int                   glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
226    int                   varssize;           /**< size of the vars- and vals-arrays */
227    int                   nvars;              /**< number of nonzeros in constraint */
228    int                   nbinvars;           /**< the number of binary variables in the constraint, only valid after
229                                               *   sorting in stage >= SCIP_STAGE_INITSOLVE
230                                               */
231    unsigned int          boundstightened:2;  /**< is constraint already propagated with bound tightening? */
232    unsigned int          rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
233                                                  *   (0: no, 1: yes, 2: with potentially adding artificial constraint */
234    unsigned int          validmaxabsval:1;   /**< is the maximum absolute value valid? */
235    unsigned int          validminabsval:1;   /**< is the minimum absolute value valid? */
236    unsigned int          validactivities:1;  /**< are the activity bounds (local and global) valid? */
237    unsigned int          validminact:1;      /**< is the local minactivity valid? */
238    unsigned int          validmaxact:1;      /**< is the local maxactivity valid? */
239    unsigned int          validglbminact:1;   /**< is the global minactivity valid? */
240    unsigned int          validglbmaxact:1;   /**< is the global maxactivity valid? */
241    unsigned int          presolved:1;        /**< is constraint already presolved? */
242    unsigned int          removedfixings:1;   /**< are all fixed variables removed from the constraint? */
243    unsigned int          validsignature:1;   /**< is the bit signature valid? */
244    unsigned int          changed:1;          /**< was constraint changed since last aggregation round in preprocessing? */
245    unsigned int          normalized:1;       /**< is the constraint in normalized form? */
246    unsigned int          upgradetried:1;     /**< was the constraint already tried to be upgraded? */
247    unsigned int          upgraded:1;         /**< is the constraint upgraded and will it be removed after preprocessing? */
248    unsigned int          indexsorted:1;      /**< are the constraint's variables sorted by type and index? */
249    unsigned int          merged:1;           /**< are the constraint's equal variables already merged? */
250    unsigned int          cliquesadded:1;     /**< were the cliques of the constraint already extracted? */
251    unsigned int          implsadded:1;       /**< were the implications of the constraint already extracted? */
252    unsigned int          coefsorted:1;       /**< are variables sorted by type and their absolute activity delta? */
253    unsigned int          varsdeleted:1;      /**< were variables deleted after last cleanup? */
254    unsigned int          hascontvar:1;       /**< does the constraint contain at least one continuous variable? */
255    unsigned int          hasnonbinvar:1;     /**< does the constraint contain at least one non-binary variable? */
256    unsigned int          hasnonbinvalid:1;   /**< is the information stored in hasnonbinvar and hascontvar valid? */
257    unsigned int          checkabsolute:1;    /**< should the constraint be checked w.r.t. an absolute feasibilty tolerance? */
258 };
259 
260 /** event data for bound change event */
261 struct SCIP_EventData
262 {
263    SCIP_CONS*            cons;               /**< linear constraint to process the bound change for */
264    int                   varpos;             /**< position of variable in vars array */
265    int                   filterpos;          /**< position of event in variable's event filter */
266 };
267 
268 /** constraint handler data */
269 struct SCIP_ConshdlrData
270 {
271    SCIP_EVENTHDLR*       eventhdlr;          /**< event handler for bound change events */
272    SCIP_LINCONSUPGRADE** linconsupgrades;    /**< linear constraint upgrade methods for specializing linear constraints */
273    SCIP_Real             maxaggrnormscale;   /**< maximal allowed relative gain in maximum norm for constraint aggregation
274                                               *   (0.0: disable constraint aggregation) */
275    SCIP_Real             maxcardbounddist;   /**< maximal relative distance from current node's dual bound to primal bound compared
276                                               *   to best node's dual bound for separating knapsack cardinality cuts */
277    SCIP_Real             mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
278    SCIP_Real             maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
279                                                *   (faster, but numerically less stable) */
280    int                   linconsupgradessize;/**< size of linconsupgrade array */
281    int                   nlinconsupgrades;   /**< number of linear constraint upgrade methods */
282    int                   tightenboundsfreq;  /**< multiplier on propagation frequency, how often the bounds are tightened */
283    int                   maxrounds;          /**< maximal number of separation rounds per node (-1: unlimited) */
284    int                   maxroundsroot;      /**< maximal number of separation rounds in the root node (-1: unlimited) */
285    int                   maxsepacuts;        /**< maximal number of cuts separated per separation round */
286    int                   maxsepacutsroot;    /**< maximal number of cuts separated per separation round in root node */
287    int                   nmincomparisons;    /**< number for minimal pairwise presolving comparisons */
288    int                   naddconss;          /**< number of added constraints */
289    SCIP_Bool             presolpairwise;     /**< should pairwise constraint comparison be performed in presolving? */
290    SCIP_Bool             presolusehashing;   /**< should hash table be used for detecting redundant constraints in advance */
291    SCIP_Bool             separateall;        /**< should all constraints be subject to cardinality cut generation instead of only
292                                               *   the ones with non-zero dual value? */
293    SCIP_Bool             aggregatevariables; /**< should presolving search for redundant variables in equations */
294    SCIP_Bool             simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
295    SCIP_Bool             dualpresolving;     /**< should dual presolving steps be performed? */
296    SCIP_Bool             singletonstuffing;  /**< should stuffing of singleton continuous variables be performed? */
297    SCIP_Bool             singlevarstuffing;  /**< should single variable stuffing be performed, which tries to fulfill
298                                               *   constraints using the cheapest variable? */
299    SCIP_Bool             sortvars;           /**< should binary variables be sorted for faster propagation? */
300    SCIP_Bool             checkrelmaxabs;     /**< should the violation for a constraint with side 0.0 be checked relative
301                                               *   to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
302    SCIP_Bool             detectcutoffbound;  /**< should presolving try to detect constraints parallel to the objective
303                                               *   function defining an upper bound and prevent these constraints from
304                                               *   entering the LP */
305    SCIP_Bool             detectlowerbound;   /**< should presolving try to detect constraints parallel to the objective
306                                               *   function defining a lower bound and prevent these constraints from
307                                               *   entering the LP */
308    SCIP_Bool             detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
309                                                  *   the objective function */
310    SCIP_Bool             rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
311                                                *   infeasibility, and extract sub-constraints from ranged rows and
312                                                *   equations */
313    SCIP_Bool             rangedrowartcons;   /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
314    int                   rangedrowmaxdepth;  /**< maximum depth to apply ranged row propagation */
315    int                   rangedrowfreq;      /**< frequency for applying ranged row propagation */
316    SCIP_Bool             multaggrremove;     /**< should multi-aggregations only be performed if the constraint can be
317                                               *   removed afterwards? */
318    SCIP_Real             maxmultaggrquot;    /**< maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation */
319    SCIP_Real             maxdualmultaggrquot;/**< maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation */
320    SCIP_Bool             extractcliques;     /**< should cliques be extracted? */
321 };
322 
323 /** linear constraint update method */
324 struct SCIP_LinConsUpgrade
325 {
326    SCIP_DECL_LINCONSUPGD((*linconsupgd));    /**< method to call for upgrading linear constraint */
327    int                   priority;           /**< priority of upgrading method */
328    SCIP_Bool             active;             /**< is upgrading enabled */
329 };
330 
331 
332 /*
333  * Propagation rules
334  */
335 
336 enum Proprule
337 {
338    PROPRULE_1_RHS        = 1,                /**< activity residuals of all other variables tighten bounds of single
339                                               *   variable due to the right hand side of the inequality */
340    PROPRULE_1_LHS        = 2,                /**< activity residuals of all other variables tighten bounds of single
341                                               *   variable due to the left hand side of the inequality */
342    PROPRULE_1_RANGEDROW  = 3,                /**< fixed variables and gcd of all left variables tighten bounds of a
343 					      *   single variable in this reanged row */
344    PROPRULE_INVALID      = 0                 /**< propagation was applied without a specific propagation rule */
345 };
346 typedef enum Proprule PROPRULE;
347 
348 /** inference information */
349 struct InferInfo
350 {
351    union
352    {
353       struct
354       {
355          unsigned int    proprule:8;         /**< propagation rule that was applied */
356          unsigned int    pos:24;             /**< variable position, the propagation rule was applied at */
357       } asbits;
358       int                asint;              /**< inference information as a single int value */
359    } val;
360 };
361 typedef struct InferInfo INFERINFO;
362 
363 /** converts an integer into an inference information */
364 static
intToInferInfo(int i)365 INFERINFO intToInferInfo(
366    int                   i                   /**< integer to convert */
367    )
368 {
369    INFERINFO inferinfo;
370 
371    inferinfo.val.asint = i;
372 
373    return inferinfo;
374 }
375 
376 /** converts an inference information into an int */
377 static
inferInfoToInt(INFERINFO inferinfo)378 int inferInfoToInt(
379    INFERINFO             inferinfo           /**< inference information to convert */
380    )
381 {
382    return inferinfo.val.asint;
383 }
384 
385 /** returns the propagation rule stored in the inference information */
386 static
inferInfoGetProprule(INFERINFO inferinfo)387 int inferInfoGetProprule(
388    INFERINFO             inferinfo           /**< inference information to convert */
389    )
390 {
391    return (int) inferinfo.val.asbits.proprule;
392 }
393 
394 /** returns the position stored in the inference information */
395 static
inferInfoGetPos(INFERINFO inferinfo)396 int inferInfoGetPos(
397    INFERINFO             inferinfo           /**< inference information to convert */
398    )
399 {
400    return (int) inferinfo.val.asbits.pos;
401 }
402 
403 /** constructs an inference information out of a propagation rule and a position number */
404 static
getInferInfo(PROPRULE proprule,int pos)405 INFERINFO getInferInfo(
406    PROPRULE              proprule,           /**< propagation rule that deduced the value */
407    int                   pos                 /**< variable position, the propagation rule was applied at */
408    )
409 {
410    INFERINFO inferinfo;
411 
412    assert(pos >= 0);
413    /* in the inferinfo struct only 24 bits for 'pos' are reserved */
414    assert(pos < (1<<24));
415 
416    inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
417    inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
418 
419    return inferinfo;
420 }
421 
422 /** constructs an inference information out of a propagation rule and a position number, returns info as int */
423 static
getInferInt(PROPRULE proprule,int pos)424 int getInferInt(
425    PROPRULE              proprule,           /**< propagation rule that deduced the value */
426    int                   pos                 /**< variable position, the propagation rule was applied at */
427    )
428 {
429    return inferInfoToInt(getInferInfo(proprule, pos));
430 }
431 
432 
433 /*
434  * memory growing methods for dynamically allocated arrays
435  */
436 
437 /** ensures, that linconsupgrades array can store at least num entries */
438 static
conshdlrdataEnsureLinconsupgradesSize(SCIP * scip,SCIP_CONSHDLRDATA * conshdlrdata,int num)439 SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(
440    SCIP*                 scip,               /**< SCIP data structure */
441    SCIP_CONSHDLRDATA*    conshdlrdata,       /**< linear constraint handler data */
442    int                   num                 /**< minimum number of entries to store */
443    )
444 {
445    assert(scip != NULL);
446    assert(conshdlrdata != NULL);
447    assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
448 
449    if( num > conshdlrdata->linconsupgradessize )
450    {
451       int newsize;
452 
453       newsize = SCIPcalcMemGrowSize(scip, num);
454       SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
455       conshdlrdata->linconsupgradessize = newsize;
456    }
457    assert(num <= conshdlrdata->linconsupgradessize);
458 
459    return SCIP_OKAY;
460 }
461 
462 /** ensures, that vars and vals arrays can store at least num entries */
463 static
consdataEnsureVarsSize(SCIP * scip,SCIP_CONSDATA * consdata,int num)464 SCIP_RETCODE consdataEnsureVarsSize(
465    SCIP*                 scip,               /**< SCIP data structure */
466    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
467    int                   num                 /**< minimum number of entries to store */
468    )
469 {
470    assert(scip != NULL);
471    assert(consdata != NULL);
472    assert(consdata->nvars <= consdata->varssize);
473 
474    if( num > consdata->varssize )
475    {
476       int newsize;
477 
478       newsize = SCIPcalcMemGrowSize(scip, num);
479       SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
480       SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
481       if( consdata->eventdata != NULL )
482       {
483          SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
484       }
485       consdata->varssize = newsize;
486    }
487    assert(num <= consdata->varssize);
488 
489    return SCIP_OKAY;
490 }
491 
492 
493 /*
494  * local methods for managing linear constraint update methods
495  */
496 
497 /** creates a linear constraint upgrade data object */
498 static
linconsupgradeCreate(SCIP * scip,SCIP_LINCONSUPGRADE ** linconsupgrade,SCIP_DECL_LINCONSUPGD ((* linconsupgd)),int priority)499 SCIP_RETCODE linconsupgradeCreate(
500    SCIP*                 scip,               /**< SCIP data structure */
501    SCIP_LINCONSUPGRADE** linconsupgrade,     /**< pointer to store the linear constraint upgrade */
502    SCIP_DECL_LINCONSUPGD((*linconsupgd)),    /**< method to call for upgrading linear constraint */
503    int                   priority            /**< priority of upgrading method */
504    )
505 {
506    assert(scip != NULL);
507    assert(linconsupgrade != NULL);
508    assert(linconsupgd != NULL);
509 
510    SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
511    (*linconsupgrade)->linconsupgd = linconsupgd;
512    (*linconsupgrade)->priority = priority;
513    (*linconsupgrade)->active = TRUE;
514 
515    return SCIP_OKAY;
516 }
517 
518 /** frees a linear constraint upgrade data object */
519 static
linconsupgradeFree(SCIP * scip,SCIP_LINCONSUPGRADE ** linconsupgrade)520 void linconsupgradeFree(
521    SCIP*                 scip,               /**< SCIP data structure */
522    SCIP_LINCONSUPGRADE** linconsupgrade      /**< pointer to the linear constraint upgrade */
523    )
524 {
525    assert(scip != NULL);
526    assert(linconsupgrade != NULL);
527    assert(*linconsupgrade != NULL);
528 
529    SCIPfreeBlockMemory(scip, linconsupgrade);
530 }
531 
532 /** creates constraint handler data for linear constraint handler */
533 static
conshdlrdataCreate(SCIP * scip,SCIP_CONSHDLRDATA ** conshdlrdata,SCIP_EVENTHDLR * eventhdlr)534 SCIP_RETCODE conshdlrdataCreate(
535    SCIP*                 scip,               /**< SCIP data structure */
536    SCIP_CONSHDLRDATA**   conshdlrdata,       /**< pointer to store the constraint handler data */
537    SCIP_EVENTHDLR*       eventhdlr           /**< event handler */
538    )
539 {
540    assert(scip != NULL);
541    assert(conshdlrdata != NULL);
542    assert(eventhdlr != NULL);
543 
544    SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
545    (*conshdlrdata)->linconsupgrades = NULL;
546    (*conshdlrdata)->linconsupgradessize = 0;
547    (*conshdlrdata)->nlinconsupgrades = 0;
548    (*conshdlrdata)->naddconss = 0;
549 
550    /* set event handler for updating linear constraint activity bounds */
551    (*conshdlrdata)->eventhdlr = eventhdlr;
552 
553    return SCIP_OKAY;
554 }
555 
556 /** frees constraint handler data for linear constraint handler */
557 static
conshdlrdataFree(SCIP * scip,SCIP_CONSHDLRDATA ** conshdlrdata)558 void conshdlrdataFree(
559    SCIP*                 scip,               /**< SCIP data structure */
560    SCIP_CONSHDLRDATA**   conshdlrdata        /**< pointer to the constraint handler data */
561    )
562 {
563    int i;
564 
565    assert(scip != NULL);
566    assert(conshdlrdata != NULL);
567    assert(*conshdlrdata != NULL);
568 
569    for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
570    {
571       linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
572    }
573    SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
574 
575    SCIPfreeBlockMemory(scip, conshdlrdata);
576 }
577 
578 /** creates a linear constraint upgrade data object */
579 static
conshdlrdataHasUpgrade(SCIP * scip,SCIP_CONSHDLRDATA * conshdlrdata,SCIP_DECL_LINCONSUPGD ((* linconsupgd)),const char * conshdlrname)580 SCIP_Bool conshdlrdataHasUpgrade(
581    SCIP*                 scip,               /**< SCIP data structure */
582    SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
583    SCIP_DECL_LINCONSUPGD((*linconsupgd)),    /**< method to call for upgrading linear constraint */
584    const char*           conshdlrname        /**< name of the constraint handler */
585    )
586 {
587    int i;
588 
589    assert(scip != NULL);
590    assert(conshdlrdata != NULL);
591    assert(linconsupgd != NULL);
592    assert(conshdlrname != NULL);
593 
594    for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
595    {
596       if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
597       {
598 #ifdef SCIP_DEBUG
599          SCIPwarningMessage(scip, "Try to add already known upgrade message for constraint handler %s.\n", conshdlrname);
600 #endif
601          return TRUE;
602       }
603    }
604 
605    return FALSE;
606 }
607 
608 /** adds a linear constraint update method to the constraint handler's data */
609 static
conshdlrdataIncludeUpgrade(SCIP * scip,SCIP_CONSHDLRDATA * conshdlrdata,SCIP_LINCONSUPGRADE * linconsupgrade)610 SCIP_RETCODE conshdlrdataIncludeUpgrade(
611    SCIP*                 scip,               /**< SCIP data structure */
612    SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
613    SCIP_LINCONSUPGRADE*  linconsupgrade      /**< linear constraint upgrade method */
614    )
615 {
616    int i;
617 
618    assert(scip != NULL);
619    assert(conshdlrdata != NULL);
620    assert(linconsupgrade != NULL);
621 
622    SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
623 
624    for( i = conshdlrdata->nlinconsupgrades;
625         i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
626    {
627       conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
628    }
629    assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
630    conshdlrdata->linconsupgrades[i] = linconsupgrade;
631    conshdlrdata->nlinconsupgrades++;
632 
633    return SCIP_OKAY;
634 }
635 
636 /*
637  * local methods
638  */
639 
640 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
641 static
lockRounding(SCIP * scip,SCIP_CONS * cons,SCIP_VAR * var,SCIP_Real val)642 SCIP_RETCODE lockRounding(
643    SCIP*                 scip,               /**< SCIP data structure */
644    SCIP_CONS*            cons,               /**< linear constraint */
645    SCIP_VAR*             var,                /**< variable of constraint entry */
646    SCIP_Real             val                 /**< coefficient of constraint entry */
647    )
648 {
649    SCIP_CONSDATA* consdata;
650 
651    assert(scip != NULL);
652    assert(cons != NULL);
653    assert(var != NULL);
654 
655    consdata = SCIPconsGetData(cons);
656    assert(consdata != NULL);
657    assert(!SCIPisZero(scip, val));
658 
659    if( SCIPisPositive(scip, val) )
660    {
661       SCIP_CALL( SCIPlockVarCons(scip, var, cons,
662          !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
663    }
664    else
665    {
666       SCIP_CALL( SCIPlockVarCons(scip, var, cons,
667          !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
668    }
669 
670    return SCIP_OKAY;
671 }
672 
673 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
674 static
unlockRounding(SCIP * scip,SCIP_CONS * cons,SCIP_VAR * var,SCIP_Real val)675 SCIP_RETCODE unlockRounding(
676    SCIP*                 scip,               /**< SCIP data structure */
677    SCIP_CONS*            cons,               /**< linear constraint */
678    SCIP_VAR*             var,                /**< variable of constraint entry */
679    SCIP_Real             val                 /**< coefficient of constraint entry */
680    )
681 {
682    SCIP_CONSDATA* consdata;
683 
684    assert(scip != NULL);
685    assert(cons != NULL);
686    assert(var != NULL);
687 
688    consdata = SCIPconsGetData(cons);
689    assert(consdata != NULL);
690    assert(!SCIPisZero(scip, val));
691 
692    if( SCIPisPositive(scip, val) )
693    {
694       SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, -consdata->lhs),
695          !SCIPisInfinity(scip, consdata->rhs)) );
696    }
697    else
698    {
699       SCIP_CALL( SCIPunlockVarCons(scip, var, cons, !SCIPisInfinity(scip, consdata->rhs),
700          !SCIPisInfinity(scip, -consdata->lhs)) );
701    }
702 
703    return SCIP_OKAY;
704 }
705 
706 /** creates event data for variable at given position, and catches events */
707 /**! [SnippetDebugAssertions] */
708 static
consCatchEvent(SCIP * scip,SCIP_CONS * cons,SCIP_EVENTHDLR * eventhdlr,int pos)709 SCIP_RETCODE consCatchEvent(
710    SCIP*                 scip,               /**< SCIP data structure */
711    SCIP_CONS*            cons,               /**< linear constraint */
712    SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
713    int                   pos                 /**< array position of variable to catch bound change events for */
714    )
715 {
716    SCIP_CONSDATA* consdata;
717    assert(scip != NULL);
718    assert(cons != NULL);
719    assert(eventhdlr != NULL);
720 
721    consdata = SCIPconsGetData(cons);
722    assert(consdata != NULL);
723 
724    assert(0 <= pos && pos < consdata->nvars);
725    assert(consdata->vars != NULL);
726    assert(consdata->vars[pos] != NULL);
727    assert(SCIPvarIsTransformed(consdata->vars[pos]));
728    assert(consdata->eventdata != NULL);
729    assert(consdata->eventdata[pos] == NULL);
730 
731    SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
732    consdata->eventdata[pos]->cons = cons;
733    consdata->eventdata[pos]->varpos = pos;
734 
735    SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
736          SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_VARFIXED | SCIP_EVENTTYPE_VARUNLOCKED
737          | SCIP_EVENTTYPE_GBDCHANGED | SCIP_EVENTTYPE_VARDELETED | SCIP_EVENTTYPE_TYPECHANGED,
738          eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
739 
740    consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(consdata->vars[pos]);
741 
742    return SCIP_OKAY;
743 }
744 /**! [SnippetDebugAssertions] */
745 
746 /** deletes event data for variable at given position, and drops events */
747 static
consDropEvent(SCIP * scip,SCIP_CONS * cons,SCIP_EVENTHDLR * eventhdlr,int pos)748 SCIP_RETCODE consDropEvent(
749    SCIP*                 scip,               /**< SCIP data structure */
750    SCIP_CONS*            cons,               /**< linear constraint */
751    SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
752    int                   pos                 /**< array position of variable to catch bound change events for */
753    )
754 {
755    SCIP_CONSDATA* consdata;
756    assert(scip != NULL);
757    assert(cons != NULL);
758    assert(eventhdlr != NULL);
759 
760    consdata = SCIPconsGetData(cons);
761    assert(consdata != NULL);
762 
763    assert(0 <= pos && pos < consdata->nvars);
764    assert(consdata->vars[pos] != NULL);
765    assert(consdata->eventdata != NULL);
766    assert(consdata->eventdata[pos] != NULL);
767    assert(consdata->eventdata[pos]->cons == cons);
768    assert(consdata->eventdata[pos]->varpos == pos);
769 
770    SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
771          SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_VARFIXED | SCIP_EVENTTYPE_VARUNLOCKED
772          | SCIP_EVENTTYPE_GBDCHANGED | SCIP_EVENTTYPE_VARDELETED | SCIP_EVENTTYPE_TYPECHANGED,
773          eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
774 
775    SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
776 
777    return SCIP_OKAY;
778 }
779 
780 /** catches bound change events for all variables in transformed linear constraint */
781 static
consCatchAllEvents(SCIP * scip,SCIP_CONS * cons,SCIP_EVENTHDLR * eventhdlr)782 SCIP_RETCODE consCatchAllEvents(
783    SCIP*                 scip,               /**< SCIP data structure */
784    SCIP_CONS*            cons,               /**< linear constraint */
785    SCIP_EVENTHDLR*       eventhdlr           /**< event handler to call for the event processing */
786    )
787 {
788    SCIP_CONSDATA* consdata;
789    int i;
790 
791    assert(scip != NULL);
792    assert(cons != NULL);
793 
794    consdata = SCIPconsGetData(cons);
795    assert(consdata != NULL);
796    assert(consdata->eventdata == NULL);
797 
798    /* allocate eventdata array */
799    SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
800    assert(consdata->eventdata != NULL);
801    BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
802 
803    /* catch event for every single variable */
804    for( i = 0; i < consdata->nvars; ++i )
805    {
806       SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
807    }
808 
809    return SCIP_OKAY;
810 }
811 
812 /** drops bound change events for all variables in transformed linear constraint */
813 static
consDropAllEvents(SCIP * scip,SCIP_CONS * cons,SCIP_EVENTHDLR * eventhdlr)814 SCIP_RETCODE consDropAllEvents(
815    SCIP*                 scip,               /**< SCIP data structure */
816    SCIP_CONS*            cons,               /**< linear constraint */
817    SCIP_EVENTHDLR*       eventhdlr           /**< event handler to call for the event processing */
818    )
819 {
820    SCIP_CONSDATA* consdata;
821    int i;
822 
823    assert(scip != NULL);
824    assert(cons != NULL);
825 
826    consdata = SCIPconsGetData(cons);
827    assert(consdata != NULL);
828    assert(consdata->eventdata != NULL);
829 
830    /* drop event of every single variable */
831    for( i = consdata->nvars - 1; i >= 0; --i )
832    {
833       SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
834    }
835 
836    /* free eventdata array */
837    SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
838    assert(consdata->eventdata == NULL);
839 
840    return SCIP_OKAY;
841 }
842 
843 /** creates a linear constraint data */
844 static
consdataCreate(SCIP * scip,SCIP_CONSDATA ** consdata,int nvars,SCIP_VAR ** vars,SCIP_Real * vals,SCIP_Real lhs,SCIP_Real rhs)845 SCIP_RETCODE consdataCreate(
846    SCIP*                 scip,               /**< SCIP data structure */
847    SCIP_CONSDATA**       consdata,           /**< pointer to linear constraint data */
848    int                   nvars,              /**< number of nonzeros in the constraint */
849    SCIP_VAR**            vars,               /**< array with variables of constraint entries */
850    SCIP_Real*            vals,               /**< array with coefficients of constraint entries */
851    SCIP_Real             lhs,                /**< left hand side of row */
852    SCIP_Real             rhs                 /**< right hand side of row */
853    )
854 {
855    int v;
856    SCIP_Real constant;
857 
858    assert(scip != NULL);
859    assert(consdata != NULL);
860    assert(nvars == 0 || vars != NULL);
861    assert(nvars == 0 || vals != NULL);
862 
863    if( SCIPisInfinity(scip, rhs) )
864       rhs = SCIPinfinity(scip);
865    else if( SCIPisInfinity(scip, -rhs) )
866       rhs = -SCIPinfinity(scip);
867 
868    if( SCIPisInfinity(scip, -lhs) )
869       lhs = -SCIPinfinity(scip);
870    else if( SCIPisInfinity(scip, lhs) )
871       lhs = SCIPinfinity(scip);
872 
873    if( SCIPisGT(scip, lhs, rhs) )
874    {
875       SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
876       SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
877    }
878 
879    SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
880 
881    (*consdata)->varssize = 0;
882    (*consdata)->nvars = nvars;
883    (*consdata)->hascontvar = FALSE;
884    (*consdata)->hasnonbinvar = FALSE;
885    (*consdata)->hasnonbinvalid = TRUE;
886    (*consdata)->vars = NULL;
887    (*consdata)->vals = NULL;
888 
889    constant = 0.0;
890    if( nvars > 0 )
891    {
892       int k;
893 
894       SCIP_VAR** varsbuffer;
895       SCIP_Real* valsbuffer;
896 
897       /* copy variables into temporary buffer */
898       SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
899       SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
900       k = 0;
901 
902       /* loop over variables and sort out fixed ones */
903       for( v = 0; v < nvars; ++v )
904       {
905          SCIP_VAR* var;
906          SCIP_Real val;
907 
908          var = vars[v];
909          val = vals[v];
910 
911          assert(var != NULL);
912          if( !SCIPisZero(scip, val) )
913          {
914             /* treat fixed variable as a constant if problem compression is enabled */
915             if( SCIPisConsCompressionEnabled(scip) && SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
916             {
917                constant += SCIPvarGetLbGlobal(var) * val;
918             }
919             else
920             {
921                varsbuffer[k] = var;
922                valsbuffer[k] = val;
923                k++;
924 
925                /* update hascontvar and hasnonbinvar flags */
926                if( !(*consdata)->hascontvar )
927                {
928                   SCIP_VARTYPE vartype = SCIPvarGetType(var);
929 
930                   if( vartype != SCIP_VARTYPE_BINARY )
931                   {
932                      (*consdata)->hasnonbinvar = TRUE;
933 
934                      if( vartype == SCIP_VARTYPE_CONTINUOUS )
935                         (*consdata)->hascontvar = TRUE;
936                   }
937                }
938             }
939          }
940       }
941       (*consdata)->nvars = k;
942 
943       if( k > 0 )
944       {
945          /* copy the possibly reduced buffer arrays into block */
946          SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
947          SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) );
948          (*consdata)->varssize = k;
949       }
950       /* free temporary buffer */
951       SCIPfreeBufferArray(scip, &valsbuffer);
952       SCIPfreeBufferArray(scip, &varsbuffer);
953    }
954 
955    (*consdata)->eventdata = NULL;
956 
957    /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
958    if( !SCIPisZero(scip, constant) )
959    {
960       if( !SCIPisInfinity(scip, REALABS(lhs)) )
961          lhs -= constant;
962 
963       if( !SCIPisInfinity(scip, REALABS(rhs)) )
964          rhs -= constant;
965    }
966 
967    (*consdata)->row = NULL;
968    (*consdata)->lhs = lhs;
969    (*consdata)->rhs = rhs;
970    (*consdata)->maxabsval = SCIP_INVALID;
971    (*consdata)->minabsval = SCIP_INVALID;
972    (*consdata)->minactivity = SCIP_INVALID;
973    (*consdata)->maxactivity = SCIP_INVALID;
974    (*consdata)->lastminactivity = SCIP_INVALID;
975    (*consdata)->lastmaxactivity = SCIP_INVALID;
976    (*consdata)->maxactdelta = SCIP_INVALID;
977    (*consdata)->maxactdeltavar = NULL;
978    (*consdata)->minactivityneginf = -1;
979    (*consdata)->minactivityposinf = -1;
980    (*consdata)->maxactivityneginf = -1;
981    (*consdata)->maxactivityposinf = -1;
982    (*consdata)->minactivityneghuge = -1;
983    (*consdata)->minactivityposhuge = -1;
984    (*consdata)->maxactivityneghuge = -1;
985    (*consdata)->maxactivityposhuge = -1;
986    (*consdata)->glbminactivity = SCIP_INVALID;
987    (*consdata)->glbmaxactivity = SCIP_INVALID;
988    (*consdata)->lastglbminactivity = SCIP_INVALID;
989    (*consdata)->lastglbmaxactivity = SCIP_INVALID;
990    (*consdata)->glbminactivityneginf = -1;
991    (*consdata)->glbminactivityposinf = -1;
992    (*consdata)->glbmaxactivityneginf = -1;
993    (*consdata)->glbmaxactivityposinf = -1;
994    (*consdata)->glbminactivityneghuge = -1;
995    (*consdata)->glbminactivityposhuge = -1;
996    (*consdata)->glbmaxactivityneghuge = -1;
997    (*consdata)->glbmaxactivityposhuge = -1;
998    (*consdata)->possignature = 0;
999    (*consdata)->negsignature = 0;
1000    (*consdata)->validmaxabsval = FALSE;
1001    (*consdata)->validminabsval = FALSE;
1002    (*consdata)->validactivities = FALSE;
1003    (*consdata)->validminact = FALSE;
1004    (*consdata)->validmaxact = FALSE;
1005    (*consdata)->validglbminact = FALSE;
1006    (*consdata)->validglbmaxact = FALSE;
1007    (*consdata)->boundstightened = 0;
1008    (*consdata)->presolved = FALSE;
1009    (*consdata)->removedfixings = FALSE;
1010    (*consdata)->validsignature = FALSE;
1011    (*consdata)->changed = TRUE;
1012    (*consdata)->normalized = FALSE;
1013    (*consdata)->upgradetried = FALSE;
1014    (*consdata)->upgraded = FALSE;
1015    (*consdata)->indexsorted = (nvars <= 1);
1016    (*consdata)->merged = (nvars <= 1);
1017    (*consdata)->cliquesadded = FALSE;
1018    (*consdata)->implsadded = FALSE;
1019    (*consdata)->coefsorted = FALSE;
1020    (*consdata)->nbinvars = -1;
1021    (*consdata)->varsdeleted = FALSE;
1022    (*consdata)->rangedrowpropagated = 0;
1023    (*consdata)->checkabsolute = FALSE;
1024 
1025    if( SCIPisTransformed(scip) )
1026    {
1027       /* get transformed variables */
1028       SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1029    }
1030 
1031    /* capture variables */
1032    for( v = 0; v < (*consdata)->nvars; v++ )
1033    {
1034       assert((*consdata)->vars[v] != NULL);
1035       assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1036       SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1037    }
1038 
1039    return SCIP_OKAY;
1040 }
1041 
1042 /** frees a linear constraint data */
1043 static
consdataFree(SCIP * scip,SCIP_CONSDATA ** consdata)1044 SCIP_RETCODE consdataFree(
1045    SCIP*                 scip,               /**< SCIP data structure */
1046    SCIP_CONSDATA**       consdata            /**< pointer to linear constraint data */
1047    )
1048 {
1049    int v;
1050 
1051    assert(scip != NULL);
1052    assert(consdata != NULL);
1053    assert(*consdata != NULL);
1054    assert((*consdata)->varssize >= 0);
1055 
1056    /* release the row */
1057    if( (*consdata)->row != NULL )
1058    {
1059       SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1060    }
1061 
1062    /* release variables */
1063    for( v = 0; v < (*consdata)->nvars; v++ )
1064    {
1065       assert((*consdata)->vars[v] != NULL);
1066       assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1067       SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1068    }
1069 
1070    SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1071    SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1072    SCIPfreeBlockMemory(scip, consdata);
1073 
1074    return SCIP_OKAY;
1075 }
1076 
1077 /** prints linear constraint in CIP format to file stream */
1078 static
consdataPrint(SCIP * scip,SCIP_CONSDATA * consdata,FILE * file)1079 SCIP_RETCODE consdataPrint(
1080    SCIP*                 scip,               /**< SCIP data structure */
1081    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
1082    FILE*                 file                /**< output file (or NULL for standard output) */
1083    )
1084 {
1085    assert(scip != NULL);
1086    assert(consdata != NULL);
1087 
1088    /* print left hand side for ranged rows */
1089    if( !SCIPisInfinity(scip, -consdata->lhs)
1090       && !SCIPisInfinity(scip, consdata->rhs)
1091       && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1092       SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1093 
1094    /* print coefficients and variables */
1095    if( consdata->nvars == 0 )
1096       SCIPinfoMessage(scip, file, "0");
1097    else
1098    {
1099       /* post linear sum of the linear constraint */
1100       SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1101    }
1102 
1103    /* print right hand side */
1104    if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1105       SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1106    else if( !SCIPisInfinity(scip, consdata->rhs) )
1107       SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1108    else if( !SCIPisInfinity(scip, -consdata->lhs) )
1109       SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1110    else
1111       SCIPinfoMessage(scip, file, " [free]");
1112 
1113    return SCIP_OKAY;
1114 }
1115 
1116 /** prints linear constraint and contained solution values of variables to file stream */
1117 static
consPrintConsSol(SCIP * scip,SCIP_CONS * cons,SCIP_SOL * sol,FILE * file)1118 SCIP_RETCODE consPrintConsSol(
1119    SCIP*                 scip,               /**< SCIP data structure */
1120    SCIP_CONS*            cons,               /**< linear constraint */
1121    SCIP_SOL*             sol,                /**< solution to print */
1122    FILE*                 file                /**< output file (or NULL for standard output) */
1123    )
1124 {
1125    SCIP_CONSDATA* consdata;
1126 
1127    assert(scip != NULL);
1128    assert(cons != NULL);
1129 
1130    consdata = SCIPconsGetData(cons);
1131    assert(consdata != NULL);
1132 
1133    SCIPmessageFPrintInfo(SCIPgetMessagehdlr(scip), file, "  [%s] <%s>: ", SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), SCIPconsGetName(cons));
1134 
1135    /* print left hand side for ranged rows */
1136    if( !SCIPisInfinity(scip, -consdata->lhs)
1137       && !SCIPisInfinity(scip, consdata->rhs)
1138       && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1139       SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1140 
1141    /* print coefficients and variables */
1142    if( consdata->nvars == 0 )
1143       SCIPinfoMessage(scip, file, "0");
1144    else
1145    {
1146       int v;
1147 
1148       /* post linear sum of the linear constraint */
1149       for( v = 0; v < consdata->nvars; ++v )
1150       {
1151          if( consdata->vals != NULL )
1152          {
1153             if( consdata->vals[v] == 1.0 )
1154             {
1155                if( v > 0 )
1156                   SCIPinfoMessage(scip, file, " +");
1157             }
1158             else if( consdata->vals[v] == -1.0 )
1159                SCIPinfoMessage(scip, file, " -");
1160             else
1161                SCIPinfoMessage(scip, file, " %+.9g", consdata->vals[v]);
1162          }
1163          else if( consdata->nvars > 0 )
1164             SCIPinfoMessage(scip, file, " +");
1165 
1166          /* print variable name */
1167          SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[v], TRUE) );
1168 
1169          SCIPinfoMessage(scip, file, " (%+.9g)", SCIPgetSolVal(scip, sol, consdata->vars[v]));
1170       }
1171    }
1172 
1173    /* print right hand side */
1174    if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1175       SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1176    else if( !SCIPisInfinity(scip, consdata->rhs) )
1177       SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1178    else if( !SCIPisInfinity(scip, -consdata->lhs) )
1179       SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1180    else
1181       SCIPinfoMessage(scip, file, " [free]");
1182 
1183    SCIPinfoMessage(scip, file, ";\n");
1184 
1185    return SCIP_OKAY;
1186 }
1187 
1188 /** invalidates activity bounds, such that they are recalculated in next get */
1189 static
consdataInvalidateActivities(SCIP_CONSDATA * consdata)1190 void consdataInvalidateActivities(
1191    SCIP_CONSDATA*        consdata            /**< linear constraint */
1192    )
1193 {
1194    assert(consdata != NULL);
1195 
1196    consdata->validactivities = FALSE;
1197    consdata->validminact = FALSE;
1198    consdata->validmaxact = FALSE;
1199    consdata->validglbminact = FALSE;
1200    consdata->validglbmaxact = FALSE;
1201    consdata->validmaxabsval = FALSE;
1202    consdata->validminabsval = FALSE;
1203    consdata->hasnonbinvalid = FALSE;
1204    consdata->minactivity = SCIP_INVALID;
1205    consdata->maxactivity = SCIP_INVALID;
1206    consdata->lastminactivity = SCIP_INVALID;
1207    consdata->lastmaxactivity = SCIP_INVALID;
1208    consdata->maxabsval = SCIP_INVALID;
1209    consdata->minabsval = SCIP_INVALID;
1210    consdata->maxactdelta = SCIP_INVALID;
1211    consdata->maxactdeltavar = NULL;
1212    consdata->minactivityneginf = -1;
1213    consdata->minactivityposinf = -1;
1214    consdata->maxactivityneginf = -1;
1215    consdata->maxactivityposinf = -1;
1216    consdata->minactivityneghuge = -1;
1217    consdata->minactivityposhuge = -1;
1218    consdata->maxactivityneghuge = -1;
1219    consdata->maxactivityposhuge = -1;
1220    consdata->glbminactivity = SCIP_INVALID;
1221    consdata->glbmaxactivity = SCIP_INVALID;
1222    consdata->lastglbminactivity = SCIP_INVALID;
1223    consdata->lastglbmaxactivity = SCIP_INVALID;
1224    consdata->glbminactivityneginf = -1;
1225    consdata->glbminactivityposinf = -1;
1226    consdata->glbmaxactivityneginf = -1;
1227    consdata->glbmaxactivityposinf = -1;
1228    consdata->glbminactivityneghuge = -1;
1229    consdata->glbminactivityposhuge = -1;
1230    consdata->glbmaxactivityneghuge = -1;
1231    consdata->glbmaxactivityposhuge = -1;
1232 }
1233 
1234 /** compute the pseudo activity of a constraint */
1235 static
consdataComputePseudoActivity(SCIP * scip,SCIP_CONSDATA * consdata)1236 SCIP_Real consdataComputePseudoActivity(
1237    SCIP*                 scip,               /**< SCIP data structure */
1238    SCIP_CONSDATA*        consdata            /**< linear constraint data */
1239    )
1240 {
1241    int i;
1242    int pseudoactivityposinf;
1243    int pseudoactivityneginf;
1244    SCIP_Real pseudoactivity;
1245    SCIP_Real bound;
1246    SCIP_Real val;
1247 
1248    pseudoactivity = 0;
1249    pseudoactivityposinf = 0;
1250    pseudoactivityneginf = 0;
1251 
1252    for( i = consdata->nvars - 1; i >= 0; --i )
1253    {
1254       val = consdata->vals[i];
1255       bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1256       if( SCIPisInfinity(scip, bound) )
1257       {
1258          if( val > 0.0 )
1259             pseudoactivityposinf++;
1260          else
1261             pseudoactivityneginf++;
1262       }
1263       else
1264       {
1265          if( SCIPisInfinity(scip, -bound) )
1266          {
1267             if( val > 0.0 )
1268                pseudoactivityneginf++;
1269             else
1270                pseudoactivityposinf++;
1271          }
1272          else
1273             pseudoactivity += val * bound;
1274       }
1275    }
1276 
1277    if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1278       return SCIP_INVALID;
1279    else if( pseudoactivityneginf > 0 )
1280       return -SCIPinfinity(scip);
1281    else if( pseudoactivityposinf > 0 )
1282       return SCIPinfinity(scip);
1283 
1284    return pseudoactivity;
1285 }
1286 
1287 /** recompute the minactivity of a constraint */
1288 static
consdataRecomputeMinactivity(SCIP * scip,SCIP_CONSDATA * consdata)1289 void consdataRecomputeMinactivity(
1290    SCIP*                 scip,               /**< SCIP data structure */
1291    SCIP_CONSDATA*        consdata            /**< linear constraint data */
1292    )
1293 {
1294    int i;
1295    SCIP_Real bound;
1296 
1297    consdata->minactivity = 0;
1298 
1299    for( i = consdata->nvars - 1; i >= 0; --i )
1300    {
1301       bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1302       if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1303          && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1304          consdata->minactivity += consdata->vals[i] * bound;
1305    }
1306 
1307    /* the activity was just computed from scratch and is valid now */
1308    consdata->validminact = TRUE;
1309 
1310    /* the activity was just computed from scratch, mark it to be reliable */
1311    consdata->lastminactivity = consdata->minactivity;
1312 }
1313 
1314 /** recompute the maxactivity of a constraint */
1315 static
consdataRecomputeMaxactivity(SCIP * scip,SCIP_CONSDATA * consdata)1316 void consdataRecomputeMaxactivity(
1317    SCIP*                 scip,               /**< SCIP data structure */
1318    SCIP_CONSDATA*        consdata            /**< linear constraint data */
1319    )
1320 {
1321    int i;
1322    SCIP_Real bound;
1323 
1324    consdata->maxactivity = 0;
1325 
1326    for( i = consdata->nvars - 1; i >= 0; --i )
1327    {
1328       bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1329       if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1330          && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1331          consdata->maxactivity += consdata->vals[i] * bound;
1332    }
1333 
1334    /* the activity was just computed from scratch and is valid now */
1335    consdata->validmaxact = TRUE;
1336 
1337    /* the activity was just computed from scratch, mark it to be reliable */
1338    consdata->lastmaxactivity = consdata->maxactivity;
1339 }
1340 
1341 /** recompute the global minactivity of a constraint */
1342 static
consdataRecomputeGlbMinactivity(SCIP * scip,SCIP_CONSDATA * consdata)1343 void consdataRecomputeGlbMinactivity(
1344    SCIP*                 scip,               /**< SCIP data structure */
1345    SCIP_CONSDATA*        consdata            /**< linear constraint data */
1346    )
1347 {
1348    int i;
1349    SCIP_Real bound;
1350 
1351    consdata->glbminactivity = 0;
1352 
1353    for( i = consdata->nvars - 1; i >= 0; --i )
1354    {
1355       bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1356       if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1357          && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1358          consdata->glbminactivity += consdata->vals[i] * bound;
1359    }
1360 
1361    /* the activity was just computed from scratch and is valid now */
1362    consdata->validglbminact = TRUE;
1363 
1364    /* the activity was just computed from scratch, mark it to be reliable */
1365    consdata->lastglbminactivity = consdata->glbminactivity;
1366 }
1367 
1368 /** recompute the global maxactivity of a constraint */
1369 static
consdataRecomputeGlbMaxactivity(SCIP * scip,SCIP_CONSDATA * consdata)1370 void consdataRecomputeGlbMaxactivity(
1371    SCIP*                 scip,               /**< SCIP data structure */
1372    SCIP_CONSDATA*        consdata            /**< linear constraint data */
1373    )
1374 {
1375    int i;
1376    SCIP_Real bound;
1377 
1378    consdata->glbmaxactivity = 0;
1379 
1380    for( i = consdata->nvars - 1; i >= 0; --i )
1381    {
1382       bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1383       if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1384          && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1385          consdata->glbmaxactivity += consdata->vals[i] * bound;
1386    }
1387 
1388    /* the activity was just computed from scratch and is valid now */
1389    consdata->validglbmaxact = TRUE;
1390 
1391    /* the activity was just computed from scratch, mark it to be reliable */
1392    consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1393 }
1394 
1395 /** calculates maximum absolute value of coefficients */
1396 static
consdataCalcMaxAbsval(SCIP_CONSDATA * consdata)1397 void consdataCalcMaxAbsval(
1398    SCIP_CONSDATA*        consdata            /**< linear constraint data */
1399    )
1400 {
1401    SCIP_Real absval;
1402    int i;
1403 
1404    assert(consdata != NULL);
1405    assert(!consdata->validmaxabsval);
1406    assert(consdata->maxabsval >= SCIP_INVALID);
1407 
1408    consdata->validmaxabsval = TRUE;
1409    consdata->maxabsval = 0.0;
1410    for( i = 0; i < consdata->nvars; ++i )
1411    {
1412       absval = consdata->vals[i];
1413       absval = REALABS(absval);
1414       if( absval > consdata->maxabsval )
1415          consdata->maxabsval = absval;
1416    }
1417 }
1418 
1419 /** calculates minimum absolute value of coefficients */
1420 static
consdataCalcMinAbsval(SCIP_CONSDATA * consdata)1421 void consdataCalcMinAbsval(
1422    SCIP_CONSDATA*        consdata            /**< linear constraint data */
1423    )
1424 {
1425    SCIP_Real absval;
1426    int i;
1427 
1428    assert(consdata != NULL);
1429    assert(!consdata->validminabsval);
1430    assert(consdata->minabsval >= SCIP_INVALID);
1431 
1432    consdata->validminabsval = TRUE;
1433 
1434    if( consdata->nvars > 0 )
1435       consdata->minabsval = REALABS(consdata->vals[0]);
1436    else
1437       consdata->minabsval = 0.0;
1438 
1439    for( i = 1; i < consdata->nvars; ++i )
1440    {
1441       absval = consdata->vals[i];
1442       absval = REALABS(absval);
1443       if( absval < consdata->minabsval )
1444          consdata->minabsval = absval;
1445    }
1446 }
1447 
1448 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1449 static
consdataCheckNonbinvar(SCIP_CONSDATA * consdata)1450 void consdataCheckNonbinvar(
1451    SCIP_CONSDATA*        consdata            /**< linear constraint data */
1452    )
1453 {
1454    int v;
1455 
1456    assert(!consdata->hasnonbinvalid);
1457    consdata->hasnonbinvar = FALSE;
1458    consdata->hascontvar = FALSE;
1459 
1460    for( v = consdata->nvars - 1; v >= 0; --v )
1461    {
1462       SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1463 
1464       if( vartype != SCIP_VARTYPE_BINARY )
1465       {
1466          consdata->hasnonbinvar = TRUE;
1467 
1468          if( vartype == SCIP_VARTYPE_CONTINUOUS )
1469          {
1470             consdata->hascontvar = TRUE;
1471             break;
1472          }
1473       }
1474    }
1475    assert(consdata->hascontvar || v < 0);
1476 
1477    consdata->hasnonbinvalid = TRUE;
1478 }
1479 
1480 
1481 #ifdef CHECKMAXACTDELTA
1482 /** checks that the stored maximal activity delta (if not invalid) is correct */
1483 static
checkMaxActivityDelta(SCIP * scip,SCIP_CONSDATA * consdata)1484 void checkMaxActivityDelta(
1485    SCIP*                 scip,               /**< SCIP data structure */
1486    SCIP_CONSDATA*        consdata            /**< linear constraint data */
1487    )
1488 {
1489    if( consdata->maxactdelta != SCIP_INVALID )
1490    {
1491       SCIP_Real maxactdelta = 0.0;
1492       SCIP_Real domain;
1493       SCIP_Real delta;
1494       SCIP_Real lb;
1495       SCIP_Real ub;
1496       int v;
1497 
1498       for( v = consdata->nvars - 1; v >= 0; --v )
1499       {
1500          lb = SCIPvarGetLbLocal(consdata->vars[v]);
1501          ub = SCIPvarGetUbLocal(consdata->vars[v]);
1502 
1503          if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1504          {
1505             maxactdelta = SCIPinfinity(scip);
1506             break;
1507          }
1508 
1509          domain = ub - lb;
1510          delta = REALABS(consdata->vals[v]) * domain;
1511 
1512          if( delta > maxactdelta )
1513          {
1514             maxactdelta = delta;
1515          }
1516       }
1517       assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1518    }
1519 }
1520 #else
1521 #define checkMaxActivityDelta(scip, consdata) /**/
1522 #endif
1523 
1524 /** recompute maximal activity contribution for a single variable */
1525 static
consdataRecomputeMaxActivityDelta(SCIP * scip,SCIP_CONSDATA * consdata)1526 void consdataRecomputeMaxActivityDelta(
1527    SCIP*                 scip,               /**< SCIP data structure */
1528    SCIP_CONSDATA*        consdata            /**< linear constraint data */
1529    )
1530 {
1531    SCIP_Real delta;
1532    int v;
1533 
1534    consdata->maxactdelta = 0.0;
1535 
1536    if( !consdata->hasnonbinvalid )
1537       consdataCheckNonbinvar(consdata);
1538 
1539    /* easy case, the problem consists only of binary variables */
1540    if( !consdata->hasnonbinvar )
1541    {
1542       for( v = consdata->nvars - 1; v >= 0; --v )
1543       {
1544          if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1545          {
1546             delta = REALABS(consdata->vals[v]);
1547 
1548             if( delta > consdata->maxactdelta )
1549             {
1550                consdata->maxactdelta = delta;
1551                consdata->maxactdeltavar = consdata->vars[v];
1552             }
1553          }
1554       }
1555       return;
1556    }
1557 
1558    for( v = consdata->nvars - 1; v >= 0; --v )
1559    {
1560       SCIP_Real domain;
1561       SCIP_Real lb;
1562       SCIP_Real ub;
1563 
1564       lb = SCIPvarGetLbLocal(consdata->vars[v]);
1565       ub = SCIPvarGetUbLocal(consdata->vars[v]);
1566 
1567       if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1568       {
1569          consdata->maxactdelta = SCIPinfinity(scip);
1570          consdata->maxactdeltavar = consdata->vars[v];
1571          break;
1572       }
1573 
1574       domain = ub - lb;
1575       delta = REALABS(consdata->vals[v]) * domain;
1576 
1577       if( delta > consdata->maxactdelta )
1578       {
1579          consdata->maxactdelta = delta;
1580          consdata->maxactdeltavar = consdata->vars[v];
1581       }
1582    }
1583 }
1584 
1585 
1586 /** updates activities for a change in a bound */
1587 static
consdataUpdateActivities(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_VAR * var,SCIP_Real oldbound,SCIP_Real newbound,SCIP_Real val,SCIP_BOUNDTYPE boundtype,SCIP_Bool global,SCIP_Bool checkreliability)1588 void consdataUpdateActivities(
1589    SCIP*                 scip,               /**< SCIP data structure */
1590    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
1591    SCIP_VAR*             var,                /**< variable that has been changed; can be NULL for global bound changes */
1592    SCIP_Real             oldbound,           /**< old bound of variable */
1593    SCIP_Real             newbound,           /**< new bound of variable */
1594    SCIP_Real             val,                /**< coefficient of constraint entry */
1595    SCIP_BOUNDTYPE        boundtype,          /**< type of the bound change */
1596    SCIP_Bool             global,             /**< is it a global or a local bound change? */
1597    SCIP_Bool             checkreliability    /**< should the reliability of the recalculated activity be checked? */
1598    )
1599 {
1600    SCIP_Real* activity;
1601    SCIP_Real* lastactivity;
1602    int* activityposinf;
1603    int* activityneginf;
1604    int* activityposhuge;
1605    int* activityneghuge;
1606    SCIP_Real oldcontribution;
1607    SCIP_Real newcontribution;
1608    SCIP_Real delta;
1609    SCIP_Bool validact;
1610    SCIP_Bool finitenewbound;
1611    SCIP_Bool hugevalnewcont;
1612 
1613    assert(scip != NULL);
1614    assert(consdata != NULL);
1615    assert(global || (var != NULL));
1616    assert(consdata->validactivities);
1617    assert(consdata->minactivity < SCIP_INVALID);
1618    assert(consdata->maxactivity < SCIP_INVALID);
1619    assert(consdata->lastminactivity < SCIP_INVALID);
1620    assert(consdata->lastmaxactivity < SCIP_INVALID);
1621    assert(consdata->minactivityneginf >= 0);
1622    assert(consdata->minactivityposinf >= 0);
1623    assert(consdata->maxactivityneginf >= 0);
1624    assert(consdata->maxactivityposinf >= 0);
1625    assert(consdata->minactivityneghuge >= 0);
1626    assert(consdata->minactivityposhuge >= 0);
1627    assert(consdata->maxactivityneghuge >= 0);
1628    assert(consdata->maxactivityposhuge >= 0);
1629    assert(consdata->glbminactivity < SCIP_INVALID);
1630    assert(consdata->glbmaxactivity < SCIP_INVALID);
1631    assert(consdata->lastglbminactivity < SCIP_INVALID);
1632    assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1633    assert(consdata->glbminactivityneginf >= 0);
1634    assert(consdata->glbminactivityposinf >= 0);
1635    assert(consdata->glbmaxactivityneginf >= 0);
1636    assert(consdata->glbmaxactivityposinf >= 0);
1637    assert(consdata->glbminactivityneghuge >= 0);
1638    assert(consdata->glbminactivityposhuge >= 0);
1639    assert(consdata->glbmaxactivityneghuge >= 0);
1640    assert(consdata->glbmaxactivityposhuge >= 0);
1641 
1642    delta = 0.0;
1643 
1644    /* we are updating global activities */
1645    if( global )
1646    {
1647       /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1648        * lower bound + pos. coef: update minactivity
1649        * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1650        * upper bound + pos. coef: update maxactivity
1651        * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1652        */
1653       if( boundtype == SCIP_BOUNDTYPE_LOWER )
1654       {
1655          if( val > 0.0 )
1656          {
1657             activity = &(consdata->glbminactivity);
1658             lastactivity = &(consdata->lastglbminactivity);
1659             activityposinf = &(consdata->glbminactivityposinf);
1660             activityneginf = &(consdata->glbminactivityneginf);
1661             activityposhuge = &(consdata->glbminactivityposhuge);
1662             activityneghuge = &(consdata->glbminactivityneghuge);
1663             validact = consdata->validglbminact;
1664          }
1665          else
1666          {
1667             activity = &(consdata->glbmaxactivity);
1668             lastactivity = &(consdata->lastglbmaxactivity);
1669             activityposinf = &(consdata->glbmaxactivityneginf);
1670             activityneginf = &(consdata->glbmaxactivityposinf);
1671             activityposhuge = &(consdata->glbmaxactivityposhuge);
1672             activityneghuge = &(consdata->glbmaxactivityneghuge);
1673             validact = consdata->validglbmaxact;
1674          }
1675       }
1676       else
1677       {
1678          if( val > 0.0 )
1679          {
1680             activity = &(consdata->glbmaxactivity);
1681             lastactivity = &(consdata->lastglbmaxactivity);
1682             activityposinf = &(consdata->glbmaxactivityposinf);
1683             activityneginf = &(consdata->glbmaxactivityneginf);
1684             activityposhuge = &(consdata->glbmaxactivityposhuge);
1685             activityneghuge = &(consdata->glbmaxactivityneghuge);
1686             validact = consdata->validglbmaxact;
1687          }
1688          else
1689          {
1690             activity = &(consdata->glbminactivity);
1691             lastactivity = &(consdata->lastglbminactivity);
1692             activityposinf = &(consdata->glbminactivityneginf);
1693             activityneginf = &(consdata->glbminactivityposinf);
1694             activityposhuge = &(consdata->glbminactivityposhuge);
1695             activityneghuge = &(consdata->glbminactivityneghuge);
1696             validact = consdata->validglbminact;
1697          }
1698       }
1699    }
1700    /* we are updating local activities */
1701    else
1702    {
1703       /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1704        * lower bound + pos. coef: update minactivity
1705        * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1706        * upper bound + pos. coef: update maxactivity
1707        * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1708        */
1709       if( boundtype == SCIP_BOUNDTYPE_LOWER )
1710       {
1711          if( val > 0.0 )
1712          {
1713             activity = &(consdata->minactivity);
1714             lastactivity = &(consdata->lastminactivity);
1715             activityposinf = &(consdata->minactivityposinf);
1716             activityneginf = &(consdata->minactivityneginf);
1717             activityposhuge = &(consdata->minactivityposhuge);
1718             activityneghuge = &(consdata->minactivityneghuge);
1719             validact = consdata->validminact;
1720          }
1721          else
1722          {
1723             activity = &(consdata->maxactivity);
1724             lastactivity = &(consdata->lastmaxactivity);
1725             activityposinf = &(consdata->maxactivityneginf);
1726             activityneginf = &(consdata->maxactivityposinf);
1727             activityposhuge = &(consdata->maxactivityposhuge);
1728             activityneghuge = &(consdata->maxactivityneghuge);
1729             validact = consdata->validmaxact;
1730          }
1731       }
1732       else
1733       {
1734          if( val > 0.0 )
1735          {
1736             activity = &(consdata->maxactivity);
1737             lastactivity = &(consdata->lastmaxactivity);
1738             activityposinf = &(consdata->maxactivityposinf);
1739             activityneginf = &(consdata->maxactivityneginf);
1740             activityposhuge = &(consdata->maxactivityposhuge);
1741             activityneghuge = &(consdata->maxactivityneghuge);
1742             validact = consdata->validmaxact;
1743          }
1744          else
1745          {
1746             activity = &(consdata->minactivity);
1747             lastactivity = &(consdata->lastminactivity);
1748             activityposinf = &(consdata->minactivityneginf);
1749             activityneginf = &(consdata->minactivityposinf);
1750             activityposhuge = &(consdata->minactivityposhuge);
1751             activityneghuge = &(consdata->minactivityneghuge);
1752             validact = consdata->validminact;
1753          }
1754       }
1755    }
1756 
1757    oldcontribution = val * oldbound;
1758    newcontribution = val * newbound;
1759    hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1760    finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1761 
1762    if( SCIPisInfinity(scip, REALABS(oldbound)) )
1763    {
1764       /* old bound was +infinity */
1765       if( oldbound > 0.0 )
1766       {
1767          assert((*activityposinf) >= 1);
1768 
1769          /* we only have to do something if the new bound is not again +infinity */
1770          if( finitenewbound || newbound < 0.0 )
1771          {
1772             /* decrease the counter for positive infinite contributions */
1773             (*activityposinf)--;
1774 
1775             /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1776             if( !finitenewbound && newbound < 0.0 )
1777                (*activityneginf)++;
1778             else if( hugevalnewcont )
1779             {
1780                /* if the contribution of this variable is too large, increase the counter for huge values */
1781                if( newcontribution > 0.0 )
1782                   (*activityposhuge)++;
1783                else
1784                   (*activityneghuge)++;
1785             }
1786             /* "normal case": just add the contribution to the activity */
1787             else
1788                delta = newcontribution;
1789          }
1790       }
1791       /* old bound was -infinity */
1792       else
1793       {
1794          assert(oldbound < 0.0);
1795          assert((*activityneginf) >= 1);
1796 
1797          /* we only have to do something ig the new bound is not again -infinity */
1798          if( finitenewbound || newbound > 0.0 )
1799          {
1800             /* decrease the counter for negative infinite contributions */
1801             (*activityneginf)--;
1802 
1803             /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1804             if( !finitenewbound && newbound > 0.0 )
1805                (*activityposinf)++;
1806             else if( hugevalnewcont )
1807             {
1808                /* if the contribution of this variable is too large, increase the counter for huge values */
1809                if( newcontribution > 0.0 )
1810                   (*activityposhuge)++;
1811                else
1812                   (*activityneghuge)++;
1813             }
1814             /* "normal case": just add the contribution to the activity */
1815             else
1816                delta = newcontribution;
1817          }
1818       }
1819    }
1820    else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1821    {
1822       /* old contribution was too large and positive */
1823       if( oldcontribution > 0.0 )
1824       {
1825          assert((*activityposhuge) >= 1);
1826 
1827          /* decrease the counter for huge positive contributions; it might be increased again later,
1828           * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1829           */
1830          (*activityposhuge)--;
1831 
1832          if( !finitenewbound )
1833          {
1834             /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1835             if( newbound > 0.0 )
1836                (*activityposinf)++;
1837             /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1838             else
1839                (*activityneginf)++;
1840          }
1841          else if( hugevalnewcont )
1842          {
1843             /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1844             if( newcontribution > 0.0 )
1845                (*activityposhuge)++;
1846             /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1847             else
1848                (*activityneghuge)++;
1849          }
1850          /* "normal case": just add the contribution to the activity */
1851          else
1852             delta = newcontribution;
1853       }
1854       /* old contribution was too large and negative */
1855       else
1856       {
1857          assert(oldcontribution < 0.0);
1858          assert((*activityneghuge) >= 1);
1859 
1860          /* decrease the counter for huge negative contributions; it might be increased again later,
1861           * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1862           */
1863          (*activityneghuge)--;
1864 
1865          if( !finitenewbound )
1866          {
1867             /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1868             if( newbound > 0.0 )
1869                (*activityposinf)++;
1870             /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1871             else
1872                (*activityneginf)++;
1873          }
1874          else if( hugevalnewcont )
1875          {
1876             /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1877             if( newcontribution > 0.0 )
1878                (*activityposhuge)++;
1879             /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1880             else
1881                (*activityneghuge)++;
1882          }
1883          /* "normal case": just add the contribution to the activity */
1884          else
1885             delta = newcontribution;
1886       }
1887    }
1888    /* old bound was finite and not too large */
1889    else
1890    {
1891       if( !finitenewbound )
1892       {
1893          /* if the new bound is +infinity, the old contribution has to be subtracted
1894           * and the counter for positive infinite contributions has to be increased
1895           */
1896          if( newbound > 0.0 )
1897          {
1898             (*activityposinf)++;
1899             delta = -oldcontribution;
1900          }
1901          /* if the new bound is -infinity, the old contribution has to be subtracted
1902           * and the counter for negative infinite contributions has to be increased
1903           */
1904          else
1905          {
1906             assert(newbound < 0.0 );
1907 
1908             (*activityneginf)++;
1909             delta = -oldcontribution;
1910          }
1911       }
1912       /* if the contribution of this variable is too large, increase the counter for huge values */
1913       else if( hugevalnewcont )
1914       {
1915          if( newcontribution > 0.0 )
1916          {
1917             (*activityposhuge)++;
1918             delta = -oldcontribution;
1919          }
1920          else
1921          {
1922             (*activityneghuge)++;
1923             delta = -oldcontribution;
1924          }
1925       }
1926       /* "normal case": just update the activity */
1927       else
1928          delta = newcontribution - oldcontribution;
1929    }
1930 
1931    /* update the activity, if the current value is valid and there was a change in the finite part */
1932    if( validact && (delta != 0.0) )
1933    {
1934       /* if the absolute value of the activity is increased, this is regarded as reliable,
1935        * otherwise, we check whether we can still trust the updated value
1936        */
1937       (*activity) = (*activity) + delta;
1938       assert(!SCIPisInfinity(scip, -(*activity)) && !SCIPisInfinity(scip, *activity));
1939 
1940       if( REALABS((*lastactivity)) < REALABS(*activity) )
1941       {
1942          (*lastactivity) = (*activity);
1943       }
1944       else
1945       {
1946          if( checkreliability && SCIPisUpdateUnreliable(scip, (*activity), (*lastactivity)) )
1947          {
1948             SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1949                (global ? "global " : ""), (*activity));
1950 
1951             /* mark the activity that was just changed and is not reliable anymore to be invalid */
1952             if( global )
1953             {
1954                if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1955                   consdata->validglbminact = FALSE;
1956                else
1957                   consdata->validglbmaxact = FALSE;
1958             }
1959             else
1960             {
1961                if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1962                   consdata->validminact = FALSE;
1963                else
1964                   consdata->validmaxact = FALSE;
1965             }
1966          }
1967       }
1968    }
1969 }
1970 
1971 /** updates minimum and maximum activity for a change in lower bound */
1972 static
consdataUpdateActivitiesLb(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_VAR * var,SCIP_Real oldlb,SCIP_Real newlb,SCIP_Real val,SCIP_Bool checkreliability)1973 void consdataUpdateActivitiesLb(
1974    SCIP*                 scip,               /**< SCIP data structure */
1975    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
1976    SCIP_VAR*             var,                /**< variable that has been changed */
1977    SCIP_Real             oldlb,              /**< old lower bound of variable */
1978    SCIP_Real             newlb,              /**< new lower bound of variable */
1979    SCIP_Real             val,                /**< coefficient of constraint entry */
1980    SCIP_Bool             checkreliability    /**< should the reliability of the recalculated activity be checked? */
1981    )
1982 {
1983    assert(scip != NULL);
1984    assert(consdata != NULL);
1985    assert(var != NULL);
1986 
1987    if( consdata->validactivities )
1988    {
1989       consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
1990 
1991       assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1992       assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1993    }
1994 }
1995 
1996 /** updates minimum and maximum activity for a change in upper bound */
1997 static
consdataUpdateActivitiesUb(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_VAR * var,SCIP_Real oldub,SCIP_Real newub,SCIP_Real val,SCIP_Bool checkreliability)1998 void consdataUpdateActivitiesUb(
1999    SCIP*                 scip,               /**< SCIP data structure */
2000    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
2001    SCIP_VAR*             var,                /**< variable that has been changed */
2002    SCIP_Real             oldub,              /**< old upper bound of variable */
2003    SCIP_Real             newub,              /**< new upper bound of variable */
2004    SCIP_Real             val,                /**< coefficient of constraint entry */
2005    SCIP_Bool             checkreliability    /**< should the reliability of the recalculated activity be checked? */
2006    )
2007 {
2008    assert(scip != NULL);
2009    assert(consdata != NULL);
2010    assert(var != NULL);
2011 
2012    if( consdata->validactivities )
2013    {
2014       consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
2015 
2016       assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
2017       assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
2018    }
2019 }
2020 
2021 /** updates minimum and maximum global activity for a change in the global lower bound */
2022 static
consdataUpdateActivitiesGlbLb(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_Real oldlb,SCIP_Real newlb,SCIP_Real val,SCIP_Bool checkreliability)2023 void consdataUpdateActivitiesGlbLb(
2024    SCIP*                 scip,               /**< SCIP data structure */
2025    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
2026    SCIP_Real             oldlb,              /**< old lower bound of variable */
2027    SCIP_Real             newlb,              /**< new lower bound of variable */
2028    SCIP_Real             val,                /**< coefficient of constraint entry */
2029    SCIP_Bool             checkreliability    /**< should the reliability of the recalculated activity be checked? */
2030    )
2031 {
2032    assert(scip != NULL);
2033    assert(consdata != NULL);
2034 
2035    if( consdata->validactivities )
2036    {
2037       consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
2038 
2039       assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2040       assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2041    }
2042 }
2043 
2044 /** updates minimum and maximum global activity for a change in global upper bound */
2045 static
consdataUpdateActivitiesGlbUb(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_Real oldub,SCIP_Real newub,SCIP_Real val,SCIP_Bool checkreliability)2046 void consdataUpdateActivitiesGlbUb(
2047    SCIP*                 scip,               /**< SCIP data structure */
2048    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
2049    SCIP_Real             oldub,              /**< old upper bound of variable */
2050    SCIP_Real             newub,              /**< new upper bound of variable */
2051    SCIP_Real             val,                /**< coefficient of constraint entry */
2052    SCIP_Bool             checkreliability    /**< should the reliability of the recalculated activity be checked? */
2053    )
2054 {
2055    assert(scip != NULL);
2056    assert(consdata != NULL);
2057 
2058    if( consdata->validactivities )
2059    {
2060       consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
2061 
2062       assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
2063       assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
2064    }
2065 }
2066 
2067 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
2068 static
consdataUpdateAddCoef(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_VAR * var,SCIP_Real val,SCIP_Bool checkreliability)2069 void consdataUpdateAddCoef(
2070    SCIP*                 scip,               /**< SCIP data structure */
2071    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
2072    SCIP_VAR*             var,                /**< variable of constraint entry */
2073    SCIP_Real             val,                /**< coefficient of constraint entry */
2074    SCIP_Bool             checkreliability    /**< should the reliability of the recalculated activity be checked? */
2075    )
2076 {
2077    assert(scip != NULL);
2078    assert(consdata != NULL);
2079    assert(var != NULL);
2080 
2081    /* update maximum absolute value */
2082    if( consdata->validmaxabsval )
2083    {
2084       SCIP_Real absval;
2085 
2086       assert(consdata->maxabsval < SCIP_INVALID);
2087 
2088       absval = REALABS(val);
2089       consdata->maxabsval = MAX(consdata->maxabsval, absval);
2090    }
2091 
2092    if( consdata->validminabsval )
2093    {
2094       SCIP_Real absval;
2095 
2096       assert(consdata->minabsval < SCIP_INVALID);
2097 
2098       absval = REALABS(val);
2099       consdata->minabsval = MIN(consdata->minabsval, absval);
2100    }
2101 
2102    /* update minimal and maximal activity */
2103    if( consdata->validactivities )
2104    {
2105       assert(consdata->minactivity < SCIP_INVALID);
2106       assert(consdata->maxactivity < SCIP_INVALID);
2107       assert(consdata->glbminactivity < SCIP_INVALID);
2108       assert(consdata->glbmaxactivity < SCIP_INVALID);
2109 
2110       consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2111       consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2112       consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2113       consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2114    }
2115 }
2116 
2117 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2118 static
consdataUpdateDelCoef(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_VAR * var,SCIP_Real val,SCIP_Bool checkreliability)2119 void consdataUpdateDelCoef(
2120    SCIP*                 scip,               /**< SCIP data structure */
2121    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
2122    SCIP_VAR*             var,                /**< variable of constraint entry */
2123    SCIP_Real             val,                /**< coefficient of constraint entry */
2124    SCIP_Bool             checkreliability    /**< should the reliability of the recalculated activity be checked? */
2125    )
2126 {
2127    assert(scip != NULL);
2128    assert(consdata != NULL);
2129    assert(var != NULL);
2130 
2131    /* invalidate maximum absolute value, if this coefficient was the maximum */
2132    if( consdata->validmaxabsval )
2133    {
2134       SCIP_Real absval;
2135 
2136       absval = REALABS(val);
2137 
2138       if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2139       {
2140          consdata->validmaxabsval = FALSE;
2141          consdata->maxabsval = SCIP_INVALID;
2142       }
2143    }
2144 
2145    /* invalidate minimum absolute value, if this coefficient was the minimum */
2146    if( consdata->validminabsval )
2147    {
2148       SCIP_Real absval;
2149 
2150       absval = REALABS(val);
2151 
2152       if( SCIPisEQ(scip, absval, consdata->minabsval) )
2153       {
2154          consdata->validminabsval = FALSE;
2155          consdata->minabsval = SCIP_INVALID;
2156       }
2157    }
2158 
2159    /* update minimal and maximal activity */
2160    if( consdata->validactivities )
2161    {
2162       assert(consdata->minactivity < SCIP_INVALID);
2163       assert(consdata->maxactivity < SCIP_INVALID);
2164       assert(consdata->glbminactivity < SCIP_INVALID);
2165       assert(consdata->glbmaxactivity < SCIP_INVALID);
2166 
2167       consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2168       consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2169       consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2170       consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2171    }
2172 }
2173 
2174 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2175 static
consdataUpdateChgCoef(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_VAR * var,SCIP_Real oldval,SCIP_Real newval,SCIP_Bool checkreliability)2176 void consdataUpdateChgCoef(
2177    SCIP*                 scip,               /**< SCIP data structure */
2178    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
2179    SCIP_VAR*             var,                /**< variable of constraint entry */
2180    SCIP_Real             oldval,             /**< old coefficient of constraint entry */
2181    SCIP_Real             newval,             /**< new coefficient of constraint entry */
2182    SCIP_Bool             checkreliability    /**< should the reliability of the recalculated activity be checked? */
2183    )
2184 {
2185    assert(scip != NULL);
2186    assert(consdata != NULL);
2187    assert(var != NULL);
2188 
2189    /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2190    assert(!SCIPisZero(scip, oldval));
2191 
2192    /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2193    assert(!SCIPisZero(scip, newval));
2194 
2195    /* update maximum absolute value */
2196    if( consdata->validmaxabsval )
2197    {
2198       SCIP_Real absval;
2199 
2200       absval = REALABS(newval);
2201 
2202       if( SCIPisGE(scip, absval, consdata->maxabsval) )
2203       {
2204          consdata->maxabsval = absval;
2205       }
2206       else
2207       {
2208          absval = REALABS(oldval);
2209 
2210          /* invalidate maximum absolute value */
2211          if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2212          {
2213             consdata->validmaxabsval = FALSE;
2214             consdata->maxabsval = SCIP_INVALID;
2215          }
2216       }
2217    }
2218 
2219    /* update minimum absolute value */
2220    if( consdata->validminabsval )
2221    {
2222       SCIP_Real absval;
2223 
2224       absval = REALABS(newval);
2225 
2226       if( SCIPisLE(scip, absval, consdata->minabsval) )
2227       {
2228          consdata->minabsval = absval;
2229       }
2230       else
2231       {
2232          absval = REALABS(oldval);
2233 
2234          /* invalidate minimum absolute value */
2235          if( SCIPisEQ(scip, absval, consdata->minabsval) )
2236          {
2237             consdata->validminabsval = FALSE;
2238             consdata->minabsval = SCIP_INVALID;
2239          }
2240       }
2241    }
2242 
2243    /* update maximum activity delta */
2244    if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2245    {
2246       SCIP_Real domain;
2247       SCIP_Real delta;
2248 
2249       assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
2250       assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
2251 
2252       domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
2253       delta = REALABS(newval) * domain;
2254 
2255       if( delta > consdata->maxactdelta )
2256       {
2257          consdata->maxactdelta = delta;
2258          consdata->maxactdeltavar = var;
2259       }
2260       else
2261       {
2262          /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2263          if( consdata->maxactdeltavar == var )
2264             consdata->maxactdelta = SCIP_INVALID;
2265       }
2266    }
2267 
2268    /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2269    consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2270    consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2271 }
2272 
2273 /** returns the maximum absolute value of all coefficients in the constraint */
2274 static
consdataGetMaxAbsval(SCIP_CONSDATA * consdata)2275 SCIP_Real consdataGetMaxAbsval(
2276    SCIP_CONSDATA*        consdata            /**< linear constraint data */
2277    )
2278 {
2279    assert(consdata != NULL);
2280 
2281    if( !consdata->validmaxabsval )
2282       consdataCalcMaxAbsval(consdata);
2283    assert(consdata->validmaxabsval);
2284    assert(consdata->maxabsval < SCIP_INVALID);
2285 
2286    return consdata->maxabsval;
2287 }
2288 
2289 /** returns the minimum absolute value of all coefficients in the constraint */
2290 static
consdataGetMinAbsval(SCIP_CONSDATA * consdata)2291 SCIP_Real consdataGetMinAbsval(
2292    SCIP_CONSDATA*        consdata            /**< linear constraint data */
2293    )
2294 {
2295    assert(consdata != NULL);
2296 
2297    if( !consdata->validminabsval )
2298       consdataCalcMinAbsval(consdata);
2299    assert(consdata->validminabsval);
2300    assert(consdata->minabsval < SCIP_INVALID);
2301 
2302    return consdata->minabsval;
2303 }
2304 
2305 /** calculates minimum and maximum local and global activity for constraint from scratch;
2306  *  additionally recalculates maximum absolute value of coefficients
2307  */
2308 static
consdataCalcActivities(SCIP * scip,SCIP_CONSDATA * consdata)2309 void consdataCalcActivities(
2310    SCIP*                 scip,               /**< SCIP data structure */
2311    SCIP_CONSDATA*        consdata            /**< linear constraint data */
2312    )
2313 {
2314    int i;
2315 
2316    assert(scip != NULL);
2317    assert(consdata != NULL);
2318    assert(!consdata->validactivities);
2319    assert(consdata->minactivity >= SCIP_INVALID || consdata->validminact);
2320    assert(consdata->maxactivity >= SCIP_INVALID || consdata->validmaxact);
2321    assert(consdata->glbminactivity >= SCIP_INVALID || consdata->validglbminact);
2322    assert(consdata->glbmaxactivity >= SCIP_INVALID || consdata->validglbmaxact);
2323 
2324    consdata->validmaxabsval = TRUE;
2325    consdata->validminabsval = TRUE;
2326    consdata->validactivities = TRUE;
2327    consdata->validminact = TRUE;
2328    consdata->validmaxact = TRUE;
2329    consdata->validglbminact = TRUE;
2330    consdata->validglbmaxact = TRUE;
2331    consdata->maxabsval = 0.0;
2332    consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2333    consdata->minactivity = 0.0;
2334    consdata->maxactivity = 0.0;
2335    consdata->lastminactivity = 0.0;
2336    consdata->lastmaxactivity = 0.0;
2337    consdata->minactivityneginf = 0;
2338    consdata->minactivityposinf = 0;
2339    consdata->maxactivityneginf = 0;
2340    consdata->maxactivityposinf = 0;
2341    consdata->minactivityneghuge = 0;
2342    consdata->minactivityposhuge = 0;
2343    consdata->maxactivityneghuge = 0;
2344    consdata->maxactivityposhuge = 0;
2345    consdata->glbminactivity = 0.0;
2346    consdata->glbmaxactivity = 0.0;
2347    consdata->lastglbminactivity = 0.0;
2348    consdata->lastglbmaxactivity = 0.0;
2349    consdata->glbminactivityneginf = 0;
2350    consdata->glbminactivityposinf = 0;
2351    consdata->glbmaxactivityneginf = 0;
2352    consdata->glbmaxactivityposinf = 0;
2353    consdata->glbminactivityneghuge = 0;
2354    consdata->glbminactivityposhuge = 0;
2355    consdata->glbmaxactivityneghuge = 0;
2356    consdata->glbmaxactivityposhuge = 0;
2357 
2358    for( i = 0; i < consdata->nvars; ++i )
2359       consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2360 
2361    consdata->lastminactivity = consdata->minactivity;
2362    consdata->lastmaxactivity = consdata->maxactivity;
2363    consdata->lastglbminactivity = consdata->glbminactivity;
2364    consdata->lastglbmaxactivity = consdata->glbmaxactivity;
2365 }
2366 
2367 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2368  *  and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2369  */
2370 static
getMinActivity(SCIP * scip,SCIP_CONSDATA * consdata,int posinf,int neginf,int poshuge,int neghuge,SCIP_Real delta,SCIP_Bool global,SCIP_Bool goodrelax,SCIP_Real * minactivity,SCIP_Bool * isrelax,SCIP_Bool * issettoinfinity)2371 void getMinActivity(
2372    SCIP*                 scip,               /**< SCIP data structure */
2373    SCIP_CONSDATA*        consdata,           /**< linear constraint */
2374    int                   posinf,             /**< number of coefficients contributing pos. infinite value */
2375    int                   neginf,             /**< number of coefficients contributing neg. infinite value */
2376    int                   poshuge,            /**< number of coefficients contributing huge pos. value */
2377    int                   neghuge,            /**< number of coefficients contributing huge neg. value */
2378    SCIP_Real             delta,              /**< value to subtract from stored minactivity
2379                                               *   (contribution of the variable set to zero when getting residual activity) */
2380    SCIP_Bool             global,             /**< should the global or local minimal activity be returned? */
2381    SCIP_Bool             goodrelax,          /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2382    SCIP_Real*            minactivity,        /**< pointer to store the minimal activity */
2383    SCIP_Bool*            isrelax,            /**< pointer to store whether the activity is a relaxation,
2384                                               *   i.e. is <= the exact minactivity (in case of huge contributing values) */
2385    SCIP_Bool*            issettoinfinity     /**< pointer to store whether minactivity was set to infinity or calculated */
2386    )
2387 {
2388    assert(scip != NULL);
2389    assert(consdata != NULL);
2390    assert(posinf >= 0);
2391    assert(neginf >= 0);
2392    assert(poshuge >= 0);
2393    assert(neghuge >= 0);
2394    assert(minactivity != NULL);
2395    assert(isrelax != NULL);
2396    assert(issettoinfinity != NULL);
2397 
2398    /* if we have pos. infinite contributions, the minactivity is +infty */
2399    if( posinf > 0 )
2400    {
2401       *minactivity = SCIPinfinity(scip);
2402       *issettoinfinity = TRUE;
2403       *isrelax = FALSE;
2404    }
2405    /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2406    else if( neginf > 0 )
2407    {
2408       *minactivity = -SCIPinfinity(scip);
2409       *issettoinfinity = TRUE;
2410       *isrelax = FALSE;
2411    }
2412    /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2413    else if( neghuge > 0 )
2414    {
2415       *minactivity = -SCIPinfinity(scip);
2416       *issettoinfinity = TRUE;
2417       *isrelax = TRUE;
2418    }
2419    /* we do not need a good relaxation and we have positive huge contributions, so we just return -infty as activity */
2420    else if( !goodrelax && poshuge > 0 )
2421    {
2422       *minactivity = -SCIPinfinity(scip);
2423       *issettoinfinity = TRUE;
2424       *isrelax = TRUE;
2425    }
2426    else
2427    {
2428       SCIP_Real tmpactivity;
2429 
2430       /* recompute minactivity if it is not valid */
2431       if( global )
2432       {
2433          if( !consdata->validglbminact )
2434             consdataRecomputeGlbMinactivity(scip, consdata);
2435          assert(consdata->validglbminact);
2436 
2437          tmpactivity = consdata->glbminactivity;
2438       }
2439       else
2440       {
2441          if( !consdata->validminact )
2442             consdataRecomputeMinactivity(scip, consdata);
2443          assert(consdata->validminact);
2444 
2445          tmpactivity = consdata->minactivity;
2446       }
2447 
2448       /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2449        * a feasible relaxation of the minactivity is the number of positive huge contributions
2450        * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2451        */
2452       if( poshuge > 0 )
2453       {
2454          *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2455          *issettoinfinity = FALSE;
2456          *isrelax = TRUE;
2457       }
2458       /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2459       else
2460       {
2461          *minactivity = tmpactivity - delta;
2462          *issettoinfinity = FALSE;
2463          *isrelax = FALSE;
2464       }
2465    }
2466 }
2467 
2468 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2469  *  and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2470  */
2471 static
getMaxActivity(SCIP * scip,SCIP_CONSDATA * consdata,int posinf,int neginf,int poshuge,int neghuge,SCIP_Real delta,SCIP_Bool global,SCIP_Bool goodrelax,SCIP_Real * maxactivity,SCIP_Bool * isrelax,SCIP_Bool * issettoinfinity)2472 void getMaxActivity(
2473    SCIP*                 scip,               /**< SCIP data structure */
2474    SCIP_CONSDATA*        consdata,           /**< linear constraint */
2475    int                   posinf,             /**< number of coefficients contributing pos. infinite value */
2476    int                   neginf,             /**< number of coefficients contributing neg. infinite value */
2477    int                   poshuge,            /**< number of coefficients contributing huge pos. value */
2478    int                   neghuge,            /**< number of coefficients contributing huge neg. value */
2479    SCIP_Real             delta,              /**< value to subtract from stored maxactivity
2480                                               *   (contribution of the variable set to zero when getting residual activity) */
2481    SCIP_Bool             global,             /**< should the global or local maximal activity be returned? */
2482    SCIP_Bool             goodrelax,          /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2483    SCIP_Real*            maxactivity,        /**< pointer to store the maximal activity */
2484    SCIP_Bool*            isrelax,            /**< pointer to store whether the activity is a relaxation,
2485                                               *   i.e. is >= the exact maxactivity (in case of huge contributing values) */
2486    SCIP_Bool*            issettoinfinity     /**< pointer to store whether maxactivity was set to infinity or calculated */
2487    )
2488 {
2489    assert(scip != NULL);
2490    assert(consdata != NULL);
2491    assert(posinf >= 0);
2492    assert(neginf >= 0);
2493    assert(poshuge >= 0);
2494    assert(neghuge >= 0);
2495    assert(maxactivity != NULL);
2496    assert(isrelax != NULL);
2497    assert(issettoinfinity != NULL);
2498 
2499    /* if we have neg. infinite contributions, the maxactivity is -infty */
2500    if( neginf > 0 )
2501    {
2502       *maxactivity = -SCIPinfinity(scip);
2503       *issettoinfinity = TRUE;
2504       *isrelax = FALSE;
2505    }
2506    /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2507    else if( posinf > 0 )
2508    {
2509       *maxactivity = SCIPinfinity(scip);
2510       *issettoinfinity = TRUE;
2511       *isrelax = FALSE;
2512    }
2513    /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2514    else if( poshuge > 0 )
2515    {
2516       *maxactivity = SCIPinfinity(scip);
2517       *issettoinfinity = TRUE;
2518       *isrelax = TRUE;
2519    }
2520    /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2521    else if( !goodrelax && neghuge > 0 )
2522    {
2523       *maxactivity = SCIPinfinity(scip);
2524       *issettoinfinity = TRUE;
2525       *isrelax = TRUE;
2526    }
2527    else
2528    {
2529       SCIP_Real tmpactivity;
2530 
2531       /* recompute maxactivity if it is not valid */
2532       if( global )
2533       {
2534          if( !consdata->validglbmaxact )
2535             consdataRecomputeGlbMaxactivity(scip, consdata);
2536          assert(consdata->validglbmaxact);
2537 
2538          tmpactivity = consdata->glbmaxactivity;
2539       }
2540       else
2541       {
2542          if( !consdata->validmaxact )
2543             consdataRecomputeMaxactivity(scip, consdata);
2544          assert(consdata->validmaxact);
2545 
2546          tmpactivity = consdata->maxactivity;
2547       }
2548 
2549       /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2550        * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2551        * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2552        */
2553       if( neghuge > 0 )
2554       {
2555          *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2556          *issettoinfinity = FALSE;
2557          *isrelax = TRUE;
2558       }
2559       /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2560       else
2561       {
2562          *maxactivity = tmpactivity - delta;
2563          *issettoinfinity = FALSE;
2564          *isrelax = FALSE;
2565       }
2566    }
2567 }
2568 
2569 /** gets activity bounds for constraint */
2570 static
consdataGetActivityBounds(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_Bool goodrelax,SCIP_Real * minactivity,SCIP_Real * maxactivity,SCIP_Bool * minisrelax,SCIP_Bool * maxisrelax,SCIP_Bool * isminsettoinfinity,SCIP_Bool * ismaxsettoinfinity)2571 void consdataGetActivityBounds(
2572    SCIP*                 scip,               /**< SCIP data structure */
2573    SCIP_CONSDATA*        consdata,           /**< linear constraint */
2574    SCIP_Bool             goodrelax,          /**< if we have huge contributions, do we need a good relaxation or are
2575                                               *   relaxed activities ignored, anyway? */
2576    SCIP_Real*            minactivity,        /**< pointer to store the minimal activity */
2577    SCIP_Real*            maxactivity,        /**< pointer to store the maximal activity */
2578    SCIP_Bool*            minisrelax,         /**< pointer to store whether the returned minactivity is just a relaxation,
2579                                               *   i.e. <= the exact minactivity (in case of huge contributions),
2580                                               *   or equal to the exact minimal activity */
2581    SCIP_Bool*            maxisrelax,         /**< pointer to store whether the returned maxactivity is just a relaxation,
2582                                               *   i.e. >= the exact maxactivity (in case of huge contributions),
2583                                               *   or equal to the exact maximal activity */
2584    SCIP_Bool*            isminsettoinfinity, /**< pointer to store whether minactivity was set to infinity or calculated */
2585    SCIP_Bool*            ismaxsettoinfinity  /**< pointer to store whether maxactivity was set to infinity or calculated */
2586 
2587    )
2588 {
2589    assert(scip != NULL);
2590    assert(consdata != NULL);
2591    assert(minactivity != NULL);
2592    assert(maxactivity != NULL);
2593    assert(isminsettoinfinity != NULL);
2594    assert(ismaxsettoinfinity != NULL);
2595 
2596    if( !consdata->validactivities )
2597    {
2598       consdataCalcActivities(scip, consdata);
2599       assert(consdata->validminact);
2600       assert(consdata->validmaxact);
2601    }
2602    assert(consdata->minactivity < SCIP_INVALID);
2603    assert(consdata->maxactivity < SCIP_INVALID);
2604    assert(consdata->minactivityneginf >= 0);
2605    assert(consdata->minactivityposinf >= 0);
2606    assert(consdata->maxactivityneginf >= 0);
2607    assert(consdata->maxactivityposinf >= 0);
2608 
2609    getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2610       consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2611       minactivity, minisrelax, isminsettoinfinity);
2612 
2613    getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2614       consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2615       maxactivity, maxisrelax, ismaxsettoinfinity);
2616 }
2617 
2618 /** calculates activity bounds for constraint after setting variable to zero */
2619 static
consdataGetReliableResidualActivity(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_VAR * cancelvar,SCIP_Real * resactivity,SCIP_Bool isminresact,SCIP_Bool useglobalbounds)2620 void consdataGetReliableResidualActivity(
2621    SCIP*                 scip,               /**< SCIP data structure */
2622    SCIP_CONSDATA*        consdata,           /**< linear constraint */
2623    SCIP_VAR*             cancelvar,          /**< variable to calculate activity residual for */
2624    SCIP_Real*            resactivity,        /**< pointer to store the residual activity */
2625    SCIP_Bool             isminresact,        /**< should minimal or maximal residual activity be calculated? */
2626    SCIP_Bool             useglobalbounds     /**< should global or local bounds be used? */
2627    )
2628 {
2629    SCIP_VAR* var;
2630    SCIP_Real val;
2631    SCIP_Real lb;
2632    SCIP_Real ub;
2633    int v;
2634 
2635    assert(scip != NULL);
2636    assert(consdata != NULL);
2637    assert(cancelvar != NULL);
2638    assert(resactivity != NULL);
2639 
2640    *resactivity = 0.0;
2641 
2642    for( v = 0; v < consdata->nvars; ++v )
2643    {
2644       var = consdata->vars[v];
2645       assert(var != NULL);
2646       if( var == cancelvar )
2647          continue;
2648 
2649       val = consdata->vals[v];
2650 
2651       if( useglobalbounds )
2652       {
2653          lb = SCIPvarGetLbGlobal(var);
2654          ub = SCIPvarGetUbGlobal(var);
2655       }
2656       else
2657       {
2658          lb = SCIPvarGetLbLocal(var);
2659          ub = SCIPvarGetUbLocal(var);
2660       }
2661 
2662       assert(!SCIPisZero(scip, val));
2663       assert(SCIPisLE(scip, lb, ub));
2664 
2665       if( val > 0.0 )
2666       {
2667          if( isminresact )
2668          {
2669             assert(!SCIPisInfinity(scip, -lb));
2670             assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2671             *resactivity += val*lb;
2672          }
2673          else
2674          {
2675             assert(!SCIPisInfinity(scip, ub));
2676             assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2677             *resactivity += val*ub;
2678          }
2679       }
2680       else
2681       {
2682          if( isminresact)
2683          {
2684             assert(!SCIPisInfinity(scip, ub));
2685             assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2686             *resactivity += val*ub;
2687          }
2688          else
2689          {
2690             assert(!SCIPisInfinity(scip, -lb));
2691             assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2692             *resactivity += val*lb;
2693          }
2694       }
2695    }
2696    assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2697 }
2698 
2699 /** gets activity bounds for constraint after setting variable to zero */
2700 static
consdataGetActivityResiduals(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_VAR * var,SCIP_Real val,SCIP_Bool goodrelax,SCIP_Real * minresactivity,SCIP_Real * maxresactivity,SCIP_Bool * minisrelax,SCIP_Bool * maxisrelax,SCIP_Bool * isminsettoinfinity,SCIP_Bool * ismaxsettoinfinity)2701 void consdataGetActivityResiduals(
2702    SCIP*                 scip,               /**< SCIP data structure */
2703    SCIP_CONSDATA*        consdata,           /**< linear constraint */
2704    SCIP_VAR*             var,                /**< variable to calculate activity residual for */
2705    SCIP_Real             val,                /**< coefficient value of variable in linear constraint */
2706    SCIP_Bool             goodrelax,          /**< if we have huge contributions, do we need a good relaxation or are
2707                                               *   relaxed acticities ignored, anyway? */
2708    SCIP_Real*            minresactivity,     /**< pointer to store the minimal residual activity */
2709    SCIP_Real*            maxresactivity,     /**< pointer to store the maximal residual activity */
2710    SCIP_Bool*            minisrelax,         /**< pointer to store whether the returned residual minactivity is just a
2711                                               *   relaxation, i.e. <= the exact residual minactivity (in case of huge
2712                                               *   contributions), or equal to the exact residual minactivity */
2713    SCIP_Bool*            maxisrelax,         /**< pointer to store whether the returned residual maxactivity is just a
2714                                               *   relaxation, i.e. <= the exact residual maxactivity (in case of huge
2715                                               *   contributions), or equal to the exact residual minactivity */
2716    SCIP_Bool*            isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2717    SCIP_Bool*            ismaxsettoinfinity  /**< pointer to store whether maxresactivity was set to infinity or calculated */
2718    )
2719 {
2720    SCIP_Real minactbound;
2721    SCIP_Real maxactbound;
2722    SCIP_Real absval;
2723 
2724    assert(scip != NULL);
2725    assert(consdata != NULL);
2726    assert(var != NULL);
2727    assert(minresactivity != NULL);
2728    assert(maxresactivity != NULL);
2729    assert(minisrelax != NULL);
2730    assert(maxisrelax != NULL);
2731    assert(isminsettoinfinity != NULL);
2732    assert(ismaxsettoinfinity != NULL);
2733 
2734    /* get activity bounds of linear constraint */
2735    if( !consdata->validactivities )
2736    {
2737       consdataCalcActivities(scip, consdata);
2738       assert(consdata->validminact);
2739       assert(consdata->validmaxact);
2740    }
2741    assert(consdata->minactivity < SCIP_INVALID);
2742    assert(consdata->maxactivity < SCIP_INVALID);
2743    assert(consdata->minactivityneginf >= 0);
2744    assert(consdata->minactivityposinf >= 0);
2745    assert(consdata->maxactivityneginf >= 0);
2746    assert(consdata->maxactivityposinf >= 0);
2747    assert(consdata->minactivityneghuge >= 0);
2748    assert(consdata->minactivityposhuge >= 0);
2749    assert(consdata->maxactivityneghuge >= 0);
2750    assert(consdata->maxactivityposhuge >= 0);
2751 
2752    if( val > 0.0 )
2753    {
2754       minactbound = SCIPvarGetLbLocal(var);
2755       maxactbound = SCIPvarGetUbLocal(var);
2756       absval = val;
2757    }
2758    else
2759    {
2760       minactbound = -SCIPvarGetUbLocal(var);
2761       maxactbound = -SCIPvarGetLbLocal(var);
2762       absval = -val;
2763    }
2764 
2765    /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2766     * and contribution of variable set to zero that has to be subtracted from finite part of activity
2767     */
2768    if( SCIPisInfinity(scip, minactbound) )
2769    {
2770       assert(consdata->minactivityposinf >= 1);
2771 
2772       getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2773          consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2774          minresactivity, minisrelax, isminsettoinfinity);
2775    }
2776    else if( SCIPisInfinity(scip, -minactbound) )
2777    {
2778       assert(consdata->minactivityneginf >= 1);
2779 
2780       getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2781          consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2782          minresactivity, minisrelax, isminsettoinfinity);
2783    }
2784    else if( SCIPisHugeValue(scip, minactbound * absval) )
2785    {
2786       assert(consdata->minactivityposhuge >= 1);
2787 
2788       getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2789          consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2790          minresactivity, minisrelax, isminsettoinfinity);
2791    }
2792    else if( SCIPisHugeValue(scip, -minactbound * absval) )
2793    {
2794       assert(consdata->minactivityneghuge >= 1);
2795 
2796       getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2797          consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2798          minresactivity, minisrelax, isminsettoinfinity);
2799    }
2800    else
2801    {
2802       getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2803          consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2804          minresactivity, minisrelax, isminsettoinfinity);
2805    }
2806 
2807    /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2808     * and contribution of variable set to zero that has to be subtracted from finite part of activity
2809     */
2810    if( SCIPisInfinity(scip, -maxactbound) )
2811    {
2812       assert(consdata->maxactivityneginf >= 1);
2813 
2814       getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2815          consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2816          maxresactivity, maxisrelax, ismaxsettoinfinity);
2817    }
2818    else if( SCIPisInfinity(scip, maxactbound) )
2819    {
2820       assert(consdata->maxactivityposinf >= 1);
2821 
2822       getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2823          consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2824          maxresactivity, maxisrelax, ismaxsettoinfinity);
2825    }
2826    else if( SCIPisHugeValue(scip, absval * maxactbound) )
2827    {
2828       assert(consdata->maxactivityposhuge >= 1);
2829 
2830       getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2831          consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2832          maxresactivity, maxisrelax, ismaxsettoinfinity);
2833    }
2834    else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2835    {
2836       assert(consdata->maxactivityneghuge >= 1);
2837 
2838       getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2839          consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2840          maxresactivity, maxisrelax, ismaxsettoinfinity);
2841    }
2842    else
2843    {
2844       getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2845          consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2846          maxresactivity, maxisrelax, ismaxsettoinfinity);
2847    }
2848 }
2849 
2850 /** gets global activity bounds for constraint */
2851 static
consdataGetGlbActivityBounds(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_Bool goodrelax,SCIP_Real * glbminactivity,SCIP_Real * glbmaxactivity,SCIP_Bool * minisrelax,SCIP_Bool * maxisrelax,SCIP_Bool * isminsettoinfinity,SCIP_Bool * ismaxsettoinfinity)2852 void consdataGetGlbActivityBounds(
2853    SCIP*                 scip,               /**< SCIP data structure */
2854    SCIP_CONSDATA*        consdata,           /**< linear constraint */
2855    SCIP_Bool             goodrelax,          /**< if we have huge contributions, do we need a good relaxation or are
2856                                               *   relaxed acticities ignored, anyway? */
2857    SCIP_Real*            glbminactivity,     /**< pointer to store the minimal activity, or NULL, if not needed */
2858    SCIP_Real*            glbmaxactivity,     /**< pointer to store the maximal activity, or NULL, if not needed */
2859    SCIP_Bool*            minisrelax,         /**< pointer to store whether the returned minactivity is just a relaxation,
2860                                               *   i.e. <= the exact minactivity (in case of huge contributions),
2861                                               *   or equal to the exact minimal activity */
2862    SCIP_Bool*            maxisrelax,         /**< pointer to store whether the returned maxactivity is just a relaxation,
2863                                               *   i.e. >= the exact maxactivity (in case of huge contributions),
2864                                               *   or equal to the exact maximal activity */
2865    SCIP_Bool*            isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2866    SCIP_Bool*            ismaxsettoinfinity  /**< pointer to store whether maxresactivity was set to infinity or calculated */
2867    )
2868 {
2869    assert(scip != NULL);
2870    assert(consdata != NULL);
2871    assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2872       || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2873 
2874    if( !consdata->validactivities )
2875    {
2876       consdataCalcActivities(scip, consdata);
2877       assert(consdata->validglbminact);
2878       assert(consdata->validglbmaxact);
2879    }
2880    assert(consdata->glbminactivity < SCIP_INVALID);
2881    assert(consdata->glbmaxactivity < SCIP_INVALID);
2882    assert(consdata->glbminactivityneginf >= 0);
2883    assert(consdata->glbminactivityposinf >= 0);
2884    assert(consdata->glbmaxactivityneginf >= 0);
2885    assert(consdata->glbmaxactivityposinf >= 0);
2886    assert(consdata->glbminactivityneghuge >= 0);
2887    assert(consdata->glbminactivityposhuge >= 0);
2888    assert(consdata->glbmaxactivityneghuge >= 0);
2889    assert(consdata->glbmaxactivityposhuge >= 0);
2890 
2891    if( glbminactivity != NULL )
2892    {
2893       assert(isminsettoinfinity != NULL);
2894       assert(minisrelax != NULL);
2895 
2896       getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2897          consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2898          glbminactivity, minisrelax, isminsettoinfinity);
2899    }
2900 
2901    if( glbmaxactivity != NULL )
2902    {
2903       assert(ismaxsettoinfinity != NULL);
2904       assert(maxisrelax != NULL);
2905 
2906       getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2907          consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2908          glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2909    }
2910 }
2911 
2912 /** gets global activity bounds for constraint after setting variable to zero */
2913 static
consdataGetGlbActivityResiduals(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_VAR * var,SCIP_Real val,SCIP_Bool goodrelax,SCIP_Real * minresactivity,SCIP_Real * maxresactivity,SCIP_Bool * minisrelax,SCIP_Bool * maxisrelax,SCIP_Bool * isminsettoinfinity,SCIP_Bool * ismaxsettoinfinity)2914 void consdataGetGlbActivityResiduals(
2915    SCIP*                 scip,               /**< SCIP data structure */
2916    SCIP_CONSDATA*        consdata,           /**< linear constraint */
2917    SCIP_VAR*             var,                /**< variable to calculate activity residual for */
2918    SCIP_Real             val,                /**< coefficient value of variable in linear constraint */
2919    SCIP_Bool             goodrelax,          /**< if we have huge contributions, do we need a good relaxation or are
2920                                               *   relaxed acticities ignored, anyway? */
2921    SCIP_Real*            minresactivity,     /**< pointer to store the minimal residual activity, or NULL, if not needed */
2922    SCIP_Real*            maxresactivity,     /**< pointer to store the maximal residual activity, or NULL, if not needed */
2923    SCIP_Bool*            minisrelax,         /**< pointer to store whether the returned residual minactivity is just a
2924                                               *   relaxation, i.e. <= the exact residual minactivity (in case of huge
2925                                               *   contributions), or equal to the exact residual minactivity */
2926    SCIP_Bool*            maxisrelax,         /**< pointer to store whether the returned residual maxactivity is just a
2927                                               *   relaxation, i.e. <= the exact residual maxactivity (in case of huge
2928                                               *   contributions), or equal to the exact residual minactivity */
2929    SCIP_Bool*            isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2930    SCIP_Bool*            ismaxsettoinfinity  /**< pointer to store whether maxresactivity was set to infinity or calculated */
2931    )
2932 {
2933    SCIP_Real minactbound;
2934    SCIP_Real maxactbound;
2935    SCIP_Real absval;
2936 
2937    assert(scip != NULL);
2938    assert(consdata != NULL);
2939    assert(var != NULL);
2940    assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2941       || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2942 
2943    /* get activity bounds of linear constraint */
2944    if( !consdata->validactivities )
2945       consdataCalcActivities(scip, consdata);
2946 
2947    assert(consdata->glbminactivity < SCIP_INVALID);
2948    assert(consdata->glbmaxactivity < SCIP_INVALID);
2949    assert(consdata->glbminactivityneginf >= 0);
2950    assert(consdata->glbminactivityposinf >= 0);
2951    assert(consdata->glbmaxactivityneginf >= 0);
2952    assert(consdata->glbmaxactivityposinf >= 0);
2953 
2954    if( val > 0.0 )
2955    {
2956       minactbound = SCIPvarGetLbGlobal(var);
2957       maxactbound = SCIPvarGetUbGlobal(var);
2958       absval = val;
2959    }
2960    else
2961    {
2962       minactbound = -SCIPvarGetUbGlobal(var);
2963       maxactbound = -SCIPvarGetLbGlobal(var);
2964       absval = -val;
2965    }
2966 
2967    if( minresactivity != NULL )
2968    {
2969       assert(isminsettoinfinity != NULL);
2970       assert(minisrelax != NULL);
2971 
2972       /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2973        * and contribution of variable set to zero that has to be subtracted from finite part of activity
2974        */
2975       if( SCIPisInfinity(scip, minactbound) )
2976       {
2977          assert(consdata->glbminactivityposinf >= 1);
2978 
2979          getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2980             consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2981             minresactivity, minisrelax, isminsettoinfinity);
2982       }
2983       else if( SCIPisInfinity(scip, -minactbound) )
2984       {
2985          assert(consdata->glbminactivityneginf >= 1);
2986 
2987          getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2988             consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2989             minresactivity, minisrelax, isminsettoinfinity);
2990       }
2991       else if( SCIPisHugeValue(scip, minactbound * absval) )
2992       {
2993          assert(consdata->glbminactivityposhuge >= 1);
2994 
2995          getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2996             consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2997             minresactivity, minisrelax, isminsettoinfinity);
2998       }
2999       else if( SCIPisHugeValue(scip, -minactbound * absval) )
3000       {
3001          assert(consdata->glbminactivityneghuge >= 1);
3002 
3003          getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3004             consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
3005             minresactivity, minisrelax, isminsettoinfinity);
3006       }
3007       else
3008       {
3009          getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
3010             consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
3011             goodrelax, minresactivity, minisrelax, isminsettoinfinity);
3012       }
3013    }
3014 
3015    if( maxresactivity != NULL )
3016    {
3017       assert(ismaxsettoinfinity != NULL);
3018       assert(maxisrelax != NULL);
3019 
3020       /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
3021        * and contribution of variable set to zero that has to be subtracted from finite part of activity
3022        */
3023       if( SCIPisInfinity(scip, -maxactbound) )
3024       {
3025          assert(consdata->glbmaxactivityneginf >= 1);
3026 
3027          getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
3028             consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3029             maxresactivity, maxisrelax, ismaxsettoinfinity);
3030       }
3031       else if( SCIPisInfinity(scip, maxactbound) )
3032       {
3033          assert(consdata->glbmaxactivityposinf >= 1);
3034 
3035          getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
3036             consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3037             maxresactivity, maxisrelax, ismaxsettoinfinity);
3038       }
3039       else if( SCIPisHugeValue(scip, absval * maxactbound) )
3040       {
3041          assert(consdata->glbmaxactivityposhuge >= 1);
3042 
3043          getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3044             consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
3045             maxresactivity, maxisrelax, ismaxsettoinfinity);
3046       }
3047       else if( SCIPisHugeValue(scip, -absval * maxactbound) )
3048       {
3049          assert(consdata->glbmaxactivityneghuge >= 1);
3050 
3051          getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3052             consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
3053             maxresactivity, maxisrelax, ismaxsettoinfinity);
3054       }
3055       else
3056       {
3057          getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
3058             consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
3059             goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
3060       }
3061    }
3062 }
3063 
3064 /** calculates the activity of the linear constraint for given solution */
3065 static
consdataGetActivity(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_SOL * sol)3066 SCIP_Real consdataGetActivity(
3067    SCIP*                 scip,               /**< SCIP data structure */
3068    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
3069    SCIP_SOL*             sol                 /**< solution to get activity for, NULL to current solution */
3070    )
3071 {
3072    SCIP_Real activity;
3073 
3074    assert(scip != NULL);
3075    assert(consdata != NULL);
3076 
3077    if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
3078       activity = consdataComputePseudoActivity(scip, consdata);
3079    else
3080    {
3081       SCIP_Real solval;
3082       int nposinf;
3083       int nneginf;
3084       SCIP_Bool negsign;
3085       int v;
3086 
3087       activity = 0.0;
3088       nposinf = 0;
3089       nneginf = 0;
3090 
3091       for( v = 0; v < consdata->nvars; ++v )
3092       {
3093          solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3094 
3095          if( consdata->vals[v] < 0 )
3096             negsign = TRUE;
3097          else
3098             negsign = FALSE;
3099 
3100          if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3101             ++nposinf;
3102          else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3103             ++nneginf;
3104          else
3105             activity += consdata->vals[v] * solval;
3106       }
3107       assert(nneginf >= 0 && nposinf >= 0);
3108 
3109       SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3110 
3111       /* check for amount of infinity values and correct the activity */
3112       if( nposinf > 0 && nneginf > 0 )
3113          activity = (consdata->rhs + consdata->lhs) / 2;
3114       else if( nposinf > 0 )
3115          activity = SCIPinfinity(scip);
3116       else if( nneginf > 0 )
3117          activity = -SCIPinfinity(scip);
3118 
3119       SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3120    }
3121 
3122    if( activity == SCIP_INVALID ) /*lint !e777*/
3123       return activity;
3124    else if( activity < 0 )
3125       activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3126    else
3127       activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3128 
3129    return activity;
3130 }
3131 
3132 /** calculates the feasibility of the linear constraint for given solution */
3133 static
consdataGetFeasibility(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_SOL * sol)3134 SCIP_Real consdataGetFeasibility(
3135    SCIP*                 scip,               /**< SCIP data structure */
3136    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
3137    SCIP_SOL*             sol                 /**< solution to get feasibility for, NULL to current solution */
3138    )
3139 {
3140    SCIP_Real activity;
3141 
3142    assert(scip != NULL);
3143    assert(consdata != NULL);
3144 
3145    activity = consdataGetActivity(scip, consdata, sol);
3146 
3147    if( activity == SCIP_INVALID ) /*lint !e777*/
3148       return -SCIPinfinity(scip);
3149 
3150    return MIN(consdata->rhs - activity, activity - consdata->lhs);
3151 }
3152 
3153 /** updates bit signatures after adding a single coefficient */
3154 static
consdataUpdateSignatures(SCIP_CONSDATA * consdata,int pos)3155 void consdataUpdateSignatures(
3156    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
3157    int                   pos                 /**< position of coefficient to update signatures for */
3158    )
3159 {
3160    uint64_t varsignature;
3161    SCIP_Real lb;
3162    SCIP_Real ub;
3163    SCIP_Real val;
3164 
3165    assert(consdata != NULL);
3166    assert(consdata->validsignature);
3167 
3168    varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3169    lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3170    ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3171    val = consdata->vals[pos];
3172    if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3173       consdata->possignature |= varsignature;
3174    if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3175       consdata->negsignature |= varsignature;
3176 }
3177 
3178 /** calculates the bit signatures of the given constraint data */
3179 static
consdataCalcSignatures(SCIP_CONSDATA * consdata)3180 void consdataCalcSignatures(
3181    SCIP_CONSDATA*        consdata            /**< linear constraint data */
3182    )
3183 {
3184    assert(consdata != NULL);
3185 
3186    if( !consdata->validsignature )
3187    {
3188       int i;
3189 
3190       consdata->validsignature = TRUE;
3191       consdata->possignature = 0;
3192       consdata->negsignature = 0;
3193       for( i = 0; i < consdata->nvars; ++i )
3194          consdataUpdateSignatures(consdata, i);
3195    }
3196 }
3197 
3198 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3199 static
SCIP_DECL_SORTINDCOMP(consdataCompVar)3200 SCIP_DECL_SORTINDCOMP(consdataCompVar)
3201 {  /*lint --e{715}*/
3202    SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3203    SCIP_VAR* var1;
3204    SCIP_VAR* var2;
3205 
3206    assert(consdata != NULL);
3207    assert(0 <= ind1 && ind1 < consdata->nvars);
3208    assert(0 <= ind2 && ind2 < consdata->nvars);
3209 
3210    var1 = consdata->vars[ind1];
3211    var2 = consdata->vars[ind2];
3212 
3213    /* exactly one variable is binary */
3214    if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3215    {
3216       return (SCIPvarIsBinary(var1) ? -1 : +1);
3217    }
3218    /* both variables are binary */
3219    else if( SCIPvarIsBinary(var1) )
3220    {
3221       return SCIPvarCompare(var1, var2);
3222    }
3223    else
3224    {
3225       SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3226       SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3227 
3228       if( vartype1 < vartype2 )
3229          return -1;
3230       else if( vartype1 > vartype2 )
3231          return +1;
3232       else
3233          return SCIPvarCompare(var1, var2);
3234    }
3235 }
3236 
3237 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3238 static
SCIP_DECL_SORTINDCOMP(consdataCompVarProp)3239 SCIP_DECL_SORTINDCOMP(consdataCompVarProp)
3240 {  /*lint --e{715}*/
3241    SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3242    SCIP_VAR* var1;
3243    SCIP_VAR* var2;
3244 
3245    assert(consdata != NULL);
3246    assert(0 <= ind1 && ind1 < consdata->nvars);
3247    assert(0 <= ind2 && ind2 < consdata->nvars);
3248 
3249    var1 = consdata->vars[ind1];
3250    var2 = consdata->vars[ind2];
3251 
3252    /* exactly one variable is binary */
3253    if( SCIPvarIsBinary(var1) != SCIPvarIsBinary(var2) )
3254    {
3255       return (SCIPvarIsBinary(var1) ? -1 : +1);
3256    }
3257    /* both variables are binary */
3258    else if( SCIPvarIsBinary(var1) )
3259    {
3260       SCIP_Real abscoef1 = REALABS(consdata->vals[ind1]);
3261       SCIP_Real abscoef2 = REALABS(consdata->vals[ind2]);
3262 
3263       if( EPSGT(abscoef1, abscoef2, 1e-9) )
3264          return -1;
3265       else if( EPSGT(abscoef2, abscoef1, 1e-9) )
3266          return +1;
3267       else
3268          return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3269    }
3270    else
3271    {
3272       SCIP_VARTYPE vartype1 = SCIPvarGetType(var1);
3273       SCIP_VARTYPE vartype2 = SCIPvarGetType(var2);
3274 
3275       if( vartype1 < vartype2 )
3276       {
3277          return -1;
3278       }
3279       else if( vartype1 > vartype2 )
3280       {
3281          return +1;
3282       }
3283       else
3284       {
3285          /* both variables are continuous */
3286          if( !SCIPvarIsIntegral(var1) )
3287          {
3288             assert(!SCIPvarIsIntegral(var2));
3289             return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3290          }
3291          else
3292          {
3293             SCIP_Real abscont1 = REALABS(consdata->vals[ind1] * (SCIPvarGetUbGlobal(var1) - SCIPvarGetLbGlobal(var1)));
3294             SCIP_Real abscont2 = REALABS(consdata->vals[ind2] * (SCIPvarGetUbGlobal(var2) - SCIPvarGetLbGlobal(var2)));
3295 
3296             if( EPSGT(abscont1, abscont2, 1e-9) )
3297                return -1;
3298             else if( EPSGT(abscont2, abscont1, 1e-9) )
3299                return +1;
3300             else
3301                return (SCIPvarGetProbindex(var1) - SCIPvarGetProbindex(var2));
3302          }
3303       }
3304    }
3305 }
3306 
3307 /** permutes the constraint's variables according to a given permutation. */
3308 static
permSortConsdata(SCIP_CONSDATA * consdata,int * perm,int nvars)3309 void permSortConsdata(
3310    SCIP_CONSDATA*        consdata,           /**< the constraint data */
3311    int*                  perm,               /**< the target permutation */
3312    int                   nvars               /**< the number of variables */
3313    )
3314 {  /*lint --e{715}*/
3315    SCIP_VAR* varv;
3316    SCIP_EVENTDATA* eventdatav;
3317    SCIP_Real valv;
3318    int v;
3319    int i;
3320    int nexti;
3321 
3322    assert(perm != NULL);
3323    assert(consdata != NULL);
3324 
3325    /* permute the variables in the linear constraint according to the target permutation */
3326    eventdatav = NULL;
3327    for( v = 0; v < nvars; ++v )
3328    {
3329       if( perm[v] != v )
3330       {
3331          varv = consdata->vars[v];
3332          valv = consdata->vals[v];
3333          if( consdata->eventdata != NULL )
3334             eventdatav = consdata->eventdata[v];
3335          i = v;
3336          do
3337          {
3338             assert(0 <= perm[i] && perm[i] < nvars);
3339             assert(perm[i] != i);
3340             consdata->vars[i] = consdata->vars[perm[i]];
3341             consdata->vals[i] = consdata->vals[perm[i]];
3342             if( consdata->eventdata != NULL )
3343             {
3344                consdata->eventdata[i] = consdata->eventdata[perm[i]];
3345                consdata->eventdata[i]->varpos = i;
3346             }
3347             nexti = perm[i];
3348             perm[i] = i;
3349             i = nexti;
3350          }
3351          while( perm[i] != v );
3352          consdata->vars[i] = varv;
3353          consdata->vals[i] = valv;
3354          if( consdata->eventdata != NULL )
3355          {
3356             consdata->eventdata[i] = eventdatav;
3357             consdata->eventdata[i]->varpos = i;
3358          }
3359          perm[i] = i;
3360       }
3361    }
3362 #ifdef SCIP_DEBUG
3363    /* check sorting */
3364    for( v = 0; v < nvars; ++v )
3365    {
3366       assert(perm[v] == v);
3367       assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3368    }
3369 #endif
3370 }
3371 
3372 /** sorts linear constraint's variables depending on the stage of the solving process:
3373  * - during PRESOLVING
3374  *       sorts variables by binaries, integers, implicit integers, and continuous variables,
3375  *       and the variables of the same type by non-decreasing variable index
3376  *
3377  * - during SOLVING
3378  *       sorts variables of the remaining problem by binaries, integers, implicit integers, and continuous variables,
3379  *       and binary and integer variables by their global max activity delta (within each group),
3380  *       ties within a group are broken by problem index of the variable.
3381  *
3382  *       This fastens the propagation time of the constraint handler.
3383  */
3384 static
consdataSort(SCIP * scip,SCIP_CONSDATA * consdata)3385 SCIP_RETCODE consdataSort(
3386    SCIP*                 scip,               /**< SCIP data structure */
3387    SCIP_CONSDATA*        consdata            /**< linear constraint data */
3388    )
3389 {
3390    assert(scip != NULL);
3391    assert(consdata != NULL);
3392 
3393    /* check if there are variables for sorting */
3394    if( consdata->nvars <= 1 )
3395    {
3396       consdata->indexsorted = TRUE;
3397       consdata->coefsorted = TRUE;
3398       consdata->nbinvars = (consdata->nvars == 1 ? (int)SCIPvarIsBinary(consdata->vars[0]) : 0);
3399    }
3400    else if( (!consdata->indexsorted && SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE)
3401       || (!consdata->coefsorted && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE) )
3402    {
3403       int* perm;
3404       int v;
3405 
3406       /* get temporary memory to store the sorted permutation */
3407       SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3408 
3409       /* call sorting method  */
3410       if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
3411          SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3412       else
3413          SCIPsort(perm, consdataCompVarProp, (void*)consdata, consdata->nvars);
3414 
3415       permSortConsdata(consdata, perm, consdata->nvars);
3416 
3417       /* free temporary memory */
3418       SCIPfreeBufferArray(scip, &perm);
3419 
3420       if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE )
3421       {
3422          consdata->indexsorted = FALSE;
3423          consdata->coefsorted = TRUE;
3424 
3425          /* count binary variables in the sorted vars array */
3426          consdata->nbinvars = 0;
3427          for( v = 0; v < consdata->nvars; ++v )
3428          {
3429             if( SCIPvarIsBinary(consdata->vars[v]) )
3430                ++consdata->nbinvars;
3431             else
3432                break;
3433          }
3434       }
3435       else
3436       {
3437          consdata->indexsorted = TRUE;
3438          consdata->coefsorted = FALSE;
3439       }
3440    }
3441 
3442    return SCIP_OKAY;
3443 }
3444 
3445 
3446 /*
3447  * local linear constraint handler methods
3448  */
3449 
3450 /** sets left hand side of linear constraint */
3451 static
chgLhs(SCIP * scip,SCIP_CONS * cons,SCIP_Real lhs)3452 SCIP_RETCODE chgLhs(
3453    SCIP*                 scip,               /**< SCIP data structure */
3454    SCIP_CONS*            cons,               /**< linear constraint */
3455    SCIP_Real             lhs                 /**< new left hand side */
3456    )
3457 {
3458    SCIP_CONSDATA* consdata;
3459    SCIP_Bool locked;
3460    int i;
3461 
3462    assert(scip != NULL);
3463    assert(cons != NULL);
3464    assert(!SCIPisInfinity(scip, lhs));
3465 
3466    /* adjust value to not be smaller than -inf */
3467    if ( SCIPisInfinity(scip, -lhs) )
3468       lhs = -SCIPinfinity(scip);
3469 
3470    consdata = SCIPconsGetData(cons);
3471    assert(consdata != NULL);
3472    assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3473    assert(!SCIPisInfinity(scip, consdata->lhs));
3474 
3475    /* check whether the side is not changed */
3476    if( SCIPisEQ(scip, consdata->lhs, lhs) )
3477       return SCIP_OKAY;
3478 
3479    /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3480    if( SCIPisEQ(scip, lhs, consdata->rhs) )
3481    {
3482       consdata->rhs = lhs;
3483       assert(consdata->row == NULL);
3484    }
3485 
3486    locked = FALSE;
3487    for( i = 0; i < NLOCKTYPES && !locked; i++ )
3488       locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3489 
3490    /* if necessary, update the rounding locks of variables */
3491    if( locked )
3492    {
3493       if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3494       {
3495          SCIP_VAR** vars;
3496          SCIP_Real* vals;
3497          int v;
3498 
3499          /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3500          vars = consdata->vars;
3501          vals = consdata->vals;
3502 
3503          for( v = 0; v < consdata->nvars; ++v )
3504          {
3505             assert(vars[v] != NULL);
3506             assert(!SCIPisZero(scip, vals[v]));
3507 
3508             if( SCIPisPositive(scip, vals[v]) )
3509             {
3510                SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3511             }
3512             else
3513             {
3514                SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3515             }
3516          }
3517       }
3518       else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3519       {
3520          SCIP_VAR** vars;
3521          SCIP_Real* vals;
3522          int v;
3523 
3524          /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3525          vars = consdata->vars;
3526          vals = consdata->vals;
3527 
3528          for( v = 0; v < consdata->nvars; ++v )
3529          {
3530             assert(vars[v] != NULL);
3531             assert(!SCIPisZero(scip, vals[v]));
3532 
3533             if( SCIPisPositive(scip, vals[v]) )
3534             {
3535                SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3536             }
3537             else
3538             {
3539                SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3540             }
3541          }
3542       }
3543    }
3544 
3545    /* check whether the left hand side is increased, if and only if that's the case we maybe can propagate, tighten and add more cliques */
3546    if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3547    {
3548       consdata->boundstightened = 0;
3549       consdata->presolved = FALSE;
3550       consdata->cliquesadded = FALSE;
3551       consdata->implsadded = FALSE;
3552 
3553       /* mark the constraint for propagation */
3554       if( SCIPconsIsTransformed(cons) )
3555       {
3556          SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3557       }
3558    }
3559 
3560    /* set new left hand side and update constraint data */
3561    consdata->lhs = lhs;
3562    consdata->changed = TRUE;
3563    consdata->normalized = FALSE;
3564    consdata->upgradetried = FALSE;
3565    consdata->rangedrowpropagated = 0;
3566 
3567    /* update the lhs of the LP row */
3568    if( consdata->row != NULL )
3569    {
3570       SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3571    }
3572 
3573    return SCIP_OKAY;
3574 }
3575 
3576 /** sets right hand side of linear constraint */
3577 static
chgRhs(SCIP * scip,SCIP_CONS * cons,SCIP_Real rhs)3578 SCIP_RETCODE chgRhs(
3579    SCIP*                 scip,               /**< SCIP data structure */
3580    SCIP_CONS*            cons,               /**< linear constraint */
3581    SCIP_Real             rhs                 /**< new right hand side */
3582    )
3583 {
3584    SCIP_CONSDATA* consdata;
3585    SCIP_Bool locked;
3586    int i;
3587 
3588    assert(scip != NULL);
3589    assert(cons != NULL);
3590    assert(!SCIPisInfinity(scip, -rhs));
3591 
3592    /* adjust value to not be larger than inf */
3593    if ( SCIPisInfinity(scip, rhs) )
3594       rhs = SCIPinfinity(scip);
3595 
3596    consdata = SCIPconsGetData(cons);
3597    assert(consdata != NULL);
3598    assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3599    assert(!SCIPisInfinity(scip, -consdata->rhs));
3600 
3601    /* check whether the side is not changed */
3602    if( SCIPisEQ(scip, consdata->rhs, rhs) )
3603       return SCIP_OKAY;
3604 
3605    /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3606    if( SCIPisEQ(scip, rhs, consdata->lhs) )
3607    {
3608       consdata->lhs = rhs;
3609       assert(consdata->row == NULL);
3610    }
3611 
3612    locked = FALSE;
3613    for( i = 0; i < NLOCKTYPES && !locked; i++ )
3614       locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
3615 
3616    /* if necessary, update the rounding locks of variables */
3617    if( locked )
3618    {
3619       assert(SCIPconsIsTransformed(cons));
3620 
3621       if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3622       {
3623          SCIP_VAR** vars;
3624          SCIP_Real* vals;
3625          int v;
3626 
3627          /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3628          vars = consdata->vars;
3629          vals = consdata->vals;
3630 
3631          for( v = 0; v < consdata->nvars; ++v )
3632          {
3633             assert(vars[v] != NULL);
3634             assert(!SCIPisZero(scip, vals[v]));
3635 
3636             if( SCIPisPositive(scip, vals[v]) )
3637             {
3638                SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3639             }
3640             else
3641             {
3642                SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3643             }
3644          }
3645       }
3646       else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3647       {
3648          SCIP_VAR** vars;
3649          SCIP_Real* vals;
3650          int v;
3651 
3652          /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3653          vars = consdata->vars;
3654          vals = consdata->vals;
3655 
3656          for( v = 0; v < consdata->nvars; ++v )
3657          {
3658             assert(vars[v] != NULL);
3659             assert(!SCIPisZero(scip, vals[v]));
3660 
3661             if( SCIPisPositive(scip, vals[v]) )
3662             {
3663                SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3664             }
3665             else
3666             {
3667                SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3668             }
3669          }
3670       }
3671    }
3672 
3673    /* check whether the right hand side is decreased, if and only if that's the case we maybe can propagate, tighten and add more cliques */
3674    if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3675    {
3676       consdata->boundstightened = 0;
3677       consdata->presolved = FALSE;
3678       consdata->cliquesadded = FALSE;
3679       consdata->implsadded = FALSE;
3680 
3681       /* mark the constraint for propagation */
3682       if( SCIPconsIsTransformed(cons) )
3683       {
3684          SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3685       }
3686    }
3687 
3688    /* set new right hand side and update constraint data */
3689    consdata->rhs = rhs;
3690    consdata->changed = TRUE;
3691    consdata->normalized = FALSE;
3692    consdata->upgradetried = FALSE;
3693    consdata->rangedrowpropagated = 0;
3694 
3695    /* update the rhs of the LP row */
3696    if( consdata->row != NULL )
3697    {
3698       SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3699    }
3700 
3701    return SCIP_OKAY;
3702 }
3703 
3704 /** adds coefficient in linear constraint */
3705 static
addCoef(SCIP * scip,SCIP_CONS * cons,SCIP_VAR * var,SCIP_Real val)3706 SCIP_RETCODE addCoef(
3707    SCIP*                 scip,               /**< SCIP data structure */
3708    SCIP_CONS*            cons,               /**< linear constraint */
3709    SCIP_VAR*             var,                /**< variable of constraint entry */
3710    SCIP_Real             val                 /**< coefficient of constraint entry */
3711    )
3712 {
3713    SCIP_CONSDATA* consdata;
3714    SCIP_Bool transformed;
3715 
3716    assert(scip != NULL);
3717    assert(cons != NULL);
3718    assert(var != NULL);
3719 
3720    /* relaxation-only variables must not be used in checked or enforced constraints */
3721    assert(!SCIPvarIsRelaxationOnly(var) || (!SCIPconsIsChecked(cons) && !SCIPconsIsEnforced(cons)));
3722 
3723    /* ignore coefficient if it is nearly zero */
3724    if( SCIPisZero(scip, val) )
3725       return SCIP_OKAY;
3726 
3727    consdata = SCIPconsGetData(cons);
3728    assert(consdata != NULL);
3729 
3730    /* are we in the transformed problem? */
3731    transformed = SCIPconsIsTransformed(cons);
3732 
3733    /* always use transformed variables in transformed constraints */
3734    if( transformed )
3735    {
3736       SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3737    }
3738    assert(var != NULL);
3739    assert(transformed == SCIPvarIsTransformed(var));
3740 
3741    SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3742    consdata->vars[consdata->nvars] = var;
3743    consdata->vals[consdata->nvars] = val;
3744    consdata->nvars++;
3745 
3746    /* capture variable */
3747    SCIP_CALL( SCIPcaptureVar(scip, var) );
3748 
3749    /* if we are in transformed problem, the variable needs an additional event data */
3750    if( transformed )
3751    {
3752       if( consdata->eventdata != NULL )
3753       {
3754          SCIP_CONSHDLR* conshdlr;
3755          SCIP_CONSHDLRDATA* conshdlrdata;
3756 
3757          /* check for event handler */
3758          conshdlr = SCIPconsGetHdlr(cons);
3759          conshdlrdata = SCIPconshdlrGetData(conshdlr);
3760          assert(conshdlrdata != NULL);
3761          assert(conshdlrdata->eventhdlr != NULL);
3762 
3763          /* initialize eventdata array */
3764          consdata->eventdata[consdata->nvars-1] = NULL;
3765 
3766          /* catch bound change events of variable */
3767          SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3768       }
3769 
3770       /* update minimum and maximum activities */
3771       consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3772 
3773       /* update maximum activity delta */
3774       if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3775       {
3776          SCIP_Real lb;
3777          SCIP_Real ub;
3778 
3779          lb = SCIPvarGetLbLocal(var);
3780          ub = SCIPvarGetUbLocal(var);
3781 
3782          if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3783          {
3784             consdata->maxactdelta = SCIPinfinity(scip);
3785             consdata->maxactdeltavar = var;
3786          }
3787          else
3788          {
3789             SCIP_Real domain = ub - lb;
3790             SCIP_Real delta = REALABS(val) * domain;
3791 
3792             if( delta > consdata->maxactdelta )
3793             {
3794                consdata->maxactdelta = delta;
3795                consdata->maxactdeltavar = var;
3796             }
3797          }
3798       }
3799    }
3800 
3801    /* install rounding locks for new variable */
3802    SCIP_CALL( lockRounding(scip, cons, var, val) );
3803 
3804    /* mark the constraint for propagation */
3805    if( transformed )
3806    {
3807       SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3808    }
3809 
3810    consdata->boundstightened = 0;
3811    consdata->presolved = FALSE;
3812    consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3813 
3814    if( consdata->validsignature )
3815       consdataUpdateSignatures(consdata, consdata->nvars-1);
3816 
3817    consdata->changed = TRUE;
3818    consdata->normalized = FALSE;
3819    consdata->upgradetried = FALSE;
3820    consdata->cliquesadded = FALSE;
3821    consdata->implsadded = FALSE;
3822    consdata->rangedrowpropagated = 0;
3823 
3824    if( consdata->nvars == 1 )
3825    {
3826       consdata->indexsorted = TRUE;
3827       consdata->coefsorted = TRUE;
3828       consdata->merged = TRUE;
3829    }
3830    else
3831    {
3832       consdata->merged = FALSE;
3833 
3834       if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
3835       {
3836          consdata->indexsorted = consdata->indexsorted && (consdataCompVar((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3837          consdata->coefsorted = FALSE;
3838       }
3839       else
3840       {
3841          consdata->indexsorted = FALSE;
3842          consdata->coefsorted = consdata->coefsorted && (consdataCompVarProp((void*)consdata, consdata->nvars-2, consdata->nvars-1) <= 0);
3843       }
3844    }
3845 
3846    /* update hascontvar and hasnonbinvar flags */
3847    if( consdata->hasnonbinvalid && !consdata->hascontvar )
3848    {
3849       SCIP_VARTYPE vartype = SCIPvarGetType(var);
3850 
3851       if( vartype != SCIP_VARTYPE_BINARY )
3852       {
3853          consdata->hasnonbinvar = TRUE;
3854 
3855          if( vartype == SCIP_VARTYPE_CONTINUOUS )
3856             consdata->hascontvar = TRUE;
3857       }
3858    }
3859 
3860    /* add the new coefficient to the LP row */
3861    if( consdata->row != NULL )
3862    {
3863       SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3864    }
3865 
3866    return SCIP_OKAY;
3867 }
3868 
3869 /** deletes coefficient at given position from linear constraint data */
3870 static
delCoefPos(SCIP * scip,SCIP_CONS * cons,int pos)3871 SCIP_RETCODE delCoefPos(
3872    SCIP*                 scip,               /**< SCIP data structure */
3873    SCIP_CONS*            cons,               /**< linear constraint */
3874    int                   pos                 /**< position of coefficient to delete */
3875    )
3876 {
3877    SCIP_CONSDATA* consdata;
3878    SCIP_VAR* var;
3879    SCIP_Real val;
3880 
3881    assert(scip != NULL);
3882    assert(cons != NULL);
3883 
3884    consdata = SCIPconsGetData(cons);
3885    assert(consdata != NULL);
3886    assert(0 <= pos && pos < consdata->nvars);
3887 
3888    var = consdata->vars[pos];
3889    val = consdata->vals[pos];
3890    assert(var != NULL);
3891 
3892    /* remove rounding locks for deleted variable */
3893    SCIP_CALL( unlockRounding(scip, cons, var, val) );
3894 
3895    /* if we are in transformed problem, delete the event data of the variable */
3896    if( SCIPconsIsTransformed(cons) )
3897    {
3898       SCIP_CONSHDLR* conshdlr;
3899       SCIP_CONSHDLRDATA* conshdlrdata;
3900 
3901       /* check for event handler */
3902       conshdlr = SCIPconsGetHdlr(cons);
3903       conshdlrdata = SCIPconshdlrGetData(conshdlr);
3904       assert(conshdlrdata != NULL);
3905       assert(conshdlrdata->eventhdlr != NULL);
3906 
3907       /* drop bound change events of variable */
3908       if( consdata->eventdata != NULL )
3909       {
3910          SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3911          assert(consdata->eventdata[pos] == NULL);
3912       }
3913    }
3914 
3915    /* move the last variable to the free slot */
3916    if( pos != consdata->nvars - 1 )
3917    {
3918       consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3919       consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3920 
3921       if( consdata->eventdata != NULL )
3922       {
3923          consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3924          assert(consdata->eventdata[pos] != NULL);
3925          consdata->eventdata[pos]->varpos = pos;
3926       }
3927 
3928       consdata->indexsorted = consdata->indexsorted && (pos + 2 >= consdata->nvars);
3929       consdata->coefsorted = consdata->coefsorted && (pos + 2 >= consdata->nvars);
3930    }
3931    consdata->nvars--;
3932 
3933    /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3934     * of the remaining variable, or give exactly 0.0)
3935     */
3936    if( consdata->nvars <= 1 )
3937       consdataInvalidateActivities(consdata);
3938    else
3939    {
3940       if( SCIPconsIsTransformed(cons) )
3941       {
3942          /* if we are in transformed problem, update minimum and maximum activities */
3943          consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3944 
3945          /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3946           * delta needs to be recalculated on the next real propagation
3947           */
3948          if( consdata->maxactdeltavar == var )
3949          {
3950             consdata->maxactdelta = SCIP_INVALID;
3951             consdata->maxactdeltavar = NULL;
3952          }
3953       }
3954    }
3955 
3956    /* mark the constraint for propagation */
3957    if( SCIPconsIsTransformed(cons) )
3958    {
3959       SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3960    }
3961 
3962    consdata->boundstightened = 0;
3963    consdata->presolved = FALSE;
3964    consdata->validsignature = FALSE;
3965    consdata->changed = TRUE;
3966    consdata->normalized = FALSE;
3967    consdata->upgradetried = FALSE;
3968    consdata->cliquesadded = FALSE;
3969    consdata->implsadded = FALSE;
3970    consdata->rangedrowpropagated = 0;
3971 
3972    /* check if hasnonbinvar flag might be incorrect now */
3973    if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3974    {
3975       consdata->hasnonbinvalid = FALSE;
3976    }
3977 
3978    /* delete coefficient from the LP row */
3979    if( consdata->row != NULL )
3980    {
3981       SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3982    }
3983 
3984    /* release variable */
3985    SCIP_CALL( SCIPreleaseVar(scip, &var) );
3986 
3987    return SCIP_OKAY;
3988 }
3989 
3990 /** changes coefficient value at given position of linear constraint data */
3991 static
chgCoefPos(SCIP * scip,SCIP_CONS * cons,int pos,SCIP_Real newval)3992 SCIP_RETCODE chgCoefPos(
3993    SCIP*                 scip,               /**< SCIP data structure */
3994    SCIP_CONS*            cons,               /**< linear constraint */
3995    int                   pos,                /**< position of coefficient to delete */
3996    SCIP_Real             newval              /**< new value of coefficient */
3997    )
3998 {
3999    SCIP_CONSDATA* consdata;
4000    SCIP_VAR* var;
4001    SCIP_Real val;
4002    SCIP_Bool locked;
4003    int i;
4004 
4005    assert(scip != NULL);
4006    assert(cons != NULL);
4007    assert(!SCIPisZero(scip, newval));
4008 
4009    consdata = SCIPconsGetData(cons);
4010    assert(consdata != NULL);
4011    assert(0 <= pos && pos < consdata->nvars);
4012    assert(!SCIPisZero(scip, newval));
4013 
4014    var = consdata->vars[pos];
4015    val = consdata->vals[pos];
4016    assert(var != NULL);
4017    assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
4018 
4019    locked = FALSE;
4020    for( i = 0; i < NLOCKTYPES && !locked; i++ )
4021       locked = SCIPconsIsLockedType(cons, (SCIP_LOCKTYPE) i);
4022 
4023    /* if necessary, update the rounding locks of the variable */
4024    if( locked && newval * val < 0.0 )
4025    {
4026       assert(SCIPconsIsTransformed(cons));
4027 
4028       /* remove rounding locks for variable with old coefficient */
4029       SCIP_CALL( unlockRounding(scip, cons, var, val) );
4030 
4031       /* install rounding locks for variable with new coefficient */
4032       SCIP_CALL( lockRounding(scip, cons, var, newval) );
4033    }
4034 
4035    /* change the value */
4036    consdata->vals[pos] = newval;
4037 
4038    if( consdata->coefsorted )
4039    {
4040       if( pos > 0 )
4041          consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos - 1, pos) <= 0);
4042       if( consdata->coefsorted && pos < consdata->nvars - 1 )
4043          consdata->coefsorted = (consdataCompVarProp((void*)consdata, pos, pos + 1) <= 0);
4044    }
4045 
4046    /* update minimum and maximum activities */
4047    if( SCIPconsIsTransformed(cons) )
4048       consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
4049 
4050    /* mark the constraint for propagation */
4051    if( SCIPconsIsTransformed(cons) )
4052    {
4053       SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
4054    }
4055 
4056    consdata->boundstightened = 0;
4057    consdata->presolved = FALSE;
4058    consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
4059    consdata->changed = TRUE;
4060    consdata->normalized = FALSE;
4061    consdata->upgradetried = FALSE;
4062    consdata->cliquesadded = FALSE;
4063    consdata->implsadded = FALSE;
4064    consdata->rangedrowpropagated = 0;
4065 
4066    return SCIP_OKAY;
4067 }
4068 
4069 /** scales a linear constraint with a constant scalar */
4070 static
scaleCons(SCIP * scip,SCIP_CONS * cons,SCIP_Real scalar)4071 SCIP_RETCODE scaleCons(
4072    SCIP*                 scip,               /**< SCIP data structure */
4073    SCIP_CONS*            cons,               /**< linear constraint to scale */
4074    SCIP_Real             scalar              /**< value to scale constraint with */
4075    )
4076 {
4077    SCIP_CONSDATA* consdata;
4078    SCIP_Real newval;
4079    SCIP_Real absscalar;
4080    int i;
4081 
4082    assert(scip != NULL);
4083    assert(cons != NULL);
4084 
4085    consdata = SCIPconsGetData(cons);
4086    assert(consdata != NULL);
4087    assert(consdata->row == NULL);
4088    assert(!SCIPisEQ(scip, scalar, 1.0));
4089 
4090    if( (!SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -consdata->lhs * scalar))
4091       || (!SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, consdata->rhs * scalar)) )
4092    {
4093       SCIPwarningMessage(scip, "skipped scaling for linear constraint <%s> to avoid numerical troubles (scalar: %.15g)\n",
4094          SCIPconsGetName(cons), scalar);
4095 
4096       return SCIP_OKAY;
4097    }
4098 
4099    /* scale the coefficients */
4100    for( i = consdata->nvars - 1; i >= 0; --i )
4101    {
4102       newval = scalar * consdata->vals[i];
4103 
4104       /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4105        * flooring down our new value
4106        */
4107       if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
4108          newval = SCIPfeasFloor(scip, newval + 0.5);
4109 
4110       if( SCIPisZero(scip, newval) )
4111       {
4112          SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
4113             consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
4114          SCIP_CALL( delCoefPos(scip, cons, i) );
4115       }
4116       else
4117          consdata->vals[i] = newval;
4118    }
4119 
4120    /* scale the sides */
4121    if( scalar < 0.0 )
4122    {
4123       SCIP_Real lhs;
4124 
4125       lhs = consdata->lhs;
4126       consdata->lhs = -consdata->rhs;
4127       consdata->rhs = -lhs;
4128    }
4129    absscalar = REALABS(scalar);
4130    if( !SCIPisInfinity(scip, -consdata->lhs) )
4131    {
4132       newval = absscalar * consdata->lhs;
4133 
4134       /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
4135        * flooring down our new value
4136        */
4137       if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
4138          consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
4139       else
4140          consdata->lhs = newval;
4141    }
4142    if( !SCIPisInfinity(scip, consdata->rhs) )
4143    {
4144       newval = absscalar * consdata->rhs;
4145 
4146       /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4147        * our new value
4148        */
4149       if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4150          consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4151       else
4152          consdata->rhs = newval;
4153    }
4154 
4155    consdataInvalidateActivities(consdata);
4156    consdata->cliquesadded = FALSE;
4157    consdata->implsadded = FALSE;
4158 
4159    return SCIP_OKAY;
4160 }
4161 
4162 /** perform deletion of variables in all constraints of the constraint handler */
4163 static
performVarDeletions(SCIP * scip,SCIP_CONSHDLR * conshdlr,SCIP_CONS ** conss,int nconss)4164 SCIP_RETCODE performVarDeletions(
4165    SCIP*                 scip,               /**< SCIP data structure */
4166    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
4167    SCIP_CONS**           conss,              /**< array of constraints */
4168    int                   nconss              /**< number of constraints */
4169    )
4170 {
4171    SCIP_CONSDATA* consdata;
4172    int i;
4173    int v;
4174 
4175    assert(scip != NULL);
4176    assert(conshdlr != NULL);
4177    assert(conss != NULL);
4178    assert(nconss >= 0);
4179    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4180 
4181    /* iterate over all constraints */
4182    for( i = 0; i < nconss; i++ )
4183    {
4184       consdata = SCIPconsGetData(conss[i]);
4185 
4186       /* constraint is marked, that some of its variables were deleted */
4187       if( consdata->varsdeleted )
4188       {
4189          /* iterate over all variables of the constraint and delete them from the constraint */
4190          for( v = consdata->nvars - 1; v >= 0; --v )
4191          {
4192             if( SCIPvarIsDeleted(consdata->vars[v]) )
4193             {
4194                SCIP_CALL( delCoefPos(scip, conss[i], v) );
4195             }
4196          }
4197          consdata->varsdeleted = FALSE;
4198       }
4199    }
4200 
4201    return SCIP_OKAY;
4202 }
4203 
4204 
4205 /** normalizes a linear constraint with the following rules:
4206  *  - if all coefficients have them same absolute value, change them to (-)1.0
4207  *  - multiplication with +1 or -1:
4208  *      Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4209  *      if the current rule doesn't determine the sign):
4210  *        1. the right hand side must not be negative
4211  *        2. the right hand side must not be infinite
4212  *        3. the absolute value of the right hand side must be greater than that of the left hand side
4213  *        4. the number of positive coefficients must not be smaller than the number of negative coefficients
4214  *        5. multiply with +1
4215  *  - rationals to integrals
4216  *      Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4217  *      by the smallest common multiple of all denominators to get integral coefficients.
4218  *      Forbid large denominators due to numerical stability.
4219  *  - division by greatest common divisor
4220  *      If all coefficients are integral, divide them by the greatest common divisor.
4221  */
4222 static
normalizeCons(SCIP * scip,SCIP_CONS * cons,SCIP_Bool * infeasible)4223 SCIP_RETCODE normalizeCons(
4224    SCIP*                 scip,               /**< SCIP data structure */
4225    SCIP_CONS*            cons,               /**< linear constraint to normalize */
4226    SCIP_Bool*            infeasible          /**< pointer to store whether infeasibility was detected */
4227    )
4228 {
4229    SCIP_CONSDATA* consdata;
4230    SCIP_Real* vals;
4231    SCIP_Longint scm;
4232    SCIP_Longint nominator;
4233    SCIP_Longint denominator;
4234    SCIP_Longint gcd;
4235    SCIP_Longint maxmult;
4236    SCIP_Real epsilon;
4237    SCIP_Real feastol;
4238    SCIP_Real maxabsval;
4239    SCIP_Real minabsval;
4240    SCIP_Bool success;
4241    SCIP_Bool onlyintegral;
4242    int nvars;
4243    int mult;
4244    int nposcoeffs;
4245    int nnegcoeffs;
4246    int i;
4247    int v;
4248 
4249    assert(scip != NULL);
4250    assert(cons != NULL);
4251    assert(infeasible != NULL);
4252 
4253    *infeasible = FALSE;
4254 
4255    /* we must not change a modifiable constraint in any way */
4256    if( SCIPconsIsModifiable(cons) )
4257       return SCIP_OKAY;
4258 
4259    /* get constraint data */
4260    consdata = SCIPconsGetData(cons);
4261    assert(consdata != NULL);
4262 
4263    /* check, if the constraint is already normalized */
4264    if( consdata->normalized )
4265       return SCIP_OKAY;
4266 
4267    /* get coefficient arrays */
4268    vals = consdata->vals;
4269    nvars = consdata->nvars;
4270    assert(nvars == 0 || vals != NULL);
4271 
4272    if( nvars == 0 )
4273    {
4274       consdata->normalized = TRUE;
4275       return SCIP_OKAY;
4276    }
4277 
4278    assert(vals != NULL);
4279 
4280    /* get maximal and minimal absolute coefficient */
4281    maxabsval = consdataGetMaxAbsval(consdata);
4282    minabsval = consdataGetMinAbsval(consdata);
4283 
4284    /* return if scaling by maxval will eliminate coefficients */
4285    if( SCIPisZero(scip, minabsval/maxabsval) )
4286       return SCIP_OKAY;
4287 
4288    /* check if all coefficients are in absolute value equal, and not 1.0 */
4289    if( !SCIPisEQ(scip, maxabsval, 1.0) )
4290    {
4291       SCIP_Bool abscoefsequ;
4292 
4293       abscoefsequ = TRUE;
4294 
4295       for( v = nvars - 1; v >= 0; --v )
4296       {
4297          if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
4298          {
4299             abscoefsequ = FALSE;
4300             break;
4301          }
4302       }
4303 
4304       /* all coefficients are in absolute value equal, so change them to (-)1.0 */
4305       if( abscoefsequ )
4306       {
4307          SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficients are in absolute value the same\n", maxabsval);
4308          SCIPdebugPrintCons(scip, cons, NULL);
4309          SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
4310 
4311          if( consdata->validmaxabsval )
4312          {
4313             if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
4314                consdata->maxabsval = 1.0;
4315             if( !SCIPisEQ(scip, consdata->minabsval, 1.0) )
4316                consdata->minabsval = 1.0;
4317 
4318             maxabsval = 1.0;
4319          }
4320          else
4321          {
4322             /* get maximal absolute coefficient */
4323             maxabsval = consdataGetMaxAbsval(consdata);
4324          }
4325 
4326          /* get new consdata information, because scaleCons() might have deleted variables */
4327          vals = consdata->vals;
4328          nvars = consdata->nvars;
4329 
4330          assert(nvars == 0 || vals != NULL);
4331       }
4332    }
4333 
4334    /* nvars might have changed */
4335    if( nvars == 0 )
4336    {
4337       consdata->normalized = TRUE;
4338       return SCIP_OKAY;
4339    }
4340 
4341    assert(vals != NULL);
4342 
4343    /* calculate the maximal multiplier for common divisor calculation:
4344     *   |p/q - val| < epsilon  and  q < feastol/epsilon  =>  |p - q*val| < feastol
4345     * which means, a value of feastol/epsilon should be used as maximal multiplier;
4346     * additionally, we don't want to scale the constraint if this would lead to too
4347     * large coefficients
4348     */
4349    epsilon = SCIPepsilon(scip) * 0.9;  /* slightly decrease epsilon to be safe in rational conversion below */
4350    feastol = SCIPfeastol(scip);
4351    maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4352 
4353    if( !consdata->hasnonbinvalid )
4354       consdataCheckNonbinvar(consdata);
4355 
4356    /* if all variables are of integral type we will allow a greater multiplier */
4357    if( !consdata->hascontvar )
4358       maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEFINTEGER / MAX(maxabsval, 1.0))); /*lint !e835*/
4359    else
4360       maxmult = MIN(maxmult, (SCIP_Longint) (MAXSCALEDCOEF / MAX(maxabsval, 1.0))); /*lint !e835*/
4361 
4362    /*
4363     * multiplication with +1 or -1
4364     */
4365    mult = 0;
4366 
4367    /* 1. the right hand side must not be negative */
4368    if( SCIPisPositive(scip, consdata->lhs) )
4369       mult = +1;
4370    else if( SCIPisNegative(scip, consdata->rhs) )
4371       mult = -1;
4372 
4373    if( mult == 0 )
4374    {
4375       /* 2. the right hand side must not be infinite */
4376       if( SCIPisInfinity(scip, -consdata->lhs) )
4377          mult = +1;
4378       else if( SCIPisInfinity(scip, consdata->rhs) )
4379          mult = -1;
4380    }
4381 
4382    if( mult == 0 )
4383    {
4384       /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4385       if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4386          mult = +1;
4387       else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4388          mult = -1;
4389    }
4390 
4391    if( mult == 0 )
4392    {
4393       /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4394       nposcoeffs = 0;
4395       nnegcoeffs = 0;
4396       for( i = 0; i < nvars; ++i )
4397       {
4398          if( vals[i] > 0.0 )
4399             nposcoeffs++;
4400          else
4401             nnegcoeffs++;
4402       }
4403       if( nposcoeffs > nnegcoeffs )
4404          mult = +1;
4405       else if( nposcoeffs < nnegcoeffs )
4406          mult = -1;
4407    }
4408 
4409    if( mult == 0 )
4410    {
4411       /* 5. multiply with +1 */
4412       mult = +1;
4413    }
4414 
4415    assert(mult == +1 || mult == -1);
4416    if( mult == -1 )
4417    {
4418       /* scale the constraint with -1 */
4419       SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4420       SCIPdebugPrintCons(scip, cons, NULL);
4421       SCIP_CALL( scaleCons(scip, cons, -1.0) );
4422 
4423       /* scalecons() can delete variables, but scaling with -1 should not do that */
4424       assert(nvars == consdata->nvars);
4425    }
4426 
4427    /*
4428     * rationals to integrals
4429     *
4430     * @todo try scaling only on behalf of non-continuous variables
4431     */
4432    success = TRUE;
4433    scm = 1;
4434    for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4435    {
4436       if( !SCIPisIntegral(scip, vals[i]) )
4437       {
4438          /* epsilon has been slightly decreased above - to be on the safe side */
4439          success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4440          if( success )
4441             scm = SCIPcalcSmaComMul(scm, denominator);
4442       }
4443    }
4444    assert(scm >= 1);
4445 
4446    /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4447     * their greatest common divisor
4448     */
4449    onlyintegral = TRUE;
4450    if( scm == 1 )
4451    {
4452       for( i = nvars - 1; i >= 0; --i )
4453       {
4454          if( !SCIPisIntegral(scip, vals[i]) )
4455          {
4456             onlyintegral = FALSE;
4457             break;
4458          }
4459       }
4460    }
4461 
4462    success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4463    if( success && scm != 1 )
4464    {
4465       /* scale the constraint with the smallest common multiple of all denominators */
4466       SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4467       SCIPdebugPrintCons(scip, cons, NULL);
4468       SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4469 
4470       if( consdata->validmaxabsval )
4471       {
4472          consdata->maxabsval *= REALABS((SCIP_Real)scm);
4473          if( !SCIPisIntegral(scip, consdata->maxabsval) )
4474          {
4475             consdata->validmaxabsval = FALSE;
4476             consdata->maxabsval = SCIP_INVALID;
4477             consdataCalcMaxAbsval(consdata);
4478          }
4479       }
4480 
4481       if( consdata->validminabsval )
4482       {
4483          consdata->minabsval *= REALABS((SCIP_Real)scm);
4484          if( !SCIPisIntegral(scip, consdata->minabsval) )
4485          {
4486             consdata->validminabsval = FALSE;
4487             consdata->minabsval = SCIP_INVALID;
4488             consdataCalcMinAbsval(consdata);
4489          }
4490       }
4491 
4492       /* get new consdata information, because scalecons() might have deleted variables */
4493       vals = consdata->vals;
4494       nvars = consdata->nvars;
4495       assert(nvars == 0 || vals != NULL);
4496    }
4497 
4498    /*
4499     * division by greatest common divisor
4500     */
4501    if( success && nvars >= 1 )
4502    {
4503       /* all coefficients are integral: divide them by their greatest common divisor */
4504       assert(SCIPisIntegral(scip, vals[0]));
4505 
4506       gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4507       for( i = 1; i < nvars && gcd > 1; ++i )
4508       {
4509          assert(SCIPisIntegral(scip, vals[i]));
4510          gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4511       }
4512 
4513       if( gcd > 1 )
4514       {
4515          /* since the lhs/rhs is not respected for gcd calculation it can happen that we detect infeasibility */
4516          if( !consdata->hascontvar && onlyintegral )
4517          {
4518             if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) && !SCIPisFeasIntegral(scip, consdata->rhs / gcd) )
4519             {
4520                *infeasible = TRUE;
4521 
4522                SCIPdebugMsg(scip, "detected infeasibility of constraint after scaling with gcd=%" SCIP_LONGINT_FORMAT ":\n", gcd);
4523                SCIPdebugPrintCons(scip, cons, NULL);
4524 
4525                return SCIP_OKAY;
4526             }
4527          }
4528 
4529          /* divide the constraint by the greatest common divisor of the coefficients */
4530          SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4531          SCIPdebugPrintCons(scip, cons, NULL);
4532          SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4533 
4534          if( consdata->validmaxabsval )
4535          {
4536             consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4537          }
4538          if( consdata->validminabsval )
4539          {
4540             consdata->minabsval /= REALABS((SCIP_Real)gcd);
4541          }
4542       }
4543    }
4544 
4545    /* mark constraint to be normalized */
4546    consdata->normalized = TRUE;
4547 
4548    SCIPdebugMsg(scip, "normalized constraint:\n");
4549    SCIPdebugPrintCons(scip, cons, NULL);
4550 
4551    return SCIP_OKAY;
4552 }
4553 
4554 /** replaces multiple occurrences of a variable by a single coefficient */
4555 static
mergeMultiples(SCIP * scip,SCIP_CONS * cons)4556 SCIP_RETCODE mergeMultiples(
4557    SCIP*                 scip,               /**< SCIP data structure */
4558    SCIP_CONS*            cons                /**< linear constraint */
4559    )
4560 {
4561    SCIP_CONSDATA* consdata;
4562    SCIP_VAR* var;
4563    SCIP_Real valsum;
4564    int v;
4565 
4566    assert(scip != NULL);
4567    assert(cons != NULL);
4568 
4569    consdata = SCIPconsGetData(cons);
4570    assert(consdata != NULL);
4571 
4572    if( consdata->merged )
4573       return SCIP_OKAY;
4574 
4575    /* sort the constraint */
4576    SCIP_CALL( consdataSort(scip, consdata) );
4577 
4578    /* go backwards through the constraint looking for multiple occurrences of the same variable;
4579     * backward direction is necessary, since delCoefPos() modifies the given position and
4580     * the subsequent ones
4581     */
4582    v = consdata->nvars-1;
4583    while( v >= 1 )
4584    {
4585       var = consdata->vars[v];
4586       if( consdata->vars[v-1] == var )
4587       {
4588          valsum = consdata->vals[v];
4589          do
4590          {
4591             SCIP_CALL( delCoefPos(scip, cons, v) );
4592             --v;
4593             valsum += consdata->vals[v];
4594          }
4595          while( v >= 1 && consdata->vars[v-1] == var );
4596 
4597          /* modify the last existing occurrence of the variable */
4598          assert(consdata->vars[v] == var);
4599          if( SCIPisZero(scip, valsum) )
4600          {
4601             SCIP_CALL( delCoefPos(scip, cons, v) );
4602 
4603             /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4604              * delta needs to be recalculated on the next real propagation
4605              */
4606             if( consdata->maxactdeltavar == var )
4607             {
4608                consdata->maxactdelta = SCIP_INVALID;
4609                consdata->maxactdeltavar = NULL;
4610             }
4611          }
4612          else
4613          {
4614             SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4615          }
4616       }
4617       --v;
4618    }
4619 
4620    consdata->merged = TRUE;
4621 
4622    return SCIP_OKAY;
4623 }
4624 
4625 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4626 static
applyFixings(SCIP * scip,SCIP_CONS * cons,SCIP_Bool * infeasible)4627 SCIP_RETCODE applyFixings(
4628    SCIP*                 scip,               /**< SCIP data structure */
4629    SCIP_CONS*            cons,               /**< linear constraint */
4630    SCIP_Bool*            infeasible          /**< pointer to store if infeasibility is detected; or NULL if this
4631                                               *   information is not needed; in this case, we apply all fixings
4632                                               *   instead of stopping after the first infeasible one */
4633    )
4634 {
4635    SCIP_CONSDATA* consdata;
4636    SCIP_VAR* var;
4637    SCIP_VAR** aggrvars;
4638    SCIP_Real val;
4639    SCIP_Real* aggrscalars;
4640    SCIP_Real fixedval;
4641    SCIP_Real aggrconst;
4642    int v;
4643    int naggrvars;
4644    int i;
4645 
4646    assert(scip != NULL);
4647    assert(cons != NULL);
4648 
4649    if( infeasible != NULL )
4650       *infeasible = FALSE;
4651 
4652    consdata = SCIPconsGetData(cons);
4653    assert(consdata != NULL);
4654 
4655    if( consdata->eventdata == NULL )
4656    {
4657       SCIP_CONSHDLR* conshdlr;
4658       SCIP_CONSHDLRDATA* conshdlrdata;
4659 
4660       conshdlr = SCIPconsGetHdlr(cons);
4661       assert(conshdlr != NULL);
4662 
4663       conshdlrdata = SCIPconshdlrGetData(conshdlr);
4664       assert(conshdlrdata != NULL);
4665 
4666       /* catch bound change events of variables */
4667       SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
4668       assert(consdata->eventdata != NULL);
4669    }
4670 
4671    if( !consdata->removedfixings )
4672    {
4673       SCIP_Real lhssubtrahend;
4674       SCIP_Real rhssubtrahend;
4675 
4676       /* if an unmodifiable row has been added to the LP, then we cannot apply fixing anymore (cannot change a row)
4677        * this should not happen, as applyFixings is called in addRelaxation() before creating and adding a row
4678        */
4679       assert(consdata->row == NULL || !SCIProwIsInLP(consdata->row) || SCIProwIsModifiable(consdata->row));
4680 
4681       lhssubtrahend = 0.0;
4682       rhssubtrahend = 0.0;
4683 
4684       SCIPdebugMsg(scip, "applying fixings:\n");
4685       SCIPdebugPrintCons(scip, cons, NULL);
4686 
4687       v = 0;
4688       while( v < consdata->nvars )
4689       {
4690          var = consdata->vars[v];
4691          val = consdata->vals[v];
4692          assert(SCIPvarIsTransformed(var));
4693 
4694          switch( SCIPvarGetStatus(var) )
4695          {
4696          case SCIP_VARSTATUS_ORIGINAL:
4697             SCIPerrorMessage("original variable in transformed linear constraint\n");
4698             return SCIP_INVALIDDATA;
4699 
4700          case SCIP_VARSTATUS_LOOSE:
4701          case SCIP_VARSTATUS_COLUMN:
4702             ++v;
4703             break;
4704 
4705          case SCIP_VARSTATUS_FIXED:
4706             assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4707             fixedval = SCIPvarGetLbGlobal(var);
4708             if( !SCIPisInfinity(scip, -consdata->lhs) )
4709             {
4710                if( SCIPisInfinity(scip, ABS(fixedval)) )
4711                {
4712                   if( val * fixedval > 0.0 )
4713                   {
4714                      SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4715                   }
4716                   else
4717                   {
4718                      if( infeasible != NULL )
4719                      {
4720                         /* if lhs gets infinity it means that the problem is infeasible */
4721                         *infeasible = TRUE;
4722                         return SCIP_OKAY;
4723                      }
4724                      else
4725                      {
4726                         SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4727                      }
4728                   }
4729                }
4730                else
4731                   lhssubtrahend += val * fixedval;
4732             }
4733             if( !SCIPisInfinity(scip, consdata->rhs) )
4734             {
4735                if( SCIPisInfinity(scip, ABS(fixedval)) )
4736                {
4737                   if( val * fixedval > 0.0 )
4738                   {
4739                      if( infeasible != NULL )
4740                      {
4741                         /* if rhs gets -infinity it means that the problem is infeasible */
4742                         *infeasible = TRUE;
4743                         return SCIP_OKAY;
4744                      }
4745                      else
4746                      {
4747                         SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4748                      }
4749                   }
4750                   else
4751                   {
4752                      SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4753                   }
4754                }
4755                else
4756                   rhssubtrahend += val * fixedval;
4757             }
4758             SCIP_CALL( delCoefPos(scip, cons, v) );
4759             break;
4760 
4761          case SCIP_VARSTATUS_AGGREGATED:
4762 	 {
4763 	    SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4764 	    SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4765 	    SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4766 
4767 	    assert(activevar != NULL);
4768 	    SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4769 	    assert(activevar != NULL);
4770 
4771 	    if( !SCIPisZero(scip, activescalar) )
4772 	    {
4773 	       SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4774 	    }
4775 
4776 	    if( !SCIPisZero(scip, activeconstant) )
4777 	    {
4778 	       if( !SCIPisInfinity(scip, -consdata->lhs) )
4779 		  lhssubtrahend += activeconstant;
4780 	       if( !SCIPisInfinity(scip, consdata->rhs) )
4781 		  rhssubtrahend += activeconstant;
4782 	    }
4783 
4784             SCIP_CALL( delCoefPos(scip, cons, v) );
4785             break;
4786 	 }
4787          case SCIP_VARSTATUS_MULTAGGR:
4788             SCIP_CALL( SCIPflattenVarAggregationGraph(scip, var) );
4789             naggrvars = SCIPvarGetMultaggrNVars(var);
4790             aggrvars = SCIPvarGetMultaggrVars(var);
4791             aggrscalars = SCIPvarGetMultaggrScalars(var);
4792             for( i = 0; i < naggrvars; ++i )
4793             {
4794                SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4795             }
4796             aggrconst = SCIPvarGetMultaggrConstant(var);
4797 
4798             if( !SCIPisInfinity(scip, -consdata->lhs) )
4799                lhssubtrahend += val * aggrconst;
4800             if( !SCIPisInfinity(scip, consdata->rhs) )
4801                rhssubtrahend += val * aggrconst;
4802 
4803             SCIP_CALL( delCoefPos(scip, cons, v) );
4804             break;
4805 
4806          case SCIP_VARSTATUS_NEGATED:
4807             SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4808             aggrconst = SCIPvarGetNegationConstant(var);
4809 
4810             if( !SCIPisInfinity(scip, -consdata->lhs) )
4811                lhssubtrahend += val * aggrconst;
4812             if( !SCIPisInfinity(scip, consdata->rhs) )
4813                rhssubtrahend += val * aggrconst;
4814 
4815             SCIP_CALL( delCoefPos(scip, cons, v) );
4816             break;
4817 
4818          default:
4819             SCIPerrorMessage("unknown variable status\n");
4820             SCIPABORT();
4821             return SCIP_INVALIDDATA;  /*lint !e527*/
4822          }
4823       }
4824 
4825       if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4826       {
4827          /* for large numbers that are relatively equal, substraction can lead to cancellation,
4828           * causing wrong fixings of other variables --> better use a real zero here;
4829           * for small numbers, polishing the difference might lead to wrong results -->
4830           * better use the exact difference in this case
4831           */
4832          if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4833          {
4834             SCIP_CALL( chgLhs(scip, cons, 0.0) );
4835          }
4836          else
4837          {
4838             SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4839          }
4840       }
4841       if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4842       {
4843          /* for large numbers that are relatively equal, substraction can lead to cancellation,
4844           * causing wrong fixings of other variables --> better use a real zero here;
4845           * for small numbers, polishing the difference might lead to wrong results -->
4846           * better use the exact difference in this case
4847           */
4848          if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4849          {
4850             SCIP_CALL( chgRhs(scip, cons, 0.0) );
4851          }
4852          else
4853          {
4854             SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4855          }
4856       }
4857       consdata->removedfixings = TRUE;
4858 
4859       SCIPdebugMsg(scip, "after fixings:\n");
4860       SCIPdebugPrintCons(scip, cons, NULL);
4861 
4862       /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4863        * to clean up the constraint
4864        */
4865       SCIP_CALL( mergeMultiples(scip, cons) );
4866 
4867       SCIPdebugMsg(scip, "after merging:\n");
4868       SCIPdebugPrintCons(scip, cons, NULL);
4869    }
4870    assert(consdata->removedfixings);
4871 
4872 #ifndef NDEBUG
4873    /* check, if all fixings are applied */
4874    for( v = 0; v < consdata->nvars; ++v )
4875       assert(SCIPvarIsActive(consdata->vars[v]));
4876 #endif
4877 
4878    return SCIP_OKAY;
4879 }
4880 
4881 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4882  *  candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4883  *  inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4884  *  conflict detecting constraint by using NULL as inferred variable
4885  */
4886 static
addConflictBounds(SCIP * scip,SCIP_CONS * cons,SCIP_VAR * infervar,SCIP_BDCHGIDX * bdchgidx,int inferpos,SCIP_Bool reasonisrhs)4887 SCIP_RETCODE addConflictBounds(
4888    SCIP*                 scip,               /**< SCIP data structure */
4889    SCIP_CONS*            cons,               /**< constraint that inferred the bound change */
4890    SCIP_VAR*             infervar,           /**< variable that was deduced, or NULL */
4891    SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index (time stamp of bound change), or NULL for current time */
4892    int                   inferpos,           /**< position of the inferred variable in the vars array */
4893    SCIP_Bool             reasonisrhs         /**< is the right hand side responsible for the bound change? */
4894    )
4895 {
4896    SCIP_CONSDATA* consdata;
4897    SCIP_VAR** vars;
4898    SCIP_Real* vals;
4899    int nvars;
4900    int i;
4901 
4902    assert(scip != NULL);
4903    assert(cons != NULL);
4904 
4905    consdata = SCIPconsGetData(cons);
4906 
4907    assert(consdata != NULL);
4908 
4909    vars = consdata->vars;
4910    vals = consdata->vals;
4911    nvars = consdata->nvars;
4912 
4913    assert(vars != NULL || nvars == 0);
4914    assert(vals != NULL || nvars == 0);
4915 
4916    assert(-1 <= inferpos && inferpos < nvars);
4917    assert((infervar == NULL) == (inferpos == -1));
4918    assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4919 
4920    /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4921     * residual value, depending on whether the left or right hand side is responsible for the bound change:
4922     *  - if the right hand side is the reason, the minimal residual activity is responsible
4923     *  - if the left hand side is the reason, the maximal residual activity is responsible
4924     */
4925 
4926    /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4927    if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4928    {
4929       SCIP_Real minresactivity;
4930       SCIP_Real maxresactivity;
4931       SCIP_Bool minisrelax;
4932       SCIP_Bool maxisrelax;
4933       SCIP_Bool isminsettoinfinity;
4934       SCIP_Bool ismaxsettoinfinity;
4935 
4936       minresactivity = -SCIPinfinity(scip);
4937       maxresactivity = SCIPinfinity(scip);
4938 
4939       /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4940       if( infervar != NULL )
4941       {
4942          assert(vals != NULL); /* for flexelint */
4943          if( reasonisrhs )
4944             consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4945                &minisrelax, NULL, &isminsettoinfinity, NULL);
4946          else
4947             consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4948                NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4949       }
4950       else
4951       {
4952          if( reasonisrhs )
4953             consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4954                &minisrelax, NULL, &isminsettoinfinity, NULL);
4955          else
4956             consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4957                NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4958       }
4959 
4960       /* we can only do something clever, if the residual activity is finite and not relaxed */
4961       if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4962       {
4963          SCIP_Real rescap;
4964          SCIP_Bool resactisinf;
4965 
4966          resactisinf = FALSE;
4967 
4968          /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4969           * than its inferred bound
4970           */
4971          if( infervar != NULL )
4972          {
4973             assert(vals != NULL); /* for flexelint */
4974 
4975             if( reasonisrhs )
4976             {
4977                if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4978                {
4979                   consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4980                   if( SCIPisInfinity(scip, -minresactivity) )
4981                      resactisinf = TRUE;
4982                }
4983                rescap = consdata->rhs - minresactivity;
4984             }
4985             else
4986             {
4987                if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4988                {
4989                   consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4990                   if( SCIPisInfinity(scip, maxresactivity) )
4991                      resactisinf = TRUE;
4992                }
4993                rescap = consdata->lhs - maxresactivity;
4994             }
4995 
4996             if( reasonisrhs == (vals[inferpos] > 0.0) )
4997                rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4998             else
4999                rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
5000          }
5001          else
5002             rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
5003 
5004          if( !resactisinf )
5005          {
5006             /* now add bounds as reasons until the residual capacity is exceeded */
5007             for( i = 0; i < nvars; ++i )
5008             {
5009                assert( vars != NULL && vals != NULL ); /* for lint */
5010 
5011                /* zero coefficients and the infered variable can be ignored */
5012                if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5013                   continue;
5014 
5015                /* check if the residual capacity is exceeded */
5016                if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
5017                   || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
5018                   break;
5019 
5020                /* update the residual capacity due to the local bound of this variable */
5021                if( reasonisrhs == (vals[i] > 0.0) )
5022                {
5023                   /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
5024                   SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5025                   rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
5026                }
5027                else
5028                {
5029                   /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
5030                   SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5031                   rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
5032                }
5033             }
5034             return SCIP_OKAY;
5035          }
5036       }
5037    }
5038 
5039    /* for a bound change on a continuous variable, all locally changed bounds are responsible */
5040    for( i = 0; i < nvars; ++i )
5041    {
5042       assert(vars != NULL); /* for flexelint */
5043       assert(vals != NULL); /* for flexelint */
5044 
5045       /* zero coefficients and the infered variable can be ignored */
5046       if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
5047          continue;
5048 
5049       if( reasonisrhs == (vals[i] > 0.0) )
5050       {
5051          /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
5052          SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
5053       }
5054       else
5055       {
5056          /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
5057          SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
5058       }
5059    }
5060 
5061    return SCIP_OKAY;
5062 }
5063 
5064 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
5065  *  variables to the conflict analysis' candidate store; the conflict analysis can be initialized
5066  *  with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
5067  */
5068 static
addConflictFixedVars(SCIP * scip,SCIP_CONS * cons,SCIP_VAR * infervar,SCIP_BDCHGIDX * bdchgidx,int inferpos)5069 SCIP_RETCODE addConflictFixedVars(
5070    SCIP*                 scip,               /**< SCIP data structure */
5071    SCIP_CONS*            cons,               /**< constraint that inferred the bound change */
5072    SCIP_VAR*             infervar,           /**< variable that was deduced, or NULL */
5073    SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index (time stamp of bound change), or NULL for current time */
5074    int                   inferpos            /**< position of the inferred variable in the vars array, or -1 */
5075    )
5076 {
5077    SCIP_CONSDATA* consdata;
5078    SCIP_VAR** vars;
5079    int nvars;
5080    int v;
5081 
5082    assert(scip != NULL);
5083    assert(cons != NULL);
5084 
5085    consdata = SCIPconsGetData(cons);
5086    assert(consdata != NULL);
5087    vars = consdata->vars;
5088    nvars = consdata->nvars;
5089    assert(vars != NULL || nvars == 0);
5090    assert(-1 <= inferpos && inferpos < nvars);
5091    assert((infervar == NULL) == (inferpos == -1));
5092    assert(inferpos == -1 || vars != NULL);
5093    assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
5094 
5095    /* collect all fixed variables */
5096    for( v = nvars - 1; v >= 0; --v )
5097    {
5098       assert(vars != NULL); /* for flexelint */
5099 
5100       /* need to add old bounds before propagation of inferrence variable */
5101       if( vars[v] == infervar )
5102       {
5103 	 assert(vars[v] != NULL);
5104 
5105 	 if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
5106 	 {
5107 	    /* @todo get boundchange index before this last boundchange and correct the index */
5108 	    SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5109 	 }
5110 
5111 	 if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
5112 	 {
5113 	    /* @todo get boundchange index before this last boundchange and correct the index */
5114 	    SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5115 	 }
5116 
5117 	 continue;
5118       }
5119 
5120       /* check for fixed variables */
5121       if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
5122       {
5123 	 /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
5124          SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
5125          SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
5126       }
5127    }
5128 
5129    return SCIP_OKAY;
5130 }
5131 
5132 /** add reasoning variables to conflict candidate queue which led to the conflict */
5133 static
addConflictReasonVars(SCIP * scip,SCIP_VAR ** vars,int nvars,SCIP_VAR * var,SCIP_Real bound)5134 SCIP_RETCODE addConflictReasonVars(
5135    SCIP*                 scip,               /**< SCIP data structure */
5136    SCIP_VAR**            vars,               /**< variables reasoning the infeasibility */
5137    int                   nvars,              /**< number of variables reasoning the infeasibility */
5138    SCIP_VAR*             var,                /**< variable which was tried to fix/tighten, or NULL */
5139    SCIP_Real             bound               /**< bound of variable which was tried to apply, or SCIP_INVALID */
5140    )
5141 {
5142    int v;
5143 
5144    assert(scip != NULL);
5145 
5146    /* collect all variables for which the local bounds differ from their global bounds */
5147    for( v = nvars - 1; v >= 0; --v )
5148    {
5149       assert(vars != NULL);
5150 
5151       /* check for local bound changes variables */
5152       if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5153       {
5154 	 /* add conflict bound */
5155          SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5156       }
5157 
5158       if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5159       {
5160          SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5161       }
5162    }
5163 
5164    if( var != NULL )
5165    {
5166       if( bound < SCIPvarGetLbLocal(var) )
5167       {
5168          SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5169       }
5170 
5171       if( bound > SCIPvarGetUbLocal(var) )
5172       {
5173          SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5174       }
5175    }
5176 
5177    return SCIP_OKAY;
5178 }
5179 
5180 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5181  *  propagation rule (see propagateCons()):
5182  *   (1) activity residuals of all other variables tighten bounds of single variable
5183  */
5184 static
resolvePropagation(SCIP * scip,SCIP_CONS * cons,SCIP_VAR * infervar,INFERINFO inferinfo,SCIP_BOUNDTYPE boundtype,SCIP_BDCHGIDX * bdchgidx,SCIP_RESULT * result)5185 SCIP_RETCODE resolvePropagation(
5186    SCIP*                 scip,               /**< SCIP data structure */
5187    SCIP_CONS*            cons,               /**< constraint that inferred the bound change */
5188    SCIP_VAR*             infervar,           /**< variable that was deduced */
5189    INFERINFO             inferinfo,          /**< inference information */
5190    SCIP_BOUNDTYPE        boundtype,          /**< the type of the changed bound (lower or upper bound) */
5191    SCIP_BDCHGIDX*        bdchgidx,           /**< bound change index (time stamp of bound change), or NULL for current time */
5192    SCIP_RESULT*          result              /**< pointer to store the result of the propagation conflict resolving call */
5193    )
5194 {
5195    SCIP_CONSDATA* consdata;
5196    SCIP_VAR** vars;
5197 #ifndef NDEBUG
5198    SCIP_Real* vals;
5199 #endif
5200    int nvars;
5201    int inferpos;
5202 
5203    assert(scip != NULL);
5204    assert(cons != NULL);
5205    assert(result != NULL);
5206 
5207    consdata = SCIPconsGetData(cons);
5208    assert(consdata != NULL);
5209    vars = consdata->vars;
5210    nvars = consdata->nvars;
5211 #ifndef NDEBUG
5212    vals = consdata->vals;
5213    assert(vars != NULL);
5214    assert(vals != NULL);
5215 #endif
5216 
5217    /* get the position of the inferred variable in the vars array */
5218    inferpos = inferInfoGetPos(inferinfo);
5219    if( inferpos >= nvars || vars[inferpos] != infervar )
5220    {
5221       /* find inference variable in constraint */
5222       /**@todo use a binary search here; the variables can be sorted by variable index */
5223       for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5224       {}
5225    }
5226    assert(inferpos < nvars);
5227    assert(vars[inferpos] == infervar);
5228    assert(!SCIPisZero(scip, vals[inferpos]));
5229 
5230    switch( inferInfoGetProprule(inferinfo) )
5231    {
5232    case PROPRULE_1_RHS:
5233       /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5234        * constraint (only taking the other variables into account) didn't leave enough space for a larger
5235        * domain in order to not exceed the right hand side of the inequality
5236        */
5237       assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5238       SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5239       *result = SCIP_SUCCESS;
5240       break;
5241 
5242    case PROPRULE_1_LHS:
5243       /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5244        * constraint (only taking the other variables into account) didn't leave enough space for a larger
5245        * domain in order to not fall below the left hand side of the inequality
5246        */
5247       assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5248       SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5249       *result = SCIP_SUCCESS;
5250       break;
5251 
5252    case PROPRULE_1_RANGEDROW:
5253       /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5254        * the given inference variable to their bounds in this given ranged row
5255        */
5256 
5257       /* check that we really have a ranged row here */
5258       assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5259       SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5260       *result = SCIP_SUCCESS;
5261       break;
5262 
5263    case PROPRULE_INVALID:
5264    default:
5265       SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5266          inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5267          boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5268       SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5269       SCIPinfoMessage(scip, NULL, ";\n");
5270       return SCIP_INVALIDDATA;
5271    }
5272 
5273    return SCIP_OKAY;
5274 }
5275 
5276 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5277 static
analyzeConflict(SCIP * scip,SCIP_CONS * cons,SCIP_Bool reasonisrhs)5278 SCIP_RETCODE analyzeConflict(
5279    SCIP*                 scip,               /**< SCIP data structure */
5280    SCIP_CONS*            cons,               /**< conflict detecting constraint */
5281    SCIP_Bool             reasonisrhs         /**< is the right hand side responsible for the conflict? */
5282    )
5283 {
5284    /* conflict analysis can only be applied in solving stage and if it is turned on */
5285    if( (SCIPgetStage(scip) != SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) || !SCIPisConflictAnalysisApplicable(scip) )
5286       return SCIP_OKAY;
5287 
5288    /* initialize conflict analysis */
5289    SCIP_CALL( SCIPinitConflictAnalysis(scip, SCIP_CONFTYPE_PROPAGATION, FALSE) );
5290 
5291    /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5292    SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5293 
5294    /* analyze the conflict */
5295    SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5296 
5297    return SCIP_OKAY;
5298 }
5299 
5300 /** check if there is any hope of tightening some bounds */
5301 static
canTightenBounds(SCIP_CONS * cons)5302 SCIP_Bool canTightenBounds(
5303    SCIP_CONS*            cons                /**< linear constraint */
5304    )
5305 {
5306    SCIP_CONSDATA* consdata;
5307    int infcountmin;
5308    int infcountmax;
5309 
5310    consdata = SCIPconsGetData(cons);
5311    assert(consdata != NULL);
5312 
5313    infcountmin = consdata->minactivityneginf
5314       + consdata->minactivityposinf
5315       + consdata->minactivityneghuge
5316       + consdata->minactivityposhuge;
5317    infcountmax = consdata->maxactivityneginf
5318       + consdata->maxactivityposinf
5319       + consdata->maxactivityneghuge
5320       + consdata->maxactivityposhuge;
5321 
5322    if( infcountmin > 1 && infcountmax > 1 )
5323       return FALSE;
5324 
5325    return TRUE;
5326 }
5327 
5328 /** tighten upper bound */
5329 static
tightenVarUb(SCIP * scip,SCIP_CONS * cons,int pos,PROPRULE proprule,SCIP_Real newub,SCIP_Real oldub,SCIP_Bool * cutoff,int * nchgbds,SCIP_Bool force)5330 SCIP_RETCODE tightenVarUb(
5331    SCIP*                 scip,               /**< SCIP data structure */
5332    SCIP_CONS*            cons,               /**< linear constraint */
5333    int                   pos,                /**< variable position */
5334    PROPRULE              proprule,           /**< propagation rule that deduced the value */
5335    SCIP_Real             newub,              /**< new upper bound */
5336    SCIP_Real             oldub,              /**< old upper bound */
5337    SCIP_Bool*            cutoff,             /**< pointer to store whether the node can be cut off */
5338    int*                  nchgbds,            /**< pointer to count the total number of tightened bounds */
5339    SCIP_Bool             force               /**< should a possible bound change be forced even if below bound strengthening tolerance */
5340    )
5341 {
5342    SCIP_CONSDATA* consdata;
5343    SCIP_VAR* var;
5344    SCIP_Real lb;
5345    SCIP_Bool infeasible;
5346    SCIP_Bool tightened;
5347 
5348    assert(cons != NULL);
5349    assert(!SCIPisInfinity(scip, newub));
5350 
5351    consdata = SCIPconsGetData(cons);
5352    assert(consdata != NULL);
5353    var = consdata->vars[pos];
5354    assert(var != NULL);
5355 
5356    lb = SCIPvarGetLbLocal(var);
5357    newub = SCIPadjustedVarUb(scip, var, newub);
5358 
5359    if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5360    {
5361       SCIP_VARTYPE vartype;
5362 
5363       SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5364          SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newub);
5365 
5366       vartype = SCIPvarGetType(var);
5367 
5368       /* tighten upper bound */
5369       SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5370 
5371       if( infeasible )
5372       {
5373          SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, new bds=[%.15g,%.15g]\n",
5374             SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5375 
5376          /* analyze conflict */
5377          SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5378 
5379          *cutoff = TRUE;
5380       }
5381       else if( tightened )
5382       {
5383          assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5384          SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5385             SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5386 
5387          (*nchgbds)++;
5388 
5389          /* if variable type was changed we might be able to upgrade the constraint */
5390          if( vartype != SCIPvarGetType(var) )
5391             consdata->upgradetried = FALSE;
5392       }
5393    }
5394    return SCIP_OKAY;
5395 }
5396 
5397 /** tighten lower bound */
5398 static
tightenVarLb(SCIP * scip,SCIP_CONS * cons,int pos,PROPRULE proprule,SCIP_Real newlb,SCIP_Real oldlb,SCIP_Bool * cutoff,int * nchgbds,SCIP_Bool force)5399 SCIP_RETCODE tightenVarLb(
5400    SCIP*                 scip,               /**< SCIP data structure */
5401    SCIP_CONS*            cons,               /**< linear constraint */
5402    int                   pos,                /**< variable position */
5403    PROPRULE              proprule,           /**< propagation rule that deduced the value */
5404    SCIP_Real             newlb,              /**< new lower bound */
5405    SCIP_Real             oldlb,              /**< old lower bound */
5406    SCIP_Bool*            cutoff,             /**< pointer to store whether the node can be cut off */
5407    int*                  nchgbds,            /**< pointer to count the total number of tightened bounds */
5408    SCIP_Bool             force               /**< should a possible bound change be forced even if below bound strengthening tolerance */
5409    )
5410 {
5411    SCIP_CONSDATA* consdata;
5412    SCIP_VAR* var;
5413    SCIP_Real ub;
5414    SCIP_Bool infeasible;
5415    SCIP_Bool tightened;
5416 
5417    assert(cons != NULL);
5418    assert(!SCIPisInfinity(scip, newlb));
5419 
5420    consdata = SCIPconsGetData(cons);
5421    assert(consdata != NULL);
5422    var = consdata->vars[pos];
5423    assert(var != NULL);
5424 
5425    ub = SCIPvarGetUbLocal(var);
5426    newlb = SCIPadjustedVarLb(scip, var, newlb);
5427 
5428    if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5429    {
5430       SCIP_VARTYPE vartype;
5431 
5432       SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5433          SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newlb);
5434 
5435       vartype = SCIPvarGetType(var);
5436 
5437       /* tighten lower bound */
5438       SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5439 
5440       if( infeasible )
5441       {
5442          SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, new bds=[%.15g,%.15g]\n",
5443             SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5444 
5445          /* analyze conflict */
5446          SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5447 
5448          *cutoff = TRUE;
5449       }
5450       else if( tightened )
5451       {
5452          assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5453          SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5454             SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5455 
5456          (*nchgbds)++;
5457 
5458          /* if variable type was changed we might be able to upgrade the constraint */
5459          if( vartype != SCIPvarGetType(var) )
5460             consdata->upgradetried = FALSE;
5461       }
5462    }
5463    return SCIP_OKAY;
5464 }
5465 
5466 /** tightens bounds of a single variable due to activity bounds (easy case) */
5467 static
tightenVarBoundsEasy(SCIP * scip,SCIP_CONS * cons,int pos,SCIP_Bool * cutoff,int * nchgbds,SCIP_Bool force)5468 SCIP_RETCODE tightenVarBoundsEasy(
5469    SCIP*                 scip,               /**< SCIP data structure */
5470    SCIP_CONS*            cons,               /**< linear constraint */
5471    int                   pos,                /**< position of the variable in the vars array */
5472    SCIP_Bool*            cutoff,             /**< pointer to store whether the node can be cut off */
5473    int*                  nchgbds,            /**< pointer to count the total number of tightened bounds */
5474    SCIP_Bool             force               /**< should a possible bound change be forced even if below bound strengthening tolerance */
5475    )
5476 {
5477    SCIP_CONSDATA* consdata;
5478    SCIP_VAR* var;
5479    SCIP_Real val;
5480    SCIP_Real lb;
5481    SCIP_Real ub;
5482    SCIP_Real lhs;
5483    SCIP_Real rhs;
5484 
5485    assert(scip != NULL);
5486    assert(cons != NULL);
5487    assert(cutoff != NULL);
5488    assert(nchgbds != NULL);
5489 
5490    /* we cannot tighten variables' bounds, if the constraint may be not complete */
5491    if( SCIPconsIsModifiable(cons) )
5492       return SCIP_OKAY;
5493 
5494    consdata = SCIPconsGetData(cons);
5495    assert(consdata != NULL);
5496    assert(0 <= pos && pos < consdata->nvars);
5497 
5498    *cutoff = FALSE;
5499 
5500    var = consdata->vars[pos];
5501    assert(var != NULL);
5502 
5503    /* we cannot tighten bounds of multi-aggregated variables */
5504    if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
5505       return SCIP_OKAY;
5506 
5507    val = consdata->vals[pos];
5508    lhs = consdata->lhs;
5509    rhs = consdata->rhs;
5510    assert(!SCIPisZero(scip, val));
5511    assert(!SCIPisInfinity(scip, lhs));
5512    assert(!SCIPisInfinity(scip, -rhs));
5513 
5514    lb = SCIPvarGetLbLocal(var);
5515    ub = SCIPvarGetUbLocal(var);
5516    assert(SCIPisLE(scip, lb, ub));
5517 
5518    /* recompute activities if needed */
5519    if( !consdata->validactivities )
5520       consdataCalcActivities(scip, consdata);
5521    assert(consdata->validactivities);
5522    if( !consdata->validminact )
5523       consdataRecomputeMinactivity(scip, consdata);
5524    assert(consdata->validminact);
5525 
5526    if( val > 0.0 )
5527    {
5528       /* check, if we can tighten the variable's upper bound */
5529       if( !SCIPisInfinity(scip, rhs) )
5530       {
5531          SCIP_Real slack;
5532          SCIP_Real alpha;
5533 
5534          /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5535          assert(consdata->validminact);
5536 
5537          /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5538          if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5539          {
5540             SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, minactivity=%.15g > rhs=%.15g\n",
5541                SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5542 
5543             *cutoff = TRUE;
5544             return SCIP_OKAY;
5545          }
5546 
5547          slack = rhs - consdata->minactivity;
5548 
5549          /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5550           * it to zero
5551           */
5552          if( !SCIPisPositive(scip, slack) )
5553             slack = 0.0;
5554 
5555          alpha = val * (ub - lb);
5556          assert(!SCIPisNegative(scip, alpha));
5557 
5558          if( SCIPisSumGT(scip, alpha, slack)  || (force && SCIPisGT(scip, alpha, slack)) )
5559          {
5560             SCIP_Real newub;
5561 
5562             /* compute new upper bound */
5563             newub = lb + (slack / val);
5564 
5565             SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5566 
5567             if( *cutoff )
5568             {
5569                SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, new bds=[%.15g,%.15g]\n",
5570                   SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5571 
5572                return SCIP_OKAY;
5573             }
5574 
5575             /* collect the new upper bound which is needed for the lower bound computation */
5576             ub = SCIPvarGetUbLocal(var);
5577          }
5578       }
5579 
5580       /* check, if we can tighten the variable's lower bound */
5581       if( !SCIPisInfinity(scip, -lhs) )
5582       {
5583          SCIP_Real slack;
5584          SCIP_Real alpha;
5585 
5586          /* make sure the max activity is reliable */
5587          if( !consdata->validmaxact )
5588          {
5589             consdataRecomputeMaxactivity(scip, consdata);
5590          }
5591          assert(consdata->validmaxact);
5592 
5593 
5594          /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5595          if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5596          {
5597             SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, maxactivity=%.15g < lhs=%.15g\n",
5598                SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5599             *cutoff = TRUE;
5600             return SCIP_OKAY;
5601          }
5602 
5603          slack = consdata->maxactivity - lhs;
5604 
5605          /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5606           * it to zero
5607           */
5608          if( !SCIPisPositive(scip, slack) )
5609             slack = 0.0;
5610 
5611          alpha = val * (ub - lb);
5612          assert(!SCIPisNegative(scip, alpha));
5613 
5614          if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5615          {
5616             SCIP_Real newlb;
5617 
5618             /* compute new lower bound */
5619             newlb = ub - (slack / val);
5620 
5621             SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5622 
5623             if( *cutoff )
5624             {
5625                SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, new bds=[%.15g,%.15g]\n",
5626                   SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5627 
5628                return SCIP_OKAY;
5629             }
5630          }
5631       }
5632    }
5633    else
5634    {
5635       /* check, if we can tighten the variable's lower bound */
5636       if( !SCIPisInfinity(scip, rhs) )
5637       {
5638          SCIP_Real slack;
5639          SCIP_Real alpha;
5640 
5641          /* min activity should be valid at this point (if this is not true, then some decisions might be wrong!) */
5642          assert(consdata->validminact);
5643 
5644          /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5645          if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5646          {
5647             SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, minactivity=%.15g > rhs=%.15g\n",
5648                SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5649 
5650             *cutoff = TRUE;
5651             return SCIP_OKAY;
5652          }
5653 
5654          slack = rhs - consdata->minactivity;
5655 
5656          /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5657           * it to zero
5658           */
5659          if( !SCIPisPositive(scip, slack) )
5660             slack = 0.0;
5661 
5662          alpha = val * (lb - ub);
5663          assert(!SCIPisNegative(scip, alpha));
5664 
5665          if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5666          {
5667             SCIP_Real newlb;
5668 
5669             /* compute new lower bound */
5670             newlb = ub + slack / val;
5671 
5672             SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5673 
5674             if( *cutoff )
5675             {
5676                SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, new bds=[%.15g,%.15g]\n",
5677                   SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5678 
5679                return SCIP_OKAY;
5680             }
5681             /* collect the new lower bound which is needed for the upper bound computation */
5682             lb = SCIPvarGetLbLocal(var);
5683          }
5684       }
5685 
5686       /* check, if we can tighten the variable's upper bound */
5687       if( !SCIPisInfinity(scip, -lhs) )
5688       {
5689          SCIP_Real slack;
5690          SCIP_Real alpha;
5691 
5692          /* make sure the max activity is reliable */
5693          if( !consdata->validmaxact )
5694          {
5695             consdataRecomputeMaxactivity(scip, consdata);
5696          }
5697          assert(consdata->validmaxact);
5698 
5699          /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5700          if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5701          {
5702             SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, maxactivity=%.15g < lhs=%.15g\n",
5703                SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5704 
5705             *cutoff = TRUE;
5706             return SCIP_OKAY;
5707          }
5708 
5709          slack = consdata->maxactivity - lhs;
5710 
5711          /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5712           * it to zero
5713           */
5714          if( !SCIPisPositive(scip, slack) )
5715             slack = 0.0;
5716 
5717          alpha = val * (lb - ub);
5718          assert(!SCIPisNegative(scip, alpha));
5719 
5720          if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5721          {
5722             SCIP_Real newub;
5723 
5724             /* compute new upper bound */
5725             newub = lb - (slack / val);
5726 
5727             SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
5728 
5729             if( *cutoff )
5730             {
5731                SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, new bds=[%.15g,%.15g]\n",
5732                   SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5733 
5734                return SCIP_OKAY;
5735             }
5736          }
5737       }
5738    }
5739 
5740    return SCIP_OKAY;
5741 }
5742 
5743 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5744 static
analyzeConflictRangedRow(SCIP * scip,SCIP_CONS * cons,SCIP_VAR ** vars,int nvars,SCIP_VAR * var,SCIP_Real bound)5745 SCIP_RETCODE analyzeConflictRangedRow(
5746    SCIP*                 scip,               /**< SCIP data structure */
5747    SCIP_CONS*            cons,               /**< conflict detecting constraint */
5748    SCIP_VAR**            vars,               /**< variables reasoning the infeasibility */
5749    int                   nvars,              /**< number of variables reasoning the infeasibility */
5750    SCIP_VAR*             var,                /**< variable which was tried to fix/tighten, or NULL */
5751    SCIP_Real             bound               /**< bound of variable which was tried to apply, or SCIP_INVALID */
5752    )
5753 {
5754 #ifndef NDEBUG
5755    SCIP_CONSDATA* consdata;
5756 
5757    assert(scip != NULL);
5758    assert(cons != NULL);
5759 
5760    consdata = SCIPconsGetData(cons);
5761    assert(consdata != NULL);
5762    assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5763 #endif
5764 
5765    /* conflict analysis can only be applied in solving stage and if it is turned on */
5766    if( (SCIPgetStage(scip) != SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) || !SCIPisConflictAnalysisApplicable(scip) )
5767       return SCIP_OKAY;
5768 
5769    /* initialize conflict analysis */
5770    SCIP_CALL( SCIPinitConflictAnalysis(scip, SCIP_CONFTYPE_PROPAGATION, FALSE) );
5771 
5772    /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5773    SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) );
5774 
5775    /* add reasoning variables to conflict candidate queue which led to the conflict */
5776    SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5777 
5778    /* analyze the conflict */
5779    SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5780 
5781    return SCIP_OKAY;
5782 }
5783 
5784 /** propagate ranged rows
5785  *
5786  *  Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5787  *  solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5788  *  variables better.
5789  *
5790  *  Example:
5791  *  c1: 12 x1 + 9  x2 - x3 = 0  with x1, x2 free and 1 <= x3 <= 2
5792  *
5793  *  x3 needs to be a multiple of 3, so the instance is infeasible.
5794  *
5795  *  Example:
5796  *  c1: 12 x1 + 9  x2 - x3 = 1  with x1, x2 free and 1 <= x3 <= 2
5797  *
5798  *  The only possible value for x3 is 2, so the variable will be fixed.
5799  *
5800  *  @todo add holes if possible
5801  */
5802 static
rangedRowPropagation(SCIP * scip,SCIP_CONS * cons,SCIP_Bool * cutoff,int * nfixedvars,int * nchgbds,int * naddconss)5803 SCIP_RETCODE rangedRowPropagation(
5804    SCIP*                 scip,               /**< SCIP data structure */
5805    SCIP_CONS*            cons,               /**< linear constraint */
5806    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
5807    int*                  nfixedvars,         /**< pointer to count number of fixed variables */
5808    int*                  nchgbds,            /**< pointer to count the number of bound changes */
5809    int*                  naddconss           /**< pointer to count number of added constraints */
5810    )
5811 {
5812    SCIP_CONSHDLRDATA* conshdlrdata;
5813    SCIP_CONSHDLR* conshdlr;
5814    SCIP_CONSDATA* consdata;
5815    SCIP_VAR** infcheckvars;
5816    SCIP_Real* infcheckvals;
5817    SCIP_Real minactinfvars;
5818    SCIP_Real maxactinfvars;
5819    SCIP_Real lb;
5820    SCIP_Real ub;
5821    SCIP_Real feastol;
5822    SCIP_Real fixedact;
5823    SCIP_Real lhs;
5824    SCIP_Real rhs;
5825    SCIP_Real absminbincoef;
5826    SCIP_Longint gcd;
5827    SCIP_Longint gcdtmp;
5828    SCIP_Bool minactinfvarsinvalid;
5829    SCIP_Bool maxactinfvarsinvalid;
5830    SCIP_Bool possiblegcd;
5831    SCIP_Bool gcdisone;
5832    SCIP_Bool addartconss;
5833    int ninfcheckvars;
5834    int nunfixedvars;
5835    int nfixedconsvars;
5836    int ncontvars;
5837    int pos;
5838    int v;
5839 
5840    assert(scip != NULL);
5841    assert(cons != NULL);
5842    assert(cutoff != NULL);
5843    assert(nfixedvars != NULL);
5844    assert(nchgbds != NULL);
5845    assert(naddconss != NULL);
5846 
5847    /* modifiable constraint can be changed so we do not have all necessary information */
5848    if( SCIPconsIsModifiable(cons) )
5849       return SCIP_OKAY;
5850 
5851    consdata = SCIPconsGetData(cons);
5852    assert(consdata != NULL);
5853 
5854    /* we already did full ranged row propagation */
5855    if( consdata->rangedrowpropagated == 2 )
5856       return SCIP_OKAY;
5857 
5858    /* at least three variables are needed */
5859    if( consdata->nvars < 3 )
5860       return SCIP_OKAY;
5861 
5862    /* do nothing on normal inequalities */
5863    if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5864       return SCIP_OKAY;
5865 
5866    /* get constraint handler data */
5867    conshdlr = SCIPconsGetHdlr(cons);
5868    assert(conshdlr != NULL);
5869    conshdlrdata = SCIPconshdlrGetData(conshdlr);
5870    assert(conshdlrdata != NULL);
5871 
5872    addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5873 
5874    /* we may add artificial constraints */
5875    if( addartconss )
5876       consdata->rangedrowpropagated = 2;
5877    /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5878     * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5879     * artificial constraints
5880     */
5881    else
5882    {
5883       if( consdata->rangedrowpropagated > 0 )
5884          return SCIP_OKAY;
5885 
5886       consdata->rangedrowpropagated = 1;
5887    }
5888    fixedact = 0;
5889    nfixedconsvars = 0;
5890    /* calculate fixed activity and number of fixed variables */
5891    for( v = consdata->nvars - 1; v >= 0; --v )
5892    {
5893       /* all zero coefficients should be eliminated */
5894       assert(!SCIPisZero(scip, consdata->vals[v]));
5895 
5896       if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5897       {
5898          fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5899 	 ++nfixedconsvars;
5900       }
5901    }
5902 
5903    /* do not work with huge fixed activities */
5904    if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5905       return SCIP_OKAY;
5906 
5907    /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5908    assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5909    lhs = consdata->lhs - fixedact;
5910    rhs = consdata->rhs - fixedact;
5911    nunfixedvars = consdata->nvars - nfixedconsvars;
5912 
5913    /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5914    SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5915    SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5916 
5917    absminbincoef = SCIP_REAL_MAX;
5918    ncontvars = 0;
5919    gcdisone = TRUE;
5920    possiblegcd = TRUE;
5921 
5922    /* we now partition all unfixed variables in two groups:
5923     *
5924     * the first one contains all integral variable with integral
5925     * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5926     * given
5927     *
5928     * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5929     * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5930     */
5931 
5932    /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5933     * variables
5934     */
5935    ninfcheckvars = 0;
5936    v = -1;
5937    pos = -1;
5938    do
5939    {
5940       ++v;
5941 
5942       /* partition the variables, do not change the order of collection, because it might be used later on */
5943       while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5944             !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5945       {
5946          if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5947          {
5948             if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5949             {
5950                ++ncontvars;
5951             }
5952             else if( SCIPvarIsBinary(consdata->vars[v]) )
5953             {
5954                SCIP_Real absval;
5955 
5956                absval = REALABS(consdata->vals[v]);
5957 
5958                if( absminbincoef > absval )
5959                   absminbincoef = absval;
5960             }
5961 
5962             gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5963             possiblegcd = FALSE;
5964             infcheckvars[ninfcheckvars] = consdata->vars[v];
5965             infcheckvals[ninfcheckvars] = consdata->vals[v];
5966             ++ninfcheckvars;
5967 
5968 	    if( pos == -1 )
5969 	       pos = v;
5970          }
5971          ++v;
5972       }
5973    }
5974    while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5975 
5976    /* if the first group of variables is empty, we stop */
5977    /* @todo try to propagate/split up a constraint of the form:
5978     *       x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5979     *       with k \in Z, c \in (d,d + 1], d \in Z, (a_1*y_1 + ... + a_n*y_n) \in (c-1 + d,d + 1]
5980     */
5981    if( v == consdata->nvars )
5982       goto TERMINATE;
5983 
5984    /* we need at least two non-continuous variables */
5985    if( ncontvars + 2 > nunfixedvars )
5986       goto TERMINATE;
5987 
5988    assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5989    assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
5990 
5991    feastol = SCIPfeastol(scip);
5992 
5993    gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5994    assert(gcd >= 2);
5995 
5996    /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5997     * calculate gcd over the first part of variables */
5998    for( ; v < consdata->nvars; ++v )
5999    {
6000       if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6001          continue;
6002 
6003       if( SCIPvarIsBinary(consdata->vars[v]) )
6004       {
6005          SCIP_Real absval;
6006 
6007          absval = REALABS(consdata->vals[v]);
6008 
6009          if( absminbincoef > absval )
6010             absminbincoef = absval;
6011       }
6012 
6013       if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
6014          SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
6015       {
6016          if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
6017             ++ncontvars;
6018 
6019          gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
6020          possiblegcd = FALSE;
6021          infcheckvars[ninfcheckvars] = consdata->vars[v];
6022          infcheckvals[ninfcheckvars] = consdata->vals[v];
6023 
6024          ++ninfcheckvars;
6025 
6026 	 if( pos == -1 )
6027 	    pos = v;
6028       }
6029       else
6030       {
6031          assert(REALABS(consdata->vals[v]) > 1.5);
6032 
6033          gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
6034          assert(gcdtmp >= 1);
6035 
6036          if( gcdtmp == 1 )
6037          {
6038             infcheckvars[ninfcheckvars] = consdata->vars[v];
6039             infcheckvals[ninfcheckvars] = consdata->vals[v];
6040 
6041             ++ninfcheckvars;
6042 
6043 	    if( pos == -1 )
6044 	       pos = v;
6045          }
6046          else
6047             gcd = gcdtmp;
6048       }
6049    }
6050    assert(gcd >= 2);
6051 
6052    /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
6053     * normalizeCons() */
6054    if( ninfcheckvars == 0 )
6055       goto TERMINATE;
6056 
6057    assert(pos >= 0);
6058 
6059    minactinfvarsinvalid = FALSE;
6060    maxactinfvarsinvalid = FALSE;
6061    maxactinfvars = 0.0;
6062    minactinfvars = 0.0;
6063 
6064    /* calculate activities over all infcheckvars */
6065    for( v = ninfcheckvars - 1; v >= 0; --v )
6066    {
6067       lb = SCIPvarGetLbLocal(infcheckvars[v]);
6068       ub = SCIPvarGetUbLocal(infcheckvars[v]);
6069 
6070       if( SCIPisInfinity(scip, -lb) )
6071       {
6072          if( infcheckvals[v] < 0.0 )
6073             maxactinfvarsinvalid = TRUE;
6074          else
6075             minactinfvarsinvalid = TRUE;
6076       }
6077       else
6078       {
6079          if( infcheckvals[v] < 0.0 )
6080             maxactinfvars += infcheckvals[v] * lb;
6081          else
6082             minactinfvars += infcheckvals[v] * lb;
6083       }
6084 
6085       if( SCIPisInfinity(scip, ub) )
6086       {
6087          if( infcheckvals[v] > 0.0 )
6088             maxactinfvarsinvalid = TRUE;
6089          else
6090             minactinfvarsinvalid = TRUE;
6091       }
6092       else
6093       {
6094          if( infcheckvals[v] > 0.0 )
6095             maxactinfvars += infcheckvals[v] * ub;
6096          else
6097             minactinfvars += infcheckvals[v] * ub;
6098       }
6099 
6100       /* better abort on to big values */
6101       if( SCIPisHugeValue(scip, -minactinfvars) )
6102 	 minactinfvarsinvalid = TRUE;
6103       if( SCIPisHugeValue(scip, maxactinfvars) )
6104 	 maxactinfvarsinvalid = TRUE;
6105 
6106       if( minactinfvarsinvalid || maxactinfvarsinvalid )
6107          goto TERMINATE;
6108    }
6109    assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
6110 
6111    SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
6112       minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
6113 
6114    /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
6115    /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
6116     *       activities */
6117    /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
6118     *       !!!note!!!
6119     *       that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
6120     *       are not at their global bound
6121     */
6122 
6123    /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
6124     * infeasibility */
6125    if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
6126       SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
6127    {
6128       SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
6129       SCIPdebugPrintCons(scip, cons, NULL);
6130 
6131       /* start conflict analysis */
6132       /* @todo improve conflict analysis by adding relaxed bounds */
6133       SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6134 
6135       *cutoff = TRUE;
6136    }
6137    else if( ncontvars == 0 )
6138    {
6139       SCIP_Longint gcdinfvars = -1;
6140 
6141       /* check for gcd over all infcheckvars */
6142       if( possiblegcd )
6143       {
6144          v = ninfcheckvars - 1;
6145          gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
6146          assert(gcdinfvars >= 2);
6147 
6148          for( ; v >= 0 && gcdinfvars >= 2; --v )
6149          {
6150             gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
6151          }
6152       }
6153       else if( gcdisone )
6154          gcdinfvars = 1;
6155 
6156       SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
6157 
6158       /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
6159       if( gcdinfvars >= 1 )
6160       {
6161          SCIP_Real value;
6162          SCIP_Real value2;
6163          SCIP_Real minvalue = SCIP_INVALID;
6164          SCIP_Real maxvalue = SCIP_INVALID;
6165          int nsols = 0;
6166 
6167          value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6168 
6169          /* check how many possible solutions exist */
6170          while( SCIPisLE(scip, value, maxactinfvars) )
6171          {
6172 	    value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6173 
6174              /* value2 might violate lhs due to numerics, in this case take the next divisible number */
6175              if( !SCIPisGE(scip, value2, lhs) )
6176              {
6177                 value2 += gcd;
6178              }
6179 
6180 	    if( SCIPisLE(scip, value2, rhs) )
6181 	    {
6182 	       ++nsols;
6183 
6184 	       /* early termination if we found more than two solutions */
6185 	       if( nsols == 3 )
6186 		  break;
6187 
6188 	       if( minvalue == SCIP_INVALID ) /*lint !e777*/
6189 		  minvalue = value;
6190 
6191 	       maxvalue = value;
6192 	    }
6193             value += gcdinfvars;
6194          }
6195          assert(nsols < 2 || minvalue <= maxvalue);
6196 
6197          /* determine last possible solution for better bounding */
6198          if( nsols == 3 )
6199          {
6200 #ifndef NDEBUG
6201             SCIP_Real secondsolval = maxvalue;
6202 #endif
6203             value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6204 
6205             /* check how many possible solutions exist */
6206             while( SCIPisGE(scip, value, minactinfvars) )
6207             {
6208                value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6209 
6210                /* value2 might violate rhs due to numerics, in this case take the next divisible number */
6211                if( !SCIPisLE(scip, value2, rhs) )
6212                {
6213                   value2 -= gcd;
6214                }
6215 
6216                if( SCIPisGE(scip, value2, lhs) )
6217                {
6218                   maxvalue = value;
6219                   assert(maxvalue > minvalue);
6220                   break;
6221                }
6222                value -= gcdinfvars;
6223             }
6224             assert(maxvalue > secondsolval);
6225          }
6226 
6227          SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6228             nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6229 
6230          /* no possible solution found */
6231          if( nsols == 0 )
6232          {
6233 	    SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6234                gcdinfvars, gcd, lhs, rhs);
6235             SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6236             SCIPdebugPrintCons(scip, cons, NULL);
6237 
6238 	    /* start conflict analysis */
6239             /* @todo improve conflict analysis by adding relaxed bounds */
6240 	    SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6241 
6242             *cutoff = TRUE;
6243          }
6244          /* if only one solution exist we can extract a new constraint or fix variables */
6245          else if( nsols == 1 )
6246          {
6247 	    assert(minvalue == maxvalue); /*lint !e777*/
6248 
6249 	    /* we can fix the only variable in our second set of variables */
6250             if( ninfcheckvars == 1 )
6251             {
6252                SCIP_Bool fixed;
6253 
6254 	       assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6255 
6256                SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6257                   SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6258                   SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6259 
6260                /* fix variable to only possible value */
6261                SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6262                      getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6263 
6264 	       if( *cutoff )
6265 	       {
6266 		  /* start conflict analysis */
6267                   /* @todo improve conflict analysis by adding relaxed bounds */
6268 		  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6269 	       }
6270 
6271                if( fixed )
6272                   ++(*nfixedvars);
6273             }
6274             else
6275             {
6276                /* check for exactly one unfixed variable which is not part of the infcheckvars */
6277                if( ninfcheckvars == nunfixedvars - 1 )
6278                {
6279                   SCIP_Real bound;
6280                   SCIP_Bool foundvar = FALSE;
6281                   SCIP_Bool fixed;
6282 		  int w = 0;
6283 
6284                   assert(ninfcheckvars > 0);
6285 
6286                   /* find variable which is not an infcheckvar and fix it */
6287                   for( v = 0; v < consdata->nvars - 1; ++v )
6288 		  {
6289                      if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6290 		     {
6291 			if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6292 			{
6293 #ifndef NDEBUG
6294                            int v2 = v + 1;
6295                            int w2 = w;
6296 
6297                            assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6298 
6299                            for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6300                            {
6301                               if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6302                                  continue;
6303 
6304                               assert(consdata->vars[v2] == infcheckvars[w2]);
6305                               ++w2;
6306                            }
6307                            assert(w2 == ninfcheckvars);
6308 #endif
6309 			   assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6310 
6311 			   foundvar = TRUE;
6312 
6313 			   if( consdata->vals[v] < 0 )
6314 			   {
6315 			      bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6316 			   }
6317 			   else
6318 			   {
6319 			      bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6320 			   }
6321 
6322 			   SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6323                               SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6324                               SCIPvarGetUbLocal(consdata->vars[v]), bound);
6325 
6326 			   /* fix variable to only possible value */
6327 			   SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6328                                  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6329 
6330 			   if( *cutoff )
6331 			   {
6332 			      /* start conflict analysis */
6333                               /* @todo improve conflict analysis by adding relaxed bounds */
6334 			      SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6335                                     consdata->vars[v], bound) );
6336 			   }
6337 
6338 			   if( fixed )
6339 			      ++(*nfixedvars);
6340 
6341 			   break;
6342 			}
6343 
6344 			++w;
6345 		     }
6346 		  }
6347 
6348                   /* maybe last variable was the not infcheckvar */
6349                   if( !foundvar )
6350                   {
6351                      assert(v == consdata->nvars - 1);
6352 		     assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6353 
6354 		     if( consdata->vals[v] < 0 )
6355 		     {
6356 			bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6357 		     }
6358 		     else
6359 		     {
6360 			bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6361 		     }
6362 
6363                      SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6364                         SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6365                         SCIPvarGetUbLocal(consdata->vars[v]), bound);
6366 
6367                      /* fix variable to only possible value */
6368 		     SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6369                            getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6370 
6371 		     if( *cutoff )
6372 		     {
6373 			/* start conflict analysis */
6374                         /* @todo improve conflict analysis by adding relaxed bounds */
6375                         SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6376                               consdata->vars[v], bound) );
6377 		     }
6378 
6379                      if( fixed )
6380                         ++(*nfixedvars);
6381                   }
6382                }
6383                else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6384                {
6385                   /* aggregation possible if we have two variables, but this will be done later on */
6386                   SCIP_CONS* newcons;
6387                   char name[SCIP_MAXSTRLEN];
6388 
6389                   /* create, add, and release new artificial constraint */
6390                   (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6391                   ++conshdlrdata->naddconss;
6392 
6393 		  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6394 
6395                   SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6396                         maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6397                   SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6398 
6399                   SCIPdebugPrintCons(scip, newcons, NULL);
6400 
6401                   SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6402 
6403                   ++(*naddconss);
6404                }
6405             }
6406          }
6407          /* at least two solutions */
6408          else
6409          {
6410             /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6411 
6412 	    /* only one variable in the second set, so we can bound this variables */
6413             if( ninfcheckvars == 1 )
6414             {
6415                SCIP_Bool tightened;
6416                SCIP_Real newlb;
6417                SCIP_Real newub;
6418 
6419 	       assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6420 
6421                if( infcheckvals[0] < 0 )
6422                {
6423                   newlb = maxvalue/infcheckvals[0];
6424                   newub = minvalue/infcheckvals[0];
6425                }
6426                else
6427                {
6428                   newlb = minvalue/infcheckvals[0];
6429                   newub = maxvalue/infcheckvals[0];
6430                }
6431                assert(newlb < newub);
6432 
6433 	       if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6434 	       {
6435 		  /* update lower bound of variable */
6436 		  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6437                      SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6438 
6439 		  /* tighten variable lower bound to minimal possible value */
6440 		  SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6441                         getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6442 
6443 		  if( *cutoff )
6444 		  {
6445 		     /* start conflict analysis */
6446                      /* @todo improve conflict analysis by adding relaxed bounds */
6447 		     SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6448 		  }
6449 
6450 		  if( tightened )
6451 		     ++(*nchgbds);
6452 	       }
6453 
6454 	       if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6455 	       {
6456 		  /* update upper bound of variable */
6457 		  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6458                      SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6459 
6460 		  /* tighten variable upper bound to maximal possible value */
6461 		  SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6462                         getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6463 
6464 		  if( *cutoff )
6465 		  {
6466 		     /* start conflict analysis */
6467                      /* @todo improve conflict analysis by adding relaxed bounds */
6468 		     SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6469 		  }
6470 
6471 		  if( tightened )
6472 		     ++(*nchgbds);
6473 	       }
6474             }
6475             /* check if we have only one not infcheckvars, if so we can tighten this variable */
6476             else if( ninfcheckvars == nunfixedvars - 1 )
6477             {
6478                SCIP_Bool foundvar = FALSE;
6479                SCIP_Bool tightened;
6480                SCIP_Real newlb;
6481                SCIP_Real newub;
6482 	       int w = 0;
6483 
6484                assert(ninfcheckvars > 0);
6485                assert(minvalue < maxvalue);
6486 
6487                /* find variable which is not an infcheckvar and fix it */
6488                for( v = 0; v < consdata->nvars - 1; ++v )
6489 	       {
6490                   if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6491 		  {
6492 		     if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6493 		     {
6494 #ifndef NDEBUG
6495                         int v2 = v + 1;
6496                         int w2 = w;
6497 
6498                         assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6499 
6500                         for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6501                         {
6502                            if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6503                               continue;
6504 
6505                            assert(consdata->vars[v2] == infcheckvars[w2]);
6506                            ++w2;
6507                         }
6508                         assert(w2 == ninfcheckvars);
6509 #endif
6510 
6511 			assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6512 			foundvar = TRUE;
6513 
6514 			if( consdata->vals[v] < 0 )
6515 			{
6516 			   newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6517 			   newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6518 			}
6519 			else
6520 			{
6521 			   newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6522 			   newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6523 			}
6524 			assert(SCIPisLE(scip, newlb, newub));
6525 
6526 			if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6527 			{
6528 			   /* update lower bound of variable */
6529 			   SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6530                               SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6531 
6532 			   /* tighten variable lower bound to minimal possible value */
6533 			   SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6534                                  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6535 
6536 			   if( *cutoff )
6537 			   {
6538 			      /* start conflict analysis */
6539                               /* @todo improve conflict analysis by adding relaxed bounds */
6540 			      SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6541                                     consdata->vars[v], newlb) );
6542 			   }
6543 
6544 			   if( tightened )
6545 			      ++(*nchgbds);
6546 			}
6547 
6548 			if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6549 			{
6550 			   /* update upper bound of variable */
6551 			   SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6552                               SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6553 
6554 			   /* tighten variable upper bound to maximal possible value */
6555 			   SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6556                                  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6557 
6558 			   if( *cutoff )
6559 			   {
6560 			      /* start conflict analysis */
6561                               /* @todo improve conflict analysis by adding relaxed bounds */
6562 			      SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6563                                     consdata->vars[v], newub) );
6564 			   }
6565 
6566 			   if( tightened )
6567 			      ++(*nchgbds);
6568 			}
6569 
6570 			break;
6571 		     }
6572 
6573 		     ++w;
6574 		  }
6575 	       }
6576 
6577                /* maybe last variable was the not infcheckvar */
6578                if( !foundvar )
6579                {
6580                   assert(v == consdata->nvars - 1);
6581 		  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6582 
6583 		  if( consdata->vals[v] < 0 )
6584 		  {
6585 		     newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6586 		     newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6587 		  }
6588 		  else
6589 		  {
6590 		     newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6591 		     newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6592 		  }
6593                   assert(SCIPisLE(scip, newlb, newub));
6594 
6595 		  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6596 		  {
6597 		     /* update lower bound of variable */
6598 		     SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6599                         SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6600 
6601                      /* tighten variable lower bound to minimal possible value */
6602 		     SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6603                            getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6604 
6605 		     if( *cutoff )
6606 		     {
6607 			/* start conflict analysis */
6608                         /* @todo improve conflict analysis by adding relaxed bounds */
6609                         SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6610 		     }
6611 
6612 		     if( tightened )
6613 			++(*nchgbds);
6614 		  }
6615 
6616 		  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6617 		  {
6618 		     /* update upper bound of variable */
6619 		     SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6620                         SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6621 
6622 		     /* tighten variable upper bound to maximal possible value */
6623 		     SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6624                            getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6625 
6626 		     if( *cutoff )
6627 		     {
6628 			/* start conflict analysis */
6629                         /* @todo improve conflict analysis by adding relaxed bounds */
6630                         SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6631 		     }
6632 
6633 		     if( tightened )
6634 			++(*nchgbds);
6635 		  }
6636                }
6637             }
6638             /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6639              * region for our infcheckvars, if possible
6640              */
6641             else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6642             {
6643                SCIP_CONS* newcons;
6644                char name[SCIP_MAXSTRLEN];
6645                SCIP_Real newlhs;
6646                SCIP_Real newrhs;
6647 
6648                assert(maxvalue > minvalue);
6649 
6650                if( SCIPisGT(scip, minvalue, minactinfvars) )
6651                   newlhs = minvalue;
6652                else
6653                   newlhs = -SCIPinfinity(scip);
6654 
6655                if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6656                   newrhs = maxvalue;
6657                else
6658                   newrhs = SCIPinfinity(scip);
6659 
6660 	       if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6661 	       {
6662 		  /* create, add, and release new artificial constraint */
6663 		  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6664 		  ++conshdlrdata->naddconss;
6665 
6666 		  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6667 
6668 		  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6669 			TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6670 		  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6671 
6672 		  SCIPdebugPrintCons(scip, newcons, NULL);
6673 		  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6674 
6675 		  ++(*naddconss);
6676 	       }
6677                /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6678                 *       should be maxvalue */
6679             }
6680          }
6681       }
6682    }
6683    else if( addartconss && ncontvars < ninfcheckvars )
6684    {
6685       SCIP_Real maxact = 0.0;
6686       SCIP_Real minact = 0.0;
6687       int w = 0;
6688 
6689       /* compute activities of non-infcheckvars */
6690       for( v = 0; v < consdata->nvars; ++v )
6691       {
6692          if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6693          {
6694             ++w;
6695             continue;
6696          }
6697 
6698          if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6699          {
6700             if( SCIPvarIsBinary(consdata->vars[v]) )
6701             {
6702                if( consdata->vals[v] > 0.0 )
6703                   maxact += consdata->vals[v];
6704                else
6705                   minact += consdata->vals[v];
6706             }
6707             else
6708             {
6709                SCIP_Real tmpval;
6710 
6711                assert(SCIPvarIsIntegral(consdata->vars[v]));
6712 
6713                if( consdata->vals[v] > 0.0 )
6714                {
6715                   tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6716 
6717                   if( SCIPisHugeValue(scip, -tmpval) )
6718                      break;
6719 
6720                   minact += tmpval;
6721 
6722                   tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6723 
6724                   if( SCIPisHugeValue(scip, tmpval) )
6725                      break;
6726 
6727                   maxact += tmpval;
6728                }
6729                else
6730                {
6731                   tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6732 
6733                   if( SCIPisHugeValue(scip, -tmpval) )
6734                      break;
6735 
6736                   minact += tmpval;
6737 
6738                   tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6739 
6740                   if( SCIPisHugeValue(scip, tmpval) )
6741                      break;
6742 
6743                   maxact += tmpval;
6744                }
6745             }
6746          }
6747       }
6748       if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6749       {
6750          SCIP_CONS* newcons;
6751          char name[SCIP_MAXSTRLEN];
6752          SCIP_Real newlhs;
6753          SCIP_Real newrhs;
6754 
6755          assert(maxact > minact);
6756          assert(w == ninfcheckvars);
6757 
6758          newlhs = lhs - maxact;
6759          newrhs = rhs - minact;
6760          assert(newlhs < newrhs);
6761 
6762          /* create, add, and release new artificial constraint */
6763          (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6764          ++conshdlrdata->naddconss;
6765 
6766          SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6767 
6768          SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6769                TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6770          SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6771 
6772          SCIPdebugPrintCons(scip, newcons, NULL);
6773          SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6774 
6775          ++(*naddconss);
6776       }
6777    }
6778 
6779  TERMINATE:
6780    SCIPfreeBufferArray(scip, &infcheckvals);
6781    SCIPfreeBufferArray(scip, &infcheckvars);
6782 
6783    return SCIP_OKAY;
6784 }
6785 
6786 /** tightens bounds of a single variable due to activity bounds */
6787 static
tightenVarBounds(SCIP * scip,SCIP_CONS * cons,int pos,SCIP_Bool * cutoff,int * nchgbds,SCIP_Bool force)6788 SCIP_RETCODE tightenVarBounds(
6789    SCIP*                 scip,               /**< SCIP data structure */
6790    SCIP_CONS*            cons,               /**< linear constraint */
6791    int                   pos,                /**< position of the variable in the vars array */
6792    SCIP_Bool*            cutoff,             /**< pointer to store whether the node can be cut off */
6793    int*                  nchgbds,            /**< pointer to count the total number of tightened bounds */
6794    SCIP_Bool             force               /**< should a possible bound change be forced even if below bound strengthening tolerance */
6795    )
6796 {
6797    SCIP_CONSDATA* consdata;
6798    SCIP_VAR* var;
6799    SCIP_Real val;
6800    SCIP_Real lb;
6801    SCIP_Real ub;
6802    SCIP_Real minresactivity;
6803    SCIP_Real maxresactivity;
6804    SCIP_Real lhs;
6805    SCIP_Real rhs;
6806    SCIP_Bool infeasible;
6807    SCIP_Bool tightened;
6808    SCIP_Bool minisrelax;
6809    SCIP_Bool maxisrelax;
6810    SCIP_Bool isminsettoinfinity;
6811    SCIP_Bool ismaxsettoinfinity;
6812 
6813    assert(scip != NULL);
6814    assert(cons != NULL);
6815    assert(cutoff != NULL);
6816    assert(nchgbds != NULL);
6817 
6818    /* we cannot tighten variables' bounds, if the constraint may be not complete */
6819    if( SCIPconsIsModifiable(cons) )
6820       return SCIP_OKAY;
6821 
6822    consdata = SCIPconsGetData(cons);
6823    assert(consdata != NULL);
6824    assert(0 <= pos && pos < consdata->nvars);
6825 
6826    *cutoff = FALSE;
6827 
6828    var = consdata->vars[pos];
6829 
6830    /* we cannot tighten bounds of multi-aggregated variables */
6831    if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR )
6832       return SCIP_OKAY;
6833 
6834    val = consdata->vals[pos];
6835    lhs = consdata->lhs;
6836    rhs = consdata->rhs;
6837    consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6838       &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
6839    assert(var != NULL);
6840    assert(!SCIPisZero(scip, val));
6841    assert(!SCIPisInfinity(scip, lhs));
6842    assert(!SCIPisInfinity(scip, -rhs));
6843 
6844    lb = SCIPvarGetLbLocal(var);
6845    ub = SCIPvarGetUbLocal(var);
6846    assert(SCIPisLE(scip, lb, ub));
6847 
6848    if( val > 0.0 )
6849    {
6850       /* check, if we can tighten the variable's bounds */
6851       if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6852       {
6853          SCIP_Real newub;
6854 
6855          newub = (rhs - minresactivity)/val;
6856 
6857          if( !SCIPisInfinity(scip, newub) &&
6858             ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6859          {
6860             SCIP_Bool activityunreliable;
6861             activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6862 
6863             /* check minresactivities for reliability */
6864             if( activityunreliable )
6865             {
6866                consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6867                newub = (rhs - minresactivity)/val;
6868                activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6869                   (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6870                      && (!force || !SCIPisLT(scip, newub, ub)));
6871             }
6872 
6873             if( !activityunreliable )
6874             {
6875                /* tighten upper bound */
6876                SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6877                   SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6878                SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6879                      &infeasible, &tightened) );
6880                if( infeasible )
6881                {
6882                   SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, new bds=[%.15g,%.15g]\n",
6883                      SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6884 
6885                   /* analyze conflict */
6886                   SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6887 
6888                   *cutoff = TRUE;
6889                   return SCIP_OKAY;
6890                }
6891                if( tightened )
6892                {
6893                   ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6894                   assert(SCIPisFeasLE(scip, ub, newub));
6895                   (*nchgbds)++;
6896 
6897                   SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6898                      SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6899                }
6900             }
6901          }
6902       }
6903 
6904       if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6905       {
6906          SCIP_Real newlb;
6907 
6908          newlb = (lhs - maxresactivity)/val;
6909          if( !SCIPisInfinity(scip, -newlb) &&
6910             ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6911          {
6912             /* check maxresactivities for reliability */
6913             if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6914             {
6915                consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6916                newlb = (lhs - maxresactivity)/val;
6917 
6918                if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6919                      && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6920                      && (!force || !SCIPisGT(scip, newlb, lb))) )
6921                   return SCIP_OKAY;
6922             }
6923 
6924             /* tighten lower bound */
6925             SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6926                SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6927             SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6928                   &infeasible, &tightened) );
6929             if( infeasible )
6930             {
6931                SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, new bds=[%.15g,%.15g]\n",
6932                   SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6933 
6934                /* analyze conflict */
6935                SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6936 
6937                *cutoff = TRUE;
6938                return SCIP_OKAY;
6939             }
6940             if( tightened )
6941             {
6942                lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6943                assert(SCIPisFeasGE(scip, lb, newlb));
6944                (*nchgbds)++;
6945                SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6946                   SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6947             }
6948          }
6949       }
6950    }
6951    else
6952    {
6953       /* check, if we can tighten the variable's bounds */
6954       if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6955       {
6956          SCIP_Real newlb;
6957 
6958          newlb = (rhs - minresactivity)/val;
6959          if( !SCIPisInfinity(scip, -newlb) &&
6960             ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6961          {
6962             SCIP_Bool activityunreliable;
6963             activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6964             /* check minresactivities for reliability */
6965             if( activityunreliable )
6966             {
6967                consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6968                newlb = (rhs - minresactivity)/val;
6969 
6970                activityunreliable = SCIPisInfinity(scip, -minresactivity)
6971                   || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6972                      && (!force || !SCIPisGT(scip, newlb, lb)));
6973             }
6974 
6975             if( !activityunreliable )
6976             {
6977                /* tighten lower bound */
6978                SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6979                   SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6980                SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6981                      &infeasible, &tightened) );
6982                if( infeasible )
6983                {
6984                   SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, new bds=[%.15g,%.15g]\n",
6985                      SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6986 
6987                   /* analyze conflict */
6988                   SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6989 
6990                   *cutoff = TRUE;
6991                   return SCIP_OKAY;
6992                }
6993                if( tightened )
6994                {
6995                   lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6996                   assert(SCIPisFeasGE(scip, lb, newlb));
6997                   (*nchgbds)++;
6998                   SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6999                      SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7000                }
7001             }
7002          }
7003       }
7004 
7005       if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
7006       {
7007          SCIP_Real newub;
7008 
7009          newub = (lhs - maxresactivity)/val;
7010          if(  !SCIPisInfinity(scip, newub) &&
7011             ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
7012          {
7013             /* check maxresactivities for reliability */
7014             if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
7015             {
7016                consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
7017                newub = (lhs - maxresactivity)/val;
7018 
7019                if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
7020                      && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
7021                      && (!force || !SCIPisLT(scip, newub, ub))) )
7022                   return SCIP_OKAY;
7023             }
7024 
7025             /* tighten upper bound */
7026             SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
7027                SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
7028             SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
7029                   &infeasible, &tightened) );
7030             if( infeasible )
7031             {
7032                SCIPdebugMsg(scip, "linear constraint <%s>: cutoff  <%s>, new bds=[%.15g,%.15g]\n",
7033                   SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
7034 
7035                /* analyze conflict */
7036                SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7037 
7038                *cutoff = TRUE;
7039                return SCIP_OKAY;
7040             }
7041             if( tightened )
7042             {
7043                ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
7044                assert(SCIPisFeasLE(scip, ub, newub));
7045                (*nchgbds)++;
7046                SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
7047                   SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
7048             }
7049          }
7050       }
7051    }
7052 
7053    return SCIP_OKAY;
7054 }
7055 
7056 #define MAXTIGHTENROUNDS 10
7057 
7058 /** tightens bounds of variables in constraint due to activity bounds */
7059 static
tightenBounds(SCIP * scip,SCIP_CONS * cons,SCIP_Real maxeasyactivitydelta,SCIP_Bool sortvars,SCIP_Bool * cutoff,int * nchgbds)7060 SCIP_RETCODE tightenBounds(
7061    SCIP*                 scip,               /**< SCIP data structure */
7062    SCIP_CONS*            cons,               /**< linear constraint */
7063    SCIP_Real             maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7064    SCIP_Bool             sortvars,           /**< should variables be used in sorted order? */
7065    SCIP_Bool*            cutoff,             /**< pointer to store whether the node can be cut off */
7066    int*                  nchgbds             /**< pointer to count the total number of tightened bounds */
7067    )
7068 {
7069    SCIP_CONSDATA* consdata;
7070    unsigned int tightenmode;
7071    int nvars;
7072    int nrounds;
7073    int lastchange;
7074    int oldnchgbds;
7075 #ifndef SCIP_DEBUG
7076    int oldnchgbdstotal;
7077 #endif
7078    int v;
7079    SCIP_Bool force;
7080    SCIP_Bool easycase;
7081 
7082    assert(scip != NULL);
7083    assert(cons != NULL);
7084    assert(nchgbds != NULL);
7085    assert(cutoff != NULL);
7086 
7087    *cutoff = FALSE;
7088 
7089    /* we cannot tighten variables' bounds, if the constraint may be not complete */
7090    if( SCIPconsIsModifiable(cons) )
7091       return SCIP_OKAY;
7092 
7093    /* if a constraint was created after presolve, then it may hold fixed variables
7094     * if there are even multi-aggregated variables, then we cannot do bound tightening on these
7095     * thus, ensure here again that variable fixings have been applied
7096     */
7097    SCIP_CALL( applyFixings(scip, cons, cutoff) );
7098    if( *cutoff )
7099       return SCIP_OKAY;
7100 
7101    /* check if constraint has any chances of tightening bounds */
7102    if( !canTightenBounds(cons) )
7103       return SCIP_OKAY;
7104 
7105    consdata = SCIPconsGetData(cons);
7106    assert(consdata != NULL);
7107 
7108    nvars = consdata->nvars;
7109    force = (nvars == 1) && !SCIPconsIsModifiable(cons);
7110 
7111    /* we are at the root node or during presolving */
7112    if( SCIPgetDepth(scip) < 1 )
7113       tightenmode = 2;
7114    else
7115       tightenmode = 1;
7116 
7117    /* stop if we already tightened the constraint and the tightening is not forced */
7118    if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
7119       return SCIP_OKAY;
7120 
7121    /* ensure that the variables are properly sorted */
7122    if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7123    {
7124       SCIP_CALL( consdataSort(scip, consdata) );
7125       assert(consdata->coefsorted);
7126    }
7127 
7128    /* update maximal activity delta if necessary */
7129    if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
7130       consdataRecomputeMaxActivityDelta(scip, consdata);
7131 
7132    assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
7133    assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
7134    checkMaxActivityDelta(scip, consdata);
7135 
7136    /* this may happen if all variables are fixed */
7137    if( SCIPisFeasZero(scip, consdata->maxactdelta) )
7138       return SCIP_OKAY;
7139 
7140    if( !SCIPisInfinity(scip, consdata->maxactdelta) )
7141    {
7142       SCIP_Real slack;
7143       SCIP_Real surplus;
7144       SCIP_Real minactivity;
7145       SCIP_Real maxactivity;
7146       SCIP_Bool minisrelax;
7147       SCIP_Bool maxisrelax;
7148       SCIP_Bool isminsettoinfinity;
7149       SCIP_Bool ismaxsettoinfinity;
7150 
7151       /* use maximal activity delta to skip propagation (cannot deduce anything) */
7152       consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax,
7153          &isminsettoinfinity, &ismaxsettoinfinity);
7154       assert(!SCIPisInfinity(scip, minactivity));
7155       assert(!SCIPisInfinity(scip, -maxactivity));
7156 
7157       slack = (SCIPisInfinity(scip, consdata->rhs) || isminsettoinfinity) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
7158       surplus = (SCIPisInfinity(scip, -consdata->lhs) || ismaxsettoinfinity) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
7159 
7160       /* check if the constraint will propagate */
7161       if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
7162          return SCIP_OKAY;
7163    }
7164 
7165    /* check if we can use fast implementation for easy and numerically well behaved cases */
7166    easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
7167 
7168    /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
7169    lastchange = -1;
7170    oldnchgbds = 0;
7171 
7172 #ifndef SCIP_DEBUG
7173    oldnchgbdstotal = *nchgbds;
7174 #endif
7175 
7176    for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7177    {
7178       /* ensure that the variables are properly sorted
7179        *
7180        * note: it might happen that integer variables become binary during bound tightening at the root node
7181        */
7182       if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->coefsorted )
7183       {
7184          SCIP_CALL( consdataSort(scip, consdata) );
7185          assert(consdata->coefsorted);
7186       }
7187 
7188       /* mark the constraint to have the variables' bounds tightened */
7189       consdata->boundstightened = (unsigned int)tightenmode;
7190 
7191       /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7192        * sorting enables skipping variables
7193        */
7194       v = 0;
7195       while( v < nvars && v != lastchange && !(*cutoff) )
7196       {
7197          oldnchgbds = *nchgbds;
7198 
7199          if( easycase )
7200          {
7201             SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7202          }
7203          else
7204          {
7205             SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7206          }
7207 
7208          /* if there was no progress, skip the rest of the binary variables */
7209          if( *nchgbds > oldnchgbds )
7210          {
7211             lastchange = v;
7212             ++v;
7213          }
7214          else if( consdata->coefsorted && v < consdata->nbinvars - 1
7215             && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7216             v = consdata->nbinvars;
7217          else
7218             ++v;
7219       }
7220 
7221 #ifndef SCIP_DEBUG
7222       SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7223          *nchgbds - oldnchgbdstotal, nrounds);
7224       oldnchgbdstotal += oldnchgbds;
7225 #endif
7226    }
7227 
7228 #ifndef NDEBUG
7229    if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7230       assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7231 #endif
7232 
7233    return SCIP_OKAY;
7234 }
7235 
7236 /** checks linear constraint for feasibility of given solution or current solution */
7237 static
checkCons(SCIP * scip,SCIP_CONS * cons,SCIP_SOL * sol,SCIP_Bool checklprows,SCIP_Bool checkrelmaxabs,SCIP_Bool * violated)7238 SCIP_RETCODE checkCons(
7239    SCIP*                 scip,               /**< SCIP data structure */
7240    SCIP_CONS*            cons,               /**< linear constraint */
7241    SCIP_SOL*             sol,                /**< solution to be checked, or NULL for current solution */
7242    SCIP_Bool             checklprows,        /**< Do constraints represented by rows in the current LP have to be checked? */
7243    SCIP_Bool             checkrelmaxabs,     /**< Should the violation for a constraint with side 0.0 be checked relative
7244                                               *   to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7245    SCIP_Bool*            violated            /**< pointer to store whether the constraint is violated */
7246    )
7247 {
7248    SCIP_CONSDATA* consdata;
7249    SCIP_Real activity;
7250    SCIP_Real absviol;
7251    SCIP_Real relviol;
7252    SCIP_Real lhsviol;
7253    SCIP_Real rhsviol;
7254 
7255    assert(scip != NULL);
7256    assert(cons != NULL);
7257    assert(violated != NULL);
7258 
7259    SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7260    SCIPdebugPrintCons(scip, cons, NULL);
7261 
7262    consdata = SCIPconsGetData(cons);
7263    assert(consdata != NULL);
7264 
7265    *violated = FALSE;
7266 
7267    if( consdata->row != NULL )
7268    {
7269       if( !checklprows && SCIProwIsInLP(consdata->row) )
7270          return SCIP_OKAY;
7271       else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7272          activity = consdataComputePseudoActivity(scip, consdata);
7273       else
7274          activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7275    }
7276    else
7277       activity = consdataGetActivity(scip, consdata, sol);
7278 
7279    SCIPdebugMsg(scip, "  consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7280       activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7281       consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7282       consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7283 
7284    /* calculate absolute and relative bound violations */
7285    lhsviol = consdata->lhs - activity;
7286    rhsviol = activity - consdata->rhs;
7287 
7288    absviol = 0.0;
7289    relviol = 0.0;
7290    if( (lhsviol > 0) && (lhsviol > rhsviol) )
7291    {
7292       absviol = lhsviol;
7293       relviol = SCIPrelDiff(consdata->lhs, activity);
7294    }
7295    else if( rhsviol > 0 )
7296    {
7297       absviol = rhsviol;
7298       relviol = SCIPrelDiff(activity, consdata->rhs);
7299    }
7300 
7301    /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7302     * return infeasible for safety
7303     */
7304    if( activity == SCIP_INVALID ) /*lint !e777*/
7305    {
7306       assert(sol == NULL);
7307       *violated = TRUE;
7308 
7309       /* set violation of invalid pseudo solutions */
7310       absviol = SCIP_INVALID;
7311       relviol = SCIP_INVALID;
7312 
7313       /* reset constraint age since we are in enforcement */
7314       SCIP_CALL( SCIPresetConsAge(scip, cons) );
7315    }
7316    /* check with relative tolerances (the default) */
7317    else if( !consdata->checkabsolute && (SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs)) )
7318    {
7319       /* the "normal" check: one of the two sides is violated */
7320       if( !checkrelmaxabs )
7321       {
7322          *violated = TRUE;
7323 
7324          /* only reset constraint age if we are in enforcement */
7325          if( sol == NULL )
7326          {
7327             SCIP_CALL( SCIPresetConsAge(scip, cons) );
7328          }
7329       }
7330       /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7331        * small compared to the absolute values occurring in the activity
7332        */
7333       else
7334       {
7335          SCIP_Real maxabs;
7336          SCIP_Real coef;
7337          SCIP_Real absval;
7338          SCIP_Real solval;
7339          int v;
7340 
7341          maxabs = 1.0;
7342 
7343          /* compute maximum absolute value */
7344          for( v = 0; v < consdata->nvars; ++v )
7345          {
7346             if( consdata->vals != NULL )
7347             {
7348                coef = consdata->vals[v];
7349             }
7350             else
7351                coef = 1.0;
7352 
7353             solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7354             absval = REALABS( coef * solval );
7355             maxabs = MAX( maxabs, absval );
7356          }
7357 
7358          /* regard left hand side, first */
7359          if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7360          {
7361             /* check whether violation is random noise */
7362             if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7363             {
7364                SCIPdebugMsg(scip, "  lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7365                   consdata->lhs - activity, maxabs);
7366                SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7367 
7368                /* only increase constraint age if we are in enforcement */
7369                if( sol == NULL )
7370                {
7371                   SCIP_CALL( SCIPincConsAge(scip, cons) );
7372                }
7373             }
7374             /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7375             else if( SCIPisZero(scip, consdata->lhs) )
7376             {
7377                if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7378                {
7379                   SCIPdebugMsg(scip, "  lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7380                      consdata->lhs - activity, maxabs);
7381                   SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7382 
7383                   /* only increase constraint age if we are in enforcement */
7384                   if( sol == NULL )
7385                   {
7386                      SCIP_CALL( SCIPincConsAge(scip, cons) );
7387                   }
7388                }
7389                else
7390                {
7391                   *violated = TRUE;
7392 
7393                   /* only reset constraint age if we are in enforcement */
7394                   if( sol == NULL )
7395                   {
7396                      SCIP_CALL( SCIPresetConsAge(scip, cons) );
7397                   }
7398                }
7399             }
7400             else
7401             {
7402                *violated = TRUE;
7403 
7404                /* only reset constraint age if we are in enforcement */
7405                if( sol == NULL )
7406                {
7407                   SCIP_CALL( SCIPresetConsAge(scip, cons) );
7408                }
7409             }
7410          }
7411 
7412          /* now regard right hand side */
7413          if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7414          {
7415             /* check whether violation is random noise */
7416             if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7417             {
7418                SCIPdebugMsg(scip, "  rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7419                   activity - consdata->rhs, maxabs);
7420                SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7421 
7422                /* only increase constraint age if we are in enforcement */
7423                if( sol == NULL )
7424                {
7425                   SCIP_CALL( SCIPincConsAge(scip, cons) );
7426                }
7427             }
7428             /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7429             else if( SCIPisZero(scip, consdata->rhs) )
7430             {
7431                if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7432                {
7433                   SCIPdebugMsg(scip, "  rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7434                      activity - consdata->rhs, maxabs);
7435                   SCIPdebug( SCIP_CALL( consPrintConsSol(scip, cons, sol, NULL) ) );
7436 
7437                   /* only increase constraint age if we are in enforcement */
7438                   if( sol == NULL )
7439                   {
7440                      SCIP_CALL( SCIPincConsAge(scip, cons) );
7441                   }
7442                }
7443                else
7444                {
7445                   *violated = TRUE;
7446 
7447                   /* only reset constraint age if we are in enforcement */
7448                   if( sol == NULL )
7449                   {
7450                      SCIP_CALL( SCIPresetConsAge(scip, cons) );
7451                   }
7452                }
7453             }
7454             else
7455             {
7456                *violated = TRUE;
7457 
7458                /* only reset constraint age if we are in enforcement */
7459                if( sol == NULL )
7460                {
7461                   SCIP_CALL( SCIPresetConsAge(scip, cons) );
7462                }
7463             }
7464          }
7465       }
7466    }
7467    /* check with absolute tolerances */
7468    else if( consdata->checkabsolute &&
7469       ((!SCIPisInfinity(scip, -consdata->lhs) && SCIPisGT(scip, consdata->lhs-activity, SCIPfeastol(scip))) ||
7470        (!SCIPisInfinity(scip,  consdata->rhs) && SCIPisGT(scip, activity-consdata->rhs, SCIPfeastol(scip)))) )
7471    {
7472       *violated = TRUE;
7473 
7474       /* only reset constraint age if we are in enforcement */
7475       if( sol == NULL )
7476       {
7477          SCIP_CALL( SCIPresetConsAge(scip, cons) );
7478       }
7479    }
7480    else
7481    {
7482       /* only increase constraint age if we are in enforcement */
7483       if( sol == NULL )
7484       {
7485          SCIP_CALL( SCIPincConsAge(scip, cons) );
7486       }
7487    }
7488 
7489    /* update absolute and relative violation of the solution */
7490    if( sol != NULL )
7491       SCIPupdateSolLPConsViolation(scip, sol, absviol, relviol);
7492 
7493    return SCIP_OKAY;
7494 }
7495 
7496 /** creates an LP row in a linear constraint data */
7497 static
createRow(SCIP * scip,SCIP_CONS * cons)7498 SCIP_RETCODE createRow(
7499    SCIP*                 scip,               /**< SCIP data structure */
7500    SCIP_CONS*            cons                /**< linear constraint */
7501    )
7502 {
7503    SCIP_CONSDATA* consdata;
7504 
7505    assert(scip != NULL);
7506    assert(cons != NULL);
7507 
7508    consdata = SCIPconsGetData(cons);
7509    assert(consdata != NULL);
7510    assert(consdata->row == NULL);
7511 
7512    SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, cons, SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7513          SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsRemovable(cons)) );
7514 
7515    SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7516 
7517    return SCIP_OKAY;
7518 }
7519 
7520 /** adds linear constraint as cut to the LP */
7521 static
addRelaxation(SCIP * scip,SCIP_CONS * cons,SCIP_Bool * cutoff)7522 SCIP_RETCODE addRelaxation(
7523    SCIP*                 scip,               /**< SCIP data structure */
7524    SCIP_CONS*            cons,               /**< linear constraint */
7525    SCIP_Bool*            cutoff              /**< pointer to store whether a cutoff was found */
7526    )
7527 {
7528    SCIP_CONSDATA* consdata;
7529 
7530    assert(scip != NULL);
7531    assert(cons != NULL);
7532 
7533    consdata = SCIPconsGetData(cons);
7534    assert(consdata != NULL);
7535 
7536    if( consdata->row == NULL )
7537    {
7538       if( !SCIPconsIsModifiable(cons) )
7539       {
7540          /* replace all fixed variables by active counterparts, as we have no chance to do this anymore after the row has been added to the LP
7541           * removing this here will make test cons/linear/fixedvar.c fail (as of 2018-12-03)
7542           */
7543          SCIP_CALL( applyFixings(scip, cons, cutoff) );
7544          if( *cutoff )
7545             return SCIP_OKAY;
7546       }
7547 
7548       /* convert consdata object into LP row */
7549       SCIP_CALL( createRow(scip, cons) );
7550    }
7551    assert(consdata->row != NULL);
7552 
7553    if( consdata->nvars == 0 )
7554    {
7555       SCIPdebugMsg(scip, "Empty linear constraint enters LP: <%s>\n", SCIPconsGetName(cons));
7556    }
7557 
7558    /* insert LP row as cut */
7559    if( !SCIProwIsInLP(consdata->row) )
7560    {
7561       SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7562       SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7563       /* if presolving is turned off, the row might be trivial */
7564       if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7565       {
7566          SCIP_CALL( SCIPaddRow(scip, consdata->row, FALSE, cutoff) );
7567       }
7568 #ifndef NDEBUG
7569       else
7570       {
7571          int pr;
7572          int cr;
7573          SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7574          SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7575          assert( pr == 0 || cr == 0 );
7576       }
7577 #endif
7578    }
7579 
7580    return SCIP_OKAY;
7581 }
7582 
7583 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7584 static
separateCons(SCIP * scip,SCIP_CONS * cons,SCIP_CONSHDLRDATA * conshdlrdata,SCIP_SOL * sol,SCIP_Bool separatecards,SCIP_Bool separateall,int * ncuts,SCIP_Bool * cutoff)7585 SCIP_RETCODE separateCons(
7586    SCIP*                 scip,               /**< SCIP data structure */
7587    SCIP_CONS*            cons,               /**< linear constraint */
7588    SCIP_CONSHDLRDATA*    conshdlrdata,       /**< constraint handler data */
7589    SCIP_SOL*             sol,                /**< primal CIP solution, NULL for current LP solution */
7590    SCIP_Bool             separatecards,      /**< should knapsack cardinality cuts be generated? */
7591    SCIP_Bool             separateall,        /**< should all constraints be subject to cardinality cut generation instead of only
7592                                               *   the ones with non-zero dual value? */
7593    int*                  ncuts,              /**< pointer to add up the number of found cuts */
7594    SCIP_Bool*            cutoff              /**< pointer to store whether a cutoff was found */
7595    )
7596 {
7597    SCIP_CONSDATA* consdata;
7598    SCIP_Bool violated;
7599    int oldncuts;
7600 
7601    assert(scip != NULL);
7602    assert(conshdlrdata != NULL);
7603    assert(cons != NULL);
7604    assert(cutoff != NULL);
7605 
7606    consdata = SCIPconsGetData(cons);
7607    assert(ncuts != NULL);
7608    assert(consdata != NULL);
7609 
7610    oldncuts = *ncuts;
7611    *cutoff = FALSE;
7612 
7613    SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7614 
7615    if( violated )
7616    {
7617       /* insert LP row as cut */
7618       SCIP_CALL( addRelaxation(scip, cons, cutoff) );
7619       (*ncuts)++;
7620    }
7621    else if( !SCIPconsIsModifiable(cons) && separatecards )
7622    {
7623       /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7624       if( !separateall && sol == NULL )
7625       {
7626          /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7627          if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7628          {
7629             SCIP_Real dualsol;
7630 
7631             dualsol = SCIProwGetDualsol(consdata->row);
7632             if( SCIPisFeasNegative(scip, dualsol) )
7633             {
7634                if( !SCIPisInfinity(scip, consdata->rhs) )
7635                {
7636                   SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7637                         consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7638                }
7639             }
7640             else if( SCIPisFeasPositive(scip, dualsol) )
7641             {
7642                if( !SCIPisInfinity(scip, -consdata->lhs) )
7643                {
7644                   SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7645                         consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7646                }
7647             }
7648          }
7649       }
7650       else
7651       {
7652          if( !SCIPisInfinity(scip, consdata->rhs) )
7653          {
7654             SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7655                   consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7656          }
7657          if( !SCIPisInfinity(scip, -consdata->lhs) )
7658          {
7659             SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7660                   consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7661          }
7662       }
7663    }
7664 
7665    if( *ncuts > oldncuts )
7666    {
7667       SCIP_CALL( SCIPresetConsAge(scip, cons) );
7668    }
7669 
7670    return SCIP_OKAY;
7671 }
7672 
7673 /** propagation method for linear constraints */
7674 static
propagateCons(SCIP * scip,SCIP_CONS * cons,SCIP_Bool tightenbounds,SCIP_Bool rangedrowpropagation,SCIP_Real maxeasyactivitydelta,SCIP_Bool sortvars,SCIP_Bool * cutoff,int * nchgbds)7675 SCIP_RETCODE propagateCons(
7676    SCIP*                 scip,               /**< SCIP data structure */
7677    SCIP_CONS*            cons,               /**< linear constraint */
7678    SCIP_Bool             tightenbounds,      /**< should the variable's bounds be tightened? */
7679    SCIP_Bool             rangedrowpropagation,/**< should ranged row propagation be performed? */
7680    SCIP_Real             maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7681    SCIP_Bool             sortvars,           /**< should variable sorting for faster propagation be used? */
7682    SCIP_Bool*            cutoff,             /**< pointer to store whether the node can be cut off */
7683    int*                  nchgbds             /**< pointer to count the total number of tightened bounds */
7684    )
7685 {
7686    SCIP_CONSDATA* consdata;
7687    SCIP_Real minactivity;
7688    SCIP_Real maxactivity;
7689    SCIP_Bool minactisrelax;
7690    SCIP_Bool maxactisrelax;
7691    SCIP_Bool isminsettoinfinity;
7692    SCIP_Bool ismaxsettoinfinity;
7693 
7694    assert(scip != NULL);
7695    assert(cons != NULL);
7696    assert(cutoff != NULL);
7697    assert(nchgbds != NULL);
7698 
7699    /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7700 
7701    consdata = SCIPconsGetData(cons);
7702    assert(consdata != NULL);
7703 
7704    if( consdata->eventdata == NULL )
7705    {
7706       SCIP_CONSHDLR* conshdlr;
7707       SCIP_CONSHDLRDATA* conshdlrdata;
7708 
7709       conshdlr = SCIPconsGetHdlr(cons);
7710       assert(conshdlr != NULL);
7711 
7712       conshdlrdata = SCIPconshdlrGetData(conshdlr);
7713       assert(conshdlrdata != NULL);
7714 
7715       /* catch bound change events of variables */
7716       SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
7717       assert(consdata->eventdata != NULL);
7718    }
7719 
7720    *cutoff = FALSE;
7721 
7722    /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7723    if( !SCIPconsIsModifiable(cons) )
7724    {
7725       /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7726       if( !SCIPinRepropagation(scip) )
7727       {
7728          SCIP_CALL( SCIPincConsAge(scip, cons) );
7729       }
7730 
7731       /* tighten the variable's bounds */
7732       if( tightenbounds )
7733       {
7734          int oldnchgbds;
7735 
7736          oldnchgbds = *nchgbds;
7737 
7738          SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7739 
7740          if( *nchgbds > oldnchgbds )
7741          {
7742             SCIP_CALL( SCIPresetConsAge(scip, cons) );
7743          }
7744       }
7745 
7746       /* propagate ranged rows */
7747       if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7748       {
7749          int nfixedvars;
7750          int naddconss;
7751          SCIPdebug( int oldnchgbds = *nchgbds; )
7752 
7753          nfixedvars = 0;
7754          naddconss = 0;
7755 
7756          SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7757 
7758          if( *cutoff )
7759          {
7760             SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7761          }
7762          else
7763          {
7764             SCIPdebug( SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars); )
7765          }
7766 
7767          if( nfixedvars > 0 )
7768             *nchgbds += 2*nfixedvars;
7769       } /*lint !e438*/
7770 
7771       /* check constraint for infeasibility and redundancy */
7772       if( !(*cutoff) )
7773       {
7774          consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
7775             &isminsettoinfinity, &ismaxsettoinfinity);
7776 
7777          if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7778          {
7779             SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7780                SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7781 
7782             /* analyze conflict */
7783             SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7784 
7785             SCIP_CALL( SCIPresetConsAge(scip, cons) );
7786             *cutoff = TRUE;
7787          }
7788          else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7789          {
7790             SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7791                SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7792 
7793             /* analyze conflict */
7794             SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7795 
7796             SCIP_CALL( SCIPresetConsAge(scip, cons) );
7797             *cutoff = TRUE;
7798          }
7799          else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7800          {
7801             SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7802                SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7803 
7804             /* remove the constraint locally unless it has become empty, in which case it is removed globally */
7805             if( consdata->nvars > 0 )
7806                SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7807             else
7808                SCIP_CALL( SCIPdelCons(scip, cons) );
7809          }
7810       }
7811    }
7812 
7813    return SCIP_OKAY;
7814 }
7815 
7816 
7817 /*
7818  * Presolving methods
7819  */
7820 
7821 /** converts all variables with fixed domain into FIXED variables */
7822 static
fixVariables(SCIP * scip,SCIP_CONS * cons,SCIP_Bool * cutoff,int * nfixedvars)7823 SCIP_RETCODE fixVariables(
7824    SCIP*                 scip,               /**< SCIP data structure */
7825    SCIP_CONS*            cons,               /**< linear constraint */
7826    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
7827    int*                  nfixedvars          /**< pointer to count the total number of fixed variables */
7828    )
7829 {
7830    SCIP_CONSDATA* consdata;
7831    SCIP_VAR* var;
7832    SCIP_VARSTATUS varstatus;
7833    SCIP_Real lb;
7834    SCIP_Real ub;
7835    SCIP_Bool fixed;
7836    SCIP_Bool infeasible;
7837    int v;
7838 
7839    assert(scip != NULL);
7840    assert(cons != NULL);
7841    assert(cutoff != NULL);
7842    assert(nfixedvars != NULL);
7843 
7844    consdata = SCIPconsGetData(cons);
7845    assert(consdata != NULL);
7846 
7847    for( v = 0; v < consdata->nvars; ++v )
7848    {
7849       assert(consdata->vars != NULL);
7850       var = consdata->vars[v];
7851       varstatus = SCIPvarGetStatus(var);
7852 
7853       if( varstatus != SCIP_VARSTATUS_FIXED )
7854       {
7855          lb = SCIPvarGetLbGlobal(var);
7856          ub = SCIPvarGetUbGlobal(var);
7857          if( SCIPisEQ(scip, lb, ub) )
7858          {
7859             SCIP_Real fixval;
7860 
7861             fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7862             SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7863                SCIPvarGetName(var), lb, ub, fixval);
7864             SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7865             if( infeasible )
7866             {
7867                SCIPdebugMsg(scip, " -> infeasible fixing\n");
7868                *cutoff = TRUE;
7869                return SCIP_OKAY;
7870             }
7871             if( fixed )
7872                (*nfixedvars)++;
7873          }
7874       }
7875    }
7876 
7877    SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7878 
7879    if( infeasible )
7880    {
7881       SCIPdebugMsg(scip, " -> infeasible fixing\n");
7882       *cutoff = TRUE;
7883       return SCIP_OKAY;
7884    }
7885 
7886    assert(consdata->removedfixings);
7887 
7888    return SCIP_OKAY;
7889 }
7890 
7891 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7892 
7893 /** extracts cliques of the constraint and adds them to SCIP
7894  *
7895  *  The following clique extraction mechanism are implemeneted
7896  *
7897  *  1. collect binary variables and sort them in non increasing order, then
7898  *
7899  *     a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7900  *        then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7901  *        condition
7902  *
7903  *            minactivity + vals[i] + vals[i+1] > rhs
7904  *
7905  *        and also add the binary to binary implication also for non-successive variables for which the same argument
7906  *        holds
7907  *
7908  *            minactivity + vals[i] + vals[j] > rhs
7909  *
7910  *        e.g. 5.3 x1 + 3.6 x2 + 3.3 x3 + 2.1 x4 <= 5.5 (all x are binary) would lead to the clique (x1, x2, x3) and the
7911  *             binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7912  *
7913  *     b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7914  *        then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7915  *        condition
7916  *
7917  *            maxactivity + vals[i] + vals[i-1] < lhs
7918  *
7919  *        and also add the binary to binary implication also for non-successive variables for which the same argument
7920  *        holds
7921  *
7922  *            maxactivity + vals[i] + vals[j] < lhs
7923  *
7924  *        e.g. you could multiply the above example by -1
7925  *
7926  *     c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7927  *        clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7928  *        condition
7929  *
7930  *            minactivity - vals[i] - vals[i-1] > rhs
7931  *
7932  *        and also add the binary to binary implication also for non-successive variables for which the
7933  *        same argument holds
7934  *
7935  *            minactivity - vals[i] - vals[j] > rhs
7936  *
7937  *        e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7938  *             implication x1 = 0 => x3 = 1
7939  *
7940  *     d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7941  *        clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7942  *        condition
7943  *
7944  *            maxactivity - vals[i] - vals[i+1] < lhs
7945  *
7946  *        and also add the binary to binary implication also for non-successive variables for which the same argument
7947  *        holds
7948  *
7949  *            maxactivity - vals[i] - vals[j] < lhs
7950  *
7951  *        e.g. you could multiply the above example by -1
7952  *
7953  *  2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7954  *     as clique, (this part is done at the end of the method)
7955  *
7956  */
7957 static
extractCliques(SCIP * scip,SCIP_CONS * cons,SCIP_Real maxeasyactivitydelta,SCIP_Bool sortvars,int * nfixedvars,int * nchgbds,SCIP_Bool * cutoff)7958 SCIP_RETCODE extractCliques(
7959    SCIP*                 scip,               /**< SCIP data structure */
7960    SCIP_CONS*            cons,               /**< linear constraint */
7961    SCIP_Real             maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7962    SCIP_Bool             sortvars,           /**< should variables be used in sorted order? */
7963    int*                  nfixedvars,         /**< pointer to count number of fixed variables */
7964    int*                  nchgbds,            /**< pointer to count the total number of tightened bounds */
7965    SCIP_Bool*            cutoff              /**< pointer to store TRUE, if a cutoff was found */
7966    )
7967 {
7968    SCIP_VAR** vars;
7969    SCIP_Real* vals;
7970    SCIP_CONSDATA* consdata;
7971    SCIP_Bool lhsclique;
7972    SCIP_Bool rhsclique;
7973    SCIP_Bool finitelhs;
7974    SCIP_Bool finiterhs;
7975    SCIP_Bool finiteminact;
7976    SCIP_Bool finitemaxact;
7977    SCIP_Bool finitenegminact;
7978    SCIP_Bool finitenegmaxact;
7979    SCIP_Bool finiteposminact;
7980    SCIP_Bool finiteposmaxact;
7981    SCIP_Bool infeasible;
7982    SCIP_Bool stopped;
7983    int cliquenonzerosadded;
7984    int v;
7985    int i;
7986    int nposcoefs;
7987    int nnegcoefs;
7988    int nvars;
7989 
7990    assert(scip != NULL);
7991    assert(cons != NULL);
7992    assert(nfixedvars != NULL);
7993    assert(nchgbds != NULL);
7994    assert(cutoff != NULL);
7995    assert(!SCIPconsIsDeleted(cons));
7996 
7997    consdata = SCIPconsGetData(cons);
7998    assert(consdata != NULL);
7999 
8000    if( consdata->nvars < 2 )
8001       return SCIP_OKAY;
8002 
8003    /* add implications if posibble
8004     *
8005     * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
8006     * maximal absolute contribution and also only if this variable would force all other variables to their bound
8007     * corresponding to the global minimal activity of the constraint
8008     */
8009    if( !consdata->implsadded )
8010    {
8011       /* sort variables by variable type */
8012       SCIP_CALL( consdataSort(scip, consdata) );
8013 
8014       /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
8015        *       up front, might change sorting correspondingly
8016        */
8017       /* fast abort if no binaries exist */
8018       if( !SCIPvarIsBinary(consdata->vars[0]) )
8019       {
8020 #ifndef NDEBUG
8021          for( i = 1; i < consdata->nvars; i++ )
8022             assert(!SCIPvarIsBinary(consdata->vars[i]));
8023 #endif
8024          return SCIP_OKAY;
8025       }
8026       nvars = consdata->nvars;
8027       vars = consdata->vars;
8028       vals = consdata->vals;
8029 
8030       /* recompute activities if needed */
8031       if( !consdata->validactivities )
8032          consdataCalcActivities(scip, consdata);
8033       assert(consdata->validactivities);
8034 
8035       finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8036       finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8037       finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8038       finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8039       finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8040       finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8041       finiteminact = (finitenegminact && finiteposminact);
8042       finitemaxact = (finitenegmaxact && finiteposmaxact);
8043 
8044       if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8045       {
8046          SCIP_Real maxabscontrib = -1.0;
8047          SCIP_Bool posval = FALSE;
8048          SCIP_Bool allbinary = TRUE;
8049          int oldnchgbds = *nchgbds;
8050          int nbdchgs = 0;
8051          int nimpls = 0;
8052          int position = -1;
8053 
8054          /* we need a valid minimal/maximal activity to add cliques */
8055          if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8056          {
8057             consdataRecomputeGlbMinactivity(scip, consdata);
8058             assert(consdata->validglbminact);
8059          }
8060 
8061          if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8062          {
8063             consdataRecomputeGlbMaxactivity(scip, consdata);
8064             assert(consdata->validglbmaxact);
8065          }
8066          assert(consdata->validglbminact || consdata->validglbmaxact);
8067 
8068          /* @todo extend this to local/constraint probing */
8069 
8070          /* determine maximal contribution to the activity */
8071          for( v = nvars - 1; v >= 0; --v )
8072          {
8073             if( SCIPvarIsBinary(vars[v]) )
8074             {
8075                if( vals[v] > 0 )
8076                {
8077                   SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
8078 
8079                   if( value > maxabscontrib )
8080                   {
8081                      maxabscontrib = value;
8082                      position = v;
8083                      posval = TRUE;
8084                   }
8085                }
8086                else
8087                {
8088                   SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
8089 
8090                   value = REALABS(value);
8091 
8092                   if( value > maxabscontrib )
8093                   {
8094                      maxabscontrib = value;
8095                      position = v;
8096                      posval = FALSE;
8097                   }
8098                }
8099             }
8100             else
8101                allbinary = FALSE;
8102          }
8103          assert(0 <= position && position < nvars);
8104 
8105          if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
8106          {
8107             /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
8108              * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8109              * implications
8110              */
8111             if( finiterhs && finiteminact && SCIPisEQ(scip, consdata->glbminactivity, consdata->rhs - maxabscontrib) )
8112             {
8113                for( v = nvars - 1; v >= 0; --v )
8114                {
8115                   /* binary to binary implications will be collected when extrating cliques */
8116                   if( !SCIPvarIsBinary(vars[v]) )
8117                   {
8118                      if( v != position )
8119                      {
8120                         if( vals[v] > 0 )
8121                         {
8122                            /* add implications */
8123                            SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8124                            ++nimpls;
8125                            *nchgbds += nbdchgs;
8126                         }
8127                         else
8128                         {
8129                            /* add implications */
8130                            SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8131                            ++nimpls;
8132                            *nchgbds += nbdchgs;
8133                         }
8134 
8135                         if( infeasible )
8136                         {
8137                            *cutoff = TRUE;
8138                            break;
8139                         }
8140                      }
8141                   }
8142                   /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8143                   else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8144                      break;
8145                }
8146             }
8147 
8148             /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
8149              * influence to their bound forces all other variables to be at their minimal contribution, we can add these
8150              * implications
8151              */
8152             if( finitelhs && finitemaxact && SCIPisEQ(scip, consdata->glbmaxactivity, consdata->lhs - maxabscontrib) )
8153             {
8154                for( v = nvars - 1; v >= 0; --v )
8155                {
8156                   /* binary to binary implications will be collected when extrating cliques */
8157                   if( !SCIPvarIsBinary(vars[v]) )
8158                   {
8159                      if( v != position )
8160                      {
8161                         if( vals[v] > 0 )
8162                         {
8163                            /* add implications */
8164                            SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
8165                            ++nimpls;
8166                            *nchgbds += nbdchgs;
8167                         }
8168                         else
8169                         {
8170                            /* add implications */
8171                            SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
8172                            ++nimpls;
8173                            *nchgbds += nbdchgs;
8174                         }
8175 
8176                         if( infeasible )
8177                         {
8178                            *cutoff = TRUE;
8179                            break;
8180                         }
8181                      }
8182                   }
8183                   /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
8184                   else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
8185                      break;
8186                }
8187             }
8188 
8189             /* did we find some implications */
8190             if( nimpls > 0 )
8191             {
8192                SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
8193 
8194                if( *cutoff )
8195                   return SCIP_OKAY;
8196 
8197                /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8198                if( *nchgbds - oldnchgbds > 0 )
8199                {
8200                   /* check for fixed variables */
8201                   SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8202                   if( *cutoff )
8203                      return SCIP_OKAY;
8204 
8205                   /* tighten variable's bounds */
8206                   SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8207                   if( *cutoff )
8208                      return SCIP_OKAY;
8209 
8210                   /* check for fixed variables */
8211                   SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8212                   if( *cutoff )
8213                      return SCIP_OKAY;
8214                }
8215             }
8216          }
8217       }
8218 
8219       consdata->implsadded = TRUE;
8220    }
8221 
8222    /* check if we already added the cliques of this constraint */
8223    if( consdata->cliquesadded )
8224       return SCIP_OKAY;
8225 
8226    consdata->cliquesadded = TRUE;
8227    cliquenonzerosadded = 0;
8228    stopped = FALSE;
8229 
8230    /* sort variables by variable type */
8231    SCIP_CALL( consdataSort(scip, consdata) );
8232 
8233    nvars = consdata->nvars;
8234    vars = consdata->vars;
8235    vals = consdata->vals;
8236 
8237    /**@todo extract more cliques, implications and variable bounds from linear constraints */
8238 
8239    /* recompute activities if needed */
8240    if( !consdata->validactivities )
8241       consdataCalcActivities(scip, consdata);
8242    assert(consdata->validactivities);
8243 
8244    finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
8245    finiterhs = !SCIPisInfinity(scip, consdata->rhs);
8246    finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
8247    finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
8248    finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
8249    finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
8250    finiteminact = (finitenegminact && finiteposminact);
8251    finitemaxact = (finitenegmaxact && finiteposmaxact);
8252 
8253    /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
8254     *    information
8255     */
8256    if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
8257    {
8258       SCIP_VAR** binvars;
8259       SCIP_Real* binvarvals;
8260       int nposbinvars = 0;
8261       int nnegbinvars = 0;
8262       int allonebinary = 0;
8263 
8264       SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
8265       SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
8266 
8267       /* collect binary variables */
8268       for( i = 0; i < nvars; ++i )
8269       {
8270          if( SCIPvarIsBinary(vars[i]) )
8271          {
8272             assert(!SCIPisZero(scip, vals[i]));
8273 
8274             if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8275                ++allonebinary;
8276 
8277             binvars[nposbinvars + nnegbinvars] = vars[i];
8278             binvarvals[nposbinvars + nnegbinvars] = vals[i];
8279 
8280             if( SCIPisPositive(scip, vals[i]) )
8281                ++nposbinvars;
8282             else
8283                ++nnegbinvars;
8284 
8285             assert(nposbinvars + nnegbinvars <= nvars);
8286          }
8287          /* stop searching for binary variables, because the constraint data is sorted */
8288          else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8289             break;
8290       }
8291       assert(nposbinvars + nnegbinvars <= nvars);
8292 
8293       /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8294        * cliques
8295        */
8296       if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8297       {
8298          SCIP_Real threshold;
8299          int oldnchgbds = *nchgbds;
8300          int nbdchgs;
8301          int jstart;
8302          int j;
8303 
8304          /* we need a valid minimal/maximal activity to add cliques */
8305          if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8306          {
8307             consdataRecomputeGlbMinactivity(scip, consdata);
8308             assert(consdata->validglbminact);
8309          }
8310 
8311          if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8312          {
8313             consdataRecomputeGlbMaxactivity(scip, consdata);
8314             assert(consdata->validglbmaxact);
8315          }
8316          assert(consdata->validglbminact || consdata->validglbmaxact);
8317 
8318          /* sort coefficients non-increasing to be faster in the clique search */
8319          SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8320 
8321          /* case a) */
8322          if( finiterhs && finitenegminact && nposbinvars >= 2 )
8323          {
8324             /* compute value that needs to be exceeded */
8325             threshold = consdata->rhs - consdata->glbminactivity;
8326 
8327             j = 1;
8328 #ifdef SCIP_DISABLED_CODE /* assertion should only hold when constraints were fully propagated and boundstightened */
8329             /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8330             assert(SCIPisFeasLE(scip, binvarvals[0], threshold));
8331 #endif
8332             /* check if at least two variables are in a clique */
8333             if( SCIPisFeasGT(scip, binvarvals[0] + binvarvals[j], threshold) )
8334             {
8335                ++j;
8336                /* check for extending the clique */
8337                while( j < nposbinvars )
8338                {
8339                   if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8340                      break;
8341                   ++j;
8342                }
8343                assert(j >= 2);
8344 
8345                /* add clique with at least two variables */
8346                SCIP_CALL( SCIPaddClique(scip, binvars, NULL, j, FALSE, &infeasible, &nbdchgs) );
8347 
8348                if( infeasible )
8349                   *cutoff = TRUE;
8350 
8351                *nchgbds += nbdchgs;
8352 
8353                cliquenonzerosadded += j;
8354                if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8355                   stopped = TRUE;
8356 
8357                /* exchange the last variable in the clique if possible and add all new ones */
8358                if( !stopped && !(*cutoff) && j < nposbinvars )
8359                {
8360                   SCIP_VAR** clqvars;
8361                   int lastfit = j - 2;
8362                   assert(lastfit >= 0);
8363 
8364                   /* copy all 'main'-clique variables */
8365                   SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8366 
8367                   /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8368                   while( lastfit >= 0 && j < nposbinvars )
8369                   {
8370                      /* check if two variables are in a clique */
8371                      if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8372                      {
8373                         clqvars[lastfit + 1] = binvars[j];
8374 
8375                         /* add clique with at least two variables */
8376                         SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8377 
8378                         if( infeasible )
8379                         {
8380                            *cutoff = TRUE;
8381                            break;
8382                         }
8383 
8384                         *nchgbds += nbdchgs;
8385 
8386                         cliquenonzerosadded += (lastfit + 2);
8387                         if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8388                         {
8389                            stopped = TRUE;
8390                            break;
8391                         }
8392 
8393                         ++j;
8394                      }
8395                      else
8396                         --lastfit;
8397                   }
8398 
8399                   SCIPfreeBufferArray(scip, &clqvars);
8400                }
8401             }
8402          }
8403 
8404          /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8405          if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8406          {
8407             /* check for fixed variables */
8408             SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8409 
8410             if( !*cutoff )
8411             {
8412                /* tighten variable's bounds */
8413                SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8414 
8415                if( !*cutoff )
8416                {
8417                   /* check for fixed variables */
8418                   SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8419 
8420                   if( !*cutoff )
8421                   {
8422                      /* sort variables by variable type */
8423                      SCIP_CALL( consdataSort(scip, consdata) );
8424 
8425                      /* recompute activities if needed */
8426                      if( !consdata->validactivities )
8427                         consdataCalcActivities(scip, consdata);
8428                      assert(consdata->validactivities);
8429 
8430                      nvars = consdata->nvars;
8431                      vars = consdata->vars;
8432                      vals = consdata->vals;
8433                      nposbinvars = 0;
8434                      nnegbinvars = 0;
8435                      allonebinary = 0;
8436 
8437                      /* update binary variables */
8438                      for( i = 0; i < nvars; ++i )
8439                      {
8440                         if( SCIPvarIsBinary(vars[i]) )
8441                         {
8442                            assert(!SCIPisZero(scip, vals[i]));
8443 
8444                            if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8445                               ++allonebinary;
8446 
8447                            binvars[nposbinvars + nnegbinvars] = vars[i];
8448                            binvarvals[nposbinvars + nnegbinvars] = vals[i];
8449 
8450                            if( SCIPisPositive(scip, vals[i]) )
8451                               ++nposbinvars;
8452                            else
8453                               ++nnegbinvars;
8454 
8455                            assert(nposbinvars + nnegbinvars <= nvars);
8456                         }
8457                         /* stop searching for binary variables, because the constraint data is sorted */
8458                         else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8459                            break;
8460                      }
8461                      assert(nposbinvars + nnegbinvars <= nvars);
8462                   }
8463                }
8464             }
8465 
8466             oldnchgbds = *nchgbds;
8467          }
8468 
8469          /* case b) */
8470          if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8471          {
8472             /* compute value that needs to be deceeded */
8473             threshold = consdata->lhs - consdata->glbmaxactivity;
8474 
8475             i = nposbinvars + nnegbinvars - 1;
8476             j = i - 1;
8477 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8478             /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8479             assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8480 #endif
8481             /* check if two variables are in a clique */
8482             if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8483             {
8484                --j;
8485                /* check for extending the clique */
8486                while( j >= nposbinvars )
8487                {
8488                   if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8489                      break;
8490                   --j;
8491                }
8492                jstart = j;
8493 
8494                assert(i - j >= 2);
8495                /* add clique with at least two variables */
8496                SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8497 
8498                if( infeasible )
8499                   *cutoff = TRUE;
8500 
8501                *nchgbds += nbdchgs;
8502 
8503                cliquenonzerosadded += (i - j);
8504                if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8505                   stopped = TRUE;
8506 
8507                /* exchange the last variable in the clique if possible and add all new ones */
8508                if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8509                {
8510                   SCIP_VAR** clqvars;
8511                   int lastfit = jstart + 1;
8512                   assert(lastfit < i);
8513 
8514                   /* copy all 'main'-clique variables */
8515                   SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8516                   ++lastfit;
8517 
8518                   /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8519                   while( lastfit <= i && j >= nposbinvars )
8520                   {
8521                      /* check if two variables are in a clique */
8522                      if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8523                      {
8524                         assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8525                         clqvars[lastfit - jstart - 2] = binvars[j];
8526 
8527                         assert(i - lastfit + 2 >= 2);
8528                         /* add clique with at least two variables */
8529                         SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8530 
8531                         if( infeasible )
8532                         {
8533                            *cutoff = TRUE;
8534                            break;
8535                         }
8536 
8537                         *nchgbds += nbdchgs;
8538 
8539                         cliquenonzerosadded += (i - lastfit + 2);
8540                         if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8541                         {
8542                            stopped = TRUE;
8543                            break;
8544                         }
8545 
8546                         --j;
8547                      }
8548                      else
8549                         ++lastfit;
8550                   }
8551 
8552                   SCIPfreeBufferArray(scip, &clqvars);
8553                }
8554             }
8555          }
8556 
8557          /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8558          if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8559          {
8560             /* check for fixed variables */
8561             SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8562 
8563             if( !*cutoff )
8564             {
8565                /* tighten variable's bounds */
8566                SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8567 
8568                if( !*cutoff )
8569                {
8570                   /* check for fixed variables */
8571                   SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8572 
8573                   if( !*cutoff )
8574                   {
8575                      /* sort variables by variable type */
8576                      SCIP_CALL( consdataSort(scip, consdata) );
8577 
8578                      /* recompute activities if needed */
8579                      if( !consdata->validactivities )
8580                         consdataCalcActivities(scip, consdata);
8581                      assert(consdata->validactivities);
8582 
8583                      nvars = consdata->nvars;
8584                      vars = consdata->vars;
8585                      vals = consdata->vals;
8586                      nposbinvars = 0;
8587                      nnegbinvars = 0;
8588                      allonebinary = 0;
8589 
8590                      /* update binary variables */
8591                      for( i = 0; i < nvars; ++i )
8592                      {
8593                         if( SCIPvarIsBinary(vars[i]) )
8594                         {
8595                            assert(!SCIPisZero(scip, vals[i]));
8596 
8597                            if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8598                               ++allonebinary;
8599 
8600                            binvars[nposbinvars + nnegbinvars] = vars[i];
8601                            binvarvals[nposbinvars + nnegbinvars] = vals[i];
8602 
8603                            if( SCIPisPositive(scip, vals[i]) )
8604                               ++nposbinvars;
8605                            else
8606                               ++nnegbinvars;
8607 
8608                            assert(nposbinvars + nnegbinvars <= nvars);
8609                         }
8610                         /* stop searching for binary variables, because the constraint data is sorted */
8611                         else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8612                            break;
8613                      }
8614                      assert(nposbinvars + nnegbinvars <= nvars);
8615                   }
8616                }
8617             }
8618 
8619             oldnchgbds = *nchgbds;
8620          }
8621 
8622          /* case c) */
8623          if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8624          {
8625             SCIP_Bool* values;
8626 
8627             /* initialize clique values array for adding a negated clique */
8628             SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8629             BMSclearMemoryArray(values, nnegbinvars);
8630 
8631             /* compute value that needs to be exceeded */
8632             threshold = consdata->rhs - consdata->glbminactivity;
8633 
8634             i = nposbinvars + nnegbinvars - 1;
8635             j = i - 1;
8636 
8637 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8638             /* check if the variable should not have already been fixed to one */
8639             assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8640 #endif
8641 
8642             if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8643             {
8644                --j;
8645                /* check for extending the clique */
8646                while( j >= nposbinvars )
8647                {
8648                   if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8649                      break;
8650                   --j;
8651                }
8652                jstart = j;
8653 
8654                assert(i - j >= 2);
8655                /* add negated clique with at least two variables */
8656                SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8657 
8658                if( infeasible )
8659                   *cutoff = TRUE;
8660 
8661                *nchgbds += nbdchgs;
8662 
8663                cliquenonzerosadded += (i - j);
8664                if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8665                   stopped = TRUE;
8666 
8667                /* exchange the last variable in the clique if possible and add all new ones */
8668                if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8669                {
8670                   SCIP_VAR** clqvars;
8671                   int lastfit = j + 1;
8672                   assert(lastfit < i);
8673 
8674                   /* copy all 'main'-clique variables */
8675                   SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8676                   ++lastfit;
8677 
8678                   /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8679                   while( lastfit <= i && j >= nposbinvars )
8680                   {
8681                      /* check if two variables are in a negated clique */
8682                      if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8683                      {
8684                         assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8685                         clqvars[lastfit - jstart - 2] = binvars[j];
8686 
8687                         assert(i - lastfit + 2 >= 2);
8688                         /* add clique with at least two variables */
8689                         SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8690 
8691                         if( infeasible )
8692                         {
8693                            *cutoff = TRUE;
8694                            break;
8695                         }
8696 
8697                         *nchgbds += nbdchgs;
8698 
8699                         cliquenonzerosadded += (i - lastfit + 2);
8700                         if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8701                         {
8702                            stopped = TRUE;
8703                            break;
8704                         }
8705 
8706                         --j;
8707                      }
8708                      else
8709                         ++lastfit;
8710                   }
8711 
8712                   SCIPfreeBufferArray(scip, &clqvars);
8713                }
8714             }
8715 
8716             SCIPfreeBufferArray(scip, &values);
8717          }
8718 
8719          /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8720          if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8721          {
8722             /* check for fixed variables */
8723             SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8724 
8725             if( !*cutoff )
8726             {
8727                /* tighten variable's bounds */
8728                SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8729 
8730                if( !*cutoff )
8731                {
8732                   /* check for fixed variables */
8733                   SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8734 
8735                   if( !*cutoff )
8736                   {
8737                      /* sort variables by variable type */
8738                      SCIP_CALL( consdataSort(scip, consdata) );
8739 
8740                      /* recompute activities if needed */
8741                      if( !consdata->validactivities )
8742                         consdataCalcActivities(scip, consdata);
8743                      assert(consdata->validactivities);
8744 
8745                      nvars = consdata->nvars;
8746                      vars = consdata->vars;
8747                      vals = consdata->vals;
8748                      nposbinvars = 0;
8749                      nnegbinvars = 0;
8750                      allonebinary = 0;
8751 
8752                      /* update binary variables */
8753                      for( i = 0; i < nvars; ++i )
8754                      {
8755                         if( SCIPvarIsBinary(vars[i]) )
8756                         {
8757                            assert(!SCIPisZero(scip, vals[i]));
8758 
8759                            if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8760                               ++allonebinary;
8761 
8762                            binvars[nposbinvars + nnegbinvars] = vars[i];
8763                            binvarvals[nposbinvars + nnegbinvars] = vals[i];
8764 
8765                            if( SCIPisPositive(scip, vals[i]) )
8766                               ++nposbinvars;
8767                            else
8768                               ++nnegbinvars;
8769 
8770                            assert(nposbinvars + nnegbinvars <= nvars);
8771                         }
8772                         /* stop searching for binary variables, because the constraint data is sorted */
8773                         else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8774                            break;
8775                      }
8776                      assert(nposbinvars + nnegbinvars <= nvars);
8777                   }
8778                }
8779             }
8780          }
8781 
8782          /* case d) */
8783          if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8784          {
8785             SCIP_Bool* values;
8786 
8787             /* initialize clique values array for adding a negated clique */
8788             SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8789             BMSclearMemoryArray(values, nposbinvars);
8790 
8791             /* compute value that needs to be exceeded */
8792             threshold = consdata->lhs - consdata->glbmaxactivity;
8793 
8794             j = 1;
8795 
8796 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8797             /* check if the variable should not have already been fixed to one */
8798             assert(!SCIPisFeasLT(scip, -binvarvals[0], threshold));
8799 #endif
8800 
8801             if( SCIPisFeasLT(scip, -binvarvals[0] - binvarvals[j], threshold) )
8802             {
8803                ++j;
8804                /* check for extending the clique */
8805                while( j < nposbinvars )
8806                {
8807                   if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8808                      break;
8809                   ++j;
8810                }
8811                assert(j >= 2);
8812 
8813                /* add negated clique with at least two variables */
8814                SCIP_CALL( SCIPaddClique(scip, binvars, values, j, FALSE, &infeasible, &nbdchgs) );
8815 
8816                if( infeasible )
8817                   *cutoff = TRUE;
8818 
8819                *nchgbds += nbdchgs;
8820 
8821                cliquenonzerosadded += j;
8822                if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8823                   stopped = TRUE;
8824 
8825                /* exchange the last variable in the clique if possible and add all new ones */
8826                if( !stopped && !(*cutoff) && j < nposbinvars )
8827                {
8828                   SCIP_VAR** clqvars;
8829                   int lastfit = j - 2;
8830                   assert(lastfit >= 0);
8831 
8832                   /* copy all 'main'-clique variables */
8833                   SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, binvars, j) );
8834 
8835                   /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8836                   while( lastfit >= 0 && j < nposbinvars )
8837                   {
8838                      /* check if two variables are in a negated clique */
8839                      if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8840                      {
8841                         clqvars[lastfit + 1] = binvars[j];
8842 
8843                         /* add clique with at least two variables */
8844                         SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8845 
8846                         if( infeasible )
8847                         {
8848                            *cutoff = TRUE;
8849                            break;
8850                         }
8851 
8852                         *nchgbds += nbdchgs;
8853 
8854                         cliquenonzerosadded += lastfit + 2;
8855                         if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8856                            break;
8857 
8858                         ++j;
8859                      }
8860                      else
8861                         --lastfit;
8862                   }
8863 
8864                   SCIPfreeBufferArray(scip, &clqvars);
8865                }
8866             }
8867 
8868             SCIPfreeBufferArray(scip, &values);
8869          }
8870       }
8871 
8872       SCIPfreeBufferArray(scip, &binvarvals);
8873       SCIPfreeBufferArray(scip, &binvars);
8874 
8875       if( *cutoff )
8876          return SCIP_OKAY;
8877    }
8878 
8879    /* 2. we only check if the constraint is a set packing / partitioning constraint */
8880 
8881    /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8882     * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8883     */
8884    nposcoefs = 0;
8885    nnegcoefs = 0;
8886    for( i = 0; i < nvars; ++i )
8887    {
8888       if( !SCIPvarIsBinary(vars[i]) )
8889          return SCIP_OKAY;
8890       else if( SCIPisEQ(scip, vals[i], +1.0) )
8891          nposcoefs++;
8892       else if( SCIPisEQ(scip, vals[i], -1.0) )
8893          nnegcoefs++;
8894       else
8895          return SCIP_OKAY;
8896    }
8897 
8898    lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8899    rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8900 
8901    if( lhsclique || rhsclique )
8902    {
8903       SCIP_Bool* values;
8904       int nbdchgs;
8905 
8906       SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8907          SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8908       SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8909 
8910       for( i = 0; i < nvars; ++i )
8911          values[i] = (rhsclique == (vals[i] > 0.0));
8912 
8913       SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8914 
8915       if( infeasible )
8916          *cutoff = TRUE;
8917 
8918       *nchgbds += nbdchgs;
8919       SCIPfreeBufferArray(scip, &values);
8920    }
8921 
8922    return SCIP_OKAY;
8923 }
8924 
8925 /** tightens left and right hand side of constraint due to integrality */
8926 static
tightenSides(SCIP * scip,SCIP_CONS * cons,int * nchgsides,SCIP_Bool * infeasible)8927 SCIP_RETCODE tightenSides(
8928    SCIP*                 scip,               /**< SCIP data structure */
8929    SCIP_CONS*            cons,               /**< linear constraint */
8930    int*                  nchgsides,          /**< pointer to count number of side changes */
8931    SCIP_Bool*            infeasible          /**< pointer to store whether infeasibility was detected */
8932    )
8933 {
8934    SCIP_CONSDATA* consdata;
8935    SCIP_Real newlhs;
8936    SCIP_Real newrhs;
8937    SCIP_Bool chglhs;
8938    SCIP_Bool chgrhs;
8939    SCIP_Bool integral;
8940    int i;
8941 
8942    assert(scip != NULL);
8943    assert(cons != NULL);
8944    assert(nchgsides != NULL);
8945    assert(infeasible != NULL);
8946 
8947    consdata = SCIPconsGetData(cons);
8948    assert(consdata != NULL);
8949 
8950    *infeasible = FALSE;
8951 
8952    chglhs = FALSE;
8953    chgrhs = FALSE;
8954    newlhs = -SCIPinfinity(scip);
8955    newrhs = SCIPinfinity(scip);
8956 
8957    if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8958    {
8959       integral = TRUE;
8960       for( i = 0; i < consdata->nvars && integral; ++i )
8961       {
8962          integral = SCIPisIntegral(scip, consdata->vals[i])
8963             && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
8964       }
8965       if( integral )
8966       {
8967          if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8968          {
8969             newlhs = SCIPfeasCeil(scip, consdata->lhs);
8970             chglhs = TRUE;
8971          }
8972          if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8973          {
8974             newrhs = SCIPfeasFloor(scip, consdata->rhs);
8975             chgrhs = TRUE;
8976          }
8977 
8978          /* check whether rounding would lead to an unsatisfiable constraint */
8979          if( SCIPisGT(scip, newlhs, newrhs) )
8980          {
8981             SCIPdebugMsg(scip, "rounding sides=[%.15g,%.15g] of linear constraint <%s> with integral coefficients and variables only "
8982                   "is infeasible\n", consdata->lhs, consdata->rhs, SCIPconsGetName(cons));
8983 
8984             *infeasible = TRUE;
8985             return SCIP_OKAY;
8986          }
8987 
8988          SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8989             SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8990 
8991          if( chglhs )
8992          {
8993             assert(!SCIPisInfinity(scip, -newlhs));
8994 
8995             SCIP_CALL( chgLhs(scip, cons, newlhs) );
8996             if( !consdata->upgraded )
8997                (*nchgsides)++;
8998          }
8999          if( chgrhs )
9000          {
9001             assert(!SCIPisInfinity(scip, newrhs));
9002 
9003             SCIP_CALL( chgRhs(scip, cons, newrhs) );
9004             if( !consdata->upgraded )
9005                (*nchgsides)++;
9006          }
9007          SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
9008             SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
9009       }
9010    }
9011 
9012    return SCIP_OKAY;
9013 }
9014 
9015 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
9016  *  given an inequality  lhs <= a*x + ai*xi <= rhs, with a non-continuous variable  li <= xi <= ui
9017  *  let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
9018  *  (i) ai >= 0:
9019  *      if  minact + ai >= lhs  and  maxact - ai <= rhs: (**)
9020  *       - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
9021  *       - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9022  *         xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9023  *       - change coefficients:
9024  *           ai'  := max(lhs - minact, maxact - rhs)
9025  *           lhs' := lhs - (ai - ai')*li
9026  *           rhs' := rhs - (ai - ai')*ui
9027  * (ii) ai < 0:
9028  *      if  minact - ai >= lhs  and  maxact + ai <= rhs: (***)
9029  *       - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
9030  *       - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
9031  *         xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
9032  *       - change coefficients:
9033  *           ai'  := min(rhs - maxact, minact - lhs)
9034  *           lhs' := lhs - (ai - ai')*ui
9035  *           rhs' := rhs - (ai - ai')*li
9036  *
9037  *  We further try to remove redundant variable from the constraint;
9038  *  Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
9039  *  A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
9040  *  variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
9041  *  the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
9042  *  E.g., for binary variables and an inequality x_1 +x_2 +10y_1 +10y_2 >= 5, setting either of the y_i to one
9043  *  suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
9044  *
9045  *  @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
9046  *        cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
9047  */
9048 static
consdataTightenCoefs(SCIP * scip,SCIP_CONS * cons,int * nchgcoefs,int * nchgsides)9049 SCIP_RETCODE consdataTightenCoefs(
9050    SCIP*                 scip,               /**< SCIP data structure */
9051    SCIP_CONS*            cons,               /**< linear constraint */
9052    int*                  nchgcoefs,          /**< pointer to count total number of changed coefficients */
9053    int*                  nchgsides           /**< pointer to count number of side changes */
9054    )
9055 {
9056    SCIP_CONSDATA* consdata;
9057    SCIP_VAR* var;
9058    SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
9059                            * activity, ignoring the coefficients contributing with infinite value */
9060    SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
9061                            * activity, ignoring the coefficients contributing with infinite value */
9062    SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
9063    SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
9064    SCIP_Bool isminsettoinfinity;
9065    SCIP_Bool ismaxsettoinfinity;
9066    SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
9067    SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
9068    SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
9069    SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
9070    SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
9071    SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
9072    SCIP_Real val;
9073    SCIP_Real newval;
9074    SCIP_Real newlhs;
9075    SCIP_Real newrhs;
9076    SCIP_Real lb;
9077    SCIP_Real ub;
9078    int i;
9079 
9080    assert(scip != NULL);
9081    assert(cons != NULL);
9082    assert(nchgcoefs != NULL);
9083    assert(nchgsides != NULL);
9084 
9085    consdata = SCIPconsGetData(cons);
9086    assert(consdata != NULL);
9087 
9088    /* @todo Is this still needed with automatic recomputation of activities? */
9089    /* if the maximal coefficient is too large, recompute the activities */
9090    if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
9091       || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
9092    {
9093       consdataRecomputeMinactivity(scip, consdata);
9094       consdataRecomputeMaxactivity(scip, consdata);
9095    }
9096 
9097    /* get the minimal and maximal activity of the constraint */
9098    consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9099       &isminsettoinfinity, &ismaxsettoinfinity);
9100 
9101    minleftactivity = 0.0;
9102    maxleftactivity = 0.0;
9103 
9104    /* try to tighten each coefficient */
9105    i = 0;
9106    while( i < consdata->nvars )
9107    {
9108       var = consdata->vars[i];
9109 
9110       /* get coefficient and variable's bounds */
9111       lb = SCIPvarGetLbLocal(var);
9112       ub = SCIPvarGetUbLocal(var);
9113       val = consdata->vals[i];
9114       assert(!SCIPisZero(scip, val));
9115 
9116       /* check sign of coefficient */
9117       if( val >= 0.0 )
9118       {
9119          /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9120          if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS &&
9121             SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
9122          {
9123             /* change coefficients:
9124              *   ai'  := max(lhs - minact, maxact - rhs)
9125              *   lhs' := lhs - (ai - ai')*li
9126              *   rhs' := rhs - (ai - ai')*ui
9127              */
9128 
9129             lval = consdata->lhs - minactivity;
9130             rval = maxactivity - consdata->rhs;
9131 
9132             /* Try to avoid cancellation, if there are only two variables */
9133             if( consdata->nvars == 2 )
9134             {
9135                SCIP_Real otherval;
9136                otherval = consdata->vals[1-i];
9137 
9138                if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9139                {
9140                   lval = consdata->lhs - val*lb;
9141                   lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9142                }
9143 
9144                if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9145                {
9146                   rval = val*ub - consdata->rhs;
9147                   rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9148                }
9149             }
9150 
9151             newval = MAX(lval, rval);
9152             assert(SCIPisSumRelLE(scip, newval, val));
9153 
9154             /* Try to avoid cancellation in computation of lhs/rhs */
9155             newlhs = consdata->lhs - val * lb;
9156             newlhs += newval * lb;
9157             newrhs = consdata->rhs - val * ub;
9158             newrhs += newval * ub;
9159 
9160             if( !SCIPisSumRelEQ(scip, newval, val) )
9161             {
9162                SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9163                   SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9164                   minactivity, maxactivity, consdata->lhs, consdata->rhs);
9165 
9166                /* update the coefficient and the activity bounds */
9167                if( SCIPisZero(scip, newval) )
9168                {
9169                   SCIP_CALL( delCoefPos(scip, cons, i) );
9170                   i--;
9171                }
9172                else
9173                {
9174                   SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9175                }
9176                (*nchgcoefs)++;
9177 
9178                /* get the new minimal and maximal activity of the constraint */
9179                consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9180                   &isminsettoinfinity, &ismaxsettoinfinity);
9181 
9182                if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9183                {
9184                   SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9185 
9186                   SCIP_CALL( chgLhs(scip, cons, newlhs) );
9187                   (*nchgsides)++;
9188                   assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9189                }
9190 
9191                if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9192                {
9193                   SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9194 
9195                   SCIP_CALL( chgRhs(scip, cons, newrhs) );
9196                   (*nchgsides)++;
9197                   assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9198                }
9199             }
9200          }
9201          else
9202          {
9203             if( !SCIPisInfinity(scip, -minleftactivity) )
9204             {
9205                assert(!SCIPisInfinity(scip, val));
9206                assert(!SCIPisInfinity(scip, lb));
9207                if( SCIPisInfinity(scip, -lb) )
9208                   minleftactivity = -SCIPinfinity(scip);
9209                else
9210                   minleftactivity += val * lb;
9211             }
9212 
9213             if( !SCIPisInfinity(scip, maxleftactivity) )
9214             {
9215                assert(!SCIPisInfinity(scip, val));
9216                assert(!SCIPisInfinity(scip, -ub));
9217                if( SCIPisInfinity(scip,ub) )
9218                   maxleftactivity = SCIPinfinity(scip);
9219                else
9220                   maxleftactivity += val * ub;
9221             }
9222          }
9223       }
9224       else
9225       {
9226          /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
9227          if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS &&
9228             SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
9229          {
9230             /* change coefficients:
9231              *   ai'  := min(rhs - maxact, minact - lhs)
9232              *   lhs' := lhs - (ai - ai')*ui
9233              *   rhs' := rhs - (ai - ai')*li
9234              */
9235 
9236             lval = minactivity - consdata->lhs;
9237             rval = consdata->rhs - maxactivity;
9238 
9239             /* Try to avoid cancellation, if there are only two variables */
9240             if( consdata->nvars == 2 )
9241             {
9242                SCIP_Real otherval;
9243                otherval = consdata->vals[1-i];
9244 
9245                if( !SCIPisInfinity(scip, -consdata->lhs) && !isminsettoinfinity )
9246                {
9247                   lval = val*ub - consdata->lhs;
9248                   lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
9249                }
9250 
9251                if( !SCIPisInfinity(scip, consdata->rhs) && !ismaxsettoinfinity )
9252                {
9253                   rval = consdata->rhs - val*lb;
9254                   rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
9255                }
9256             }
9257 
9258             newval = MIN(lval, rval);
9259             assert(SCIPisSumRelGE(scip, newval, val));
9260 
9261             /* Try to avoid cancellation in computation of lhs/rhs */
9262             newlhs = consdata->lhs - val * ub;
9263             newlhs += newval * ub;
9264             newrhs = consdata->rhs - val * lb;
9265             newrhs += newval * lb;
9266 
9267             if( !SCIPisSumRelEQ(scip, newval, val) )
9268             {
9269                SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
9270                   SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
9271                   minactivity, maxactivity, consdata->lhs, consdata->rhs);
9272 
9273                /* update the coefficient and the activity bounds */
9274                if( SCIPisZero(scip, newval) )
9275                {
9276                   SCIP_CALL( delCoefPos(scip, cons, i) );
9277                   i--;
9278                }
9279                else
9280                {
9281                   SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
9282                }
9283                (*nchgcoefs)++;
9284 
9285                /* get the new minimal and maximal activity of the constraint */
9286                consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9287                   &isminsettoinfinity, &ismaxsettoinfinity);
9288 
9289                if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
9290                {
9291                   SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9292 
9293                   SCIP_CALL( chgLhs(scip, cons, newlhs) );
9294                   (*nchgsides)++;
9295                   assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9296                }
9297 
9298                if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
9299                {
9300                   SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9301 
9302                   SCIP_CALL( chgRhs(scip, cons, newrhs) );
9303                   (*nchgsides)++;
9304                   assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9305                }
9306             }
9307          }
9308          else
9309          {
9310             if( !SCIPisInfinity(scip, -minleftactivity) )
9311             {
9312                assert(!SCIPisInfinity(scip, -val));
9313                assert(!SCIPisInfinity(scip, -ub));
9314                if( SCIPisInfinity(scip, ub) )
9315                   minleftactivity = -SCIPinfinity(scip);
9316                else
9317                   minleftactivity += val * ub;
9318             }
9319 
9320             if( !SCIPisInfinity(scip, maxleftactivity) )
9321             {
9322                assert(!SCIPisInfinity(scip, -val));
9323                assert(!SCIPisInfinity(scip, lb));
9324                if( SCIPisInfinity(scip, -lb) )
9325                   maxleftactivity = SCIPinfinity(scip);
9326                else
9327                   maxleftactivity += val * lb;
9328             }
9329          }
9330       }
9331       ++i;
9332    }
9333 
9334    SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9335       minleftactivity, consdata->rhs);
9336    SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9337       maxleftactivity, consdata->lhs);
9338 
9339    /* minleft == \infty  ==>  minactivity == \infty */
9340    assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9341    assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9342 
9343    /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9344     * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9345     * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9346     * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9347     */
9348    assert(!SCIPisInfinity(scip, minactivity));
9349    if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9350       return SCIP_OKAY;
9351 
9352    /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9353     * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9354     * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9355     * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9356     */
9357    assert(!SCIPisInfinity(scip, -maxactivity));
9358    if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9359       return SCIP_OKAY;
9360 
9361    /* correct lhs and rhs by min/max activity of surely non-redundant variables
9362     * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9363     */
9364    aggrlhs = consdata->lhs - minactivity + minleftactivity;
9365    aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9366 
9367    /* check if the constraint contains variables which are redundant. The reasoning is the following:
9368     * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9369     * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9370     * they can be removed from the constraint.
9371     * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9372     */
9373    if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9374       && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9375    {
9376       SCIP_Real minleftactivitypart;
9377       SCIP_Real maxleftactivitypart;
9378 
9379       assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9380 
9381       /* try to remove redundant variables from constraint */
9382       i = 0;
9383       while( i < consdata->nvars )
9384       {
9385          var = consdata->vars[i];
9386          minleftactivitypart = 0.0;
9387          maxleftactivitypart = 0.0;
9388          lb = SCIPvarGetLbLocal(var);
9389          ub = SCIPvarGetUbLocal(var);
9390 
9391          /* get coefficient and variable's bounds */
9392          val = consdata->vals[i];
9393          assert(!SCIPisZero(scip, val));
9394 
9395          /* check sign of coefficient */
9396          if( val >= 0.0 )
9397          {
9398             /* negation of condition above in case of positive val */
9399             if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9400                SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9401             {
9402                SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9403                SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9404                SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9405                   SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9406 
9407                minleftactivitypart = val * lb;
9408                maxleftactivitypart = val * ub;
9409 
9410                SCIP_CALL( delCoefPos(scip, cons, i) );
9411                i--;
9412 
9413                /* get the new minimal and maximal activity of the constraint */
9414                consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9415                   &isminsettoinfinity, &ismaxsettoinfinity);
9416 
9417                /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9418                 * huge contributions
9419                 */
9420                assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9421                assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9422             }
9423          }
9424          else
9425          {
9426             /* negation of condition above in case of negative val */
9427             if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9428                SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9429             {
9430                SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9431                   SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9432 
9433                minleftactivitypart = val * ub;
9434                maxleftactivitypart = val * lb;
9435 
9436                SCIP_CALL( delCoefPos(scip, cons, i) );
9437                i--;
9438 
9439                /* get the new minimal and maximal activity of the constraint */
9440                consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
9441                   &isminsettoinfinity, &ismaxsettoinfinity);
9442 
9443                /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9444                 * huge contributions
9445                 */
9446                assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9447                assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9448             }
9449          }
9450 
9451          /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9452           * redundant variables could get deleted,
9453           * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9454           * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9455           * we would also delete y2 and as a result we would have gotten infeasibility */
9456          /* adjust lhs and right hand side */
9457          newlhs = consdata->lhs - minleftactivitypart;
9458          newrhs = consdata->rhs - maxleftactivitypart;
9459 
9460          if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9461          {
9462             SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9463             SCIP_CALL( chgLhs(scip, cons, newlhs) );
9464             ++(*nchgsides);
9465             assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9466          }
9467          if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9468          {
9469             SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9470             SCIP_CALL( chgRhs(scip, cons, newrhs) );
9471             ++(*nchgsides);
9472             assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9473          }
9474          ++i;
9475       }
9476    }
9477 
9478    return SCIP_OKAY;
9479 }
9480 
9481 /** processes equality with only one variable by fixing the variable and deleting the constraint */
9482 static
convertUnaryEquality(SCIP * scip,SCIP_CONS * cons,SCIP_Bool * cutoff,int * nfixedvars,int * ndelconss)9483 SCIP_RETCODE convertUnaryEquality(
9484    SCIP*                 scip,               /**< SCIP data structure */
9485    SCIP_CONS*            cons,               /**< linear constraint */
9486    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
9487    int*                  nfixedvars,         /**< pointer to count number of fixed variables */
9488    int*                  ndelconss           /**< pointer to count number of deleted constraints */
9489    )
9490 {
9491    SCIP_CONSDATA* consdata;
9492    SCIP_VAR* var;
9493    SCIP_Real val;
9494    SCIP_Real fixval;
9495    SCIP_Bool infeasible;
9496    SCIP_Bool fixed;
9497 
9498    assert(scip != NULL);
9499    assert(cons != NULL);
9500    assert(cutoff != NULL);
9501    assert(nfixedvars != NULL);
9502    assert(ndelconss != NULL);
9503 
9504    consdata = SCIPconsGetData(cons);
9505    assert(consdata != NULL);
9506    assert(consdata->nvars == 1);
9507    assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9508 
9509    /* calculate the value to fix the variable to */
9510    var = consdata->vars[0];
9511    val = consdata->vals[0];
9512    assert(!SCIPisZero(scip, val));
9513    fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9514       consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9515    SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9516       SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9517 
9518    /* fix variable */
9519    SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9520    if( infeasible )
9521    {
9522       SCIPdebugMsg(scip, " -> infeasible fixing\n");
9523       *cutoff = TRUE;
9524       return SCIP_OKAY;
9525    }
9526    if( fixed )
9527       (*nfixedvars)++;
9528 
9529    /* disable constraint */
9530    SCIP_CALL( SCIPdelCons(scip, cons) );
9531    if( !consdata->upgraded )
9532       (*ndelconss)++;
9533 
9534    return SCIP_OKAY;
9535 }
9536 
9537 /** processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9538 static
convertBinaryEquality(SCIP * scip,SCIP_CONS * cons,SCIP_Bool * cutoff,int * naggrvars,int * ndelconss)9539 SCIP_RETCODE convertBinaryEquality(
9540    SCIP*                 scip,               /**< SCIP data structure */
9541    SCIP_CONS*            cons,               /**< linear constraint */
9542    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
9543    int*                  naggrvars,          /**< pointer to count number of aggregated variables */
9544    int*                  ndelconss           /**< pointer to count number of deleted constraints */
9545    )
9546 {
9547    SCIP_CONSDATA* consdata;
9548    SCIP_Bool infeasible;
9549    SCIP_Bool redundant;
9550    SCIP_Bool aggregated;
9551 
9552    assert(scip != NULL);
9553    assert(cons != NULL);
9554    assert(cutoff != NULL);
9555    assert(naggrvars != NULL);
9556    assert(ndelconss != NULL);
9557 
9558    consdata = SCIPconsGetData(cons);
9559    assert(consdata != NULL);
9560    assert(consdata->nvars == 2);
9561    assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9562 
9563    SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9564       SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9565       consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9566 
9567    /* aggregate the equality */
9568    SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9569          consdata->rhs, &infeasible, &redundant, &aggregated) );
9570 
9571    /* check for infeasibility of aggregation */
9572    if( infeasible )
9573    {
9574       SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9575       *cutoff = TRUE;
9576       return SCIP_OKAY;
9577    }
9578 
9579    /* count the aggregation */
9580    if( aggregated )
9581       (*naggrvars)++;
9582 
9583    /* delete the constraint, if it is redundant */
9584    if( redundant )
9585    {
9586       SCIP_CALL( SCIPdelCons(scip, cons) );
9587 
9588       if( !consdata->upgraded )
9589          (*ndelconss)++;
9590    }
9591 
9592    return SCIP_OKAY;
9593 }
9594 
9595 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9596 static
getNewSidesAfterAggregation(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_VAR * slackvar,SCIP_Real slackcoef,SCIP_Real * newlhs,SCIP_Real * newrhs)9597 void getNewSidesAfterAggregation(
9598    SCIP*                 scip,               /**< SCIP data structure */
9599    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
9600    SCIP_VAR*             slackvar,           /**< variable to be aggregated out */
9601    SCIP_Real             slackcoef,          /**< coefficient of variable in constraint */
9602    SCIP_Real*            newlhs,             /**< pointer to store new lhs of constraint */
9603    SCIP_Real*            newrhs              /**< pointer to store new rhs of constraint */
9604    )
9605 {
9606    SCIP_Real slackvarlb;
9607    SCIP_Real slackvarub;
9608 
9609    assert(scip != NULL);
9610    assert(consdata != NULL);
9611    assert(newlhs != NULL);
9612    assert(newrhs != NULL);
9613    assert(!SCIPisInfinity(scip, -consdata->lhs));
9614    assert(!SCIPisInfinity(scip, consdata->rhs));
9615 
9616    slackvarlb = SCIPvarGetLbGlobal(slackvar);
9617    slackvarub = SCIPvarGetUbGlobal(slackvar);
9618    if( slackcoef > 0.0 )
9619    {
9620       if( SCIPisInfinity(scip, -slackvarlb) )
9621          *newrhs = SCIPinfinity(scip);
9622       else
9623          *newrhs = consdata->rhs - slackcoef * slackvarlb;
9624       if( SCIPisInfinity(scip, slackvarub) )
9625          *newlhs = -SCIPinfinity(scip);
9626       else
9627          *newlhs = consdata->lhs - slackcoef * slackvarub;
9628    }
9629    else
9630    {
9631       if( SCIPisInfinity(scip, -slackvarlb) )
9632          *newlhs = -SCIPinfinity(scip);
9633       else
9634          *newlhs = consdata->rhs - slackcoef * slackvarlb;
9635       if( SCIPisInfinity(scip, slackvarub) )
9636          *newrhs = SCIPinfinity(scip);
9637       else
9638          *newrhs = consdata->lhs - slackcoef * slackvarub;
9639    }
9640    assert(SCIPisLE(scip, *newlhs, *newrhs));
9641 }
9642 
9643 /** processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9644  *  into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9645  *  is implicitly integral by this constraint
9646  *
9647  *  @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9648  *       can help.
9649  */
9650 static
convertLongEquality(SCIP * scip,SCIP_CONSHDLRDATA * conshdlrdata,SCIP_CONS * cons,SCIP_Bool * cutoff,int * naggrvars,int * ndelconss)9651 SCIP_RETCODE convertLongEquality(
9652    SCIP*                 scip,               /**< SCIP data structure */
9653    SCIP_CONSHDLRDATA*    conshdlrdata,       /**< linear constraint handler data */
9654    SCIP_CONS*            cons,               /**< linear constraint */
9655    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
9656    int*                  naggrvars,          /**< pointer to count number of aggregated variables */
9657    int*                  ndelconss           /**< pointer to count number of deleted constraints */
9658    )
9659 {
9660    SCIP_CONSDATA* consdata;
9661    SCIP_VAR** vars;
9662    SCIP_Real* vals;
9663    SCIP_VARTYPE bestslacktype;
9664    SCIP_VARTYPE slacktype;
9665    SCIP_Real lhs;
9666    SCIP_Real rhs;
9667    SCIP_Real bestslackdomrng;
9668    SCIP_Real minabsval;
9669    SCIP_Real maxabsval;
9670    SCIP_Bool bestremovescons;
9671    SCIP_Bool coefszeroone;
9672    SCIP_Bool coefsintegral;
9673    SCIP_Bool varsintegral;
9674    SCIP_Bool infeasible;
9675    SCIP_Bool samevar;
9676    int supinf;                               /* counter for infinite contributions to the supremum of a possible
9677                                               * multi-aggregation
9678                                               */
9679    int infinf;                               /* counter for infinite contributions to the infimum of a possible
9680                                               * multi-aggregation
9681                                               */
9682    int maxnlocksstay;
9683    int maxnlocksremove;
9684    int bestslackpos;
9685    int bestnlocks;
9686    int ncontvars;
9687    int contvarpos;
9688    int nintvars;
9689    int nimplvars;
9690    int intvarpos;
9691    int v;
9692 
9693    assert(scip != NULL);
9694    assert(cons != NULL);
9695    assert(cutoff != NULL);
9696    assert(naggrvars != NULL);
9697 
9698    consdata = SCIPconsGetData(cons);
9699    assert(consdata != NULL);
9700    assert(consdata->nvars > 2);
9701    assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9702 
9703    SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9704 
9705    /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9706     * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9707     *   maxnlocksstay:   maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9708     *   maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9709     */
9710    lhs = consdata->lhs;
9711    rhs = consdata->rhs;
9712    maxnlocksstay = 0;
9713    if( consdata->nvars == 3 )
9714    {
9715       /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9716        * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9717        */
9718       maxnlocksremove = 3;
9719    }
9720    else if( consdata->nvars == 4 )
9721    {
9722       /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9723        * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9724        */
9725       maxnlocksremove = 2;
9726    }
9727    else
9728    {
9729       /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9730       maxnlocksremove = 1;
9731    }
9732 
9733    /* the locks on this constraint can be ignored */
9734    if( SCIPconsIsChecked(cons) )
9735    {
9736       if( !SCIPisInfinity(scip, -lhs) )
9737       {
9738          maxnlocksstay++;
9739          maxnlocksremove++;
9740       }
9741       if( !SCIPisInfinity(scip, rhs) )
9742       {
9743          maxnlocksstay++;
9744          maxnlocksremove++;
9745       }
9746    }
9747 
9748    /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9749    vars = consdata->vars;
9750    vals = consdata->vals;
9751    bestslackpos = -1;
9752    bestslacktype = SCIP_VARTYPE_BINARY;
9753    bestnlocks = INT_MAX;
9754    bestremovescons = FALSE;
9755    bestslackdomrng = 0.0;
9756    coefszeroone = TRUE;
9757    coefsintegral = TRUE;
9758    varsintegral = TRUE;
9759    ncontvars = 0;
9760    contvarpos = -1;
9761    nintvars = 0;
9762    nimplvars = 0;
9763    intvarpos = -1;
9764    minabsval = SCIPinfinity(scip);
9765    maxabsval = -1.0;
9766    for( v = 0; v < consdata->nvars; ++v )
9767    {
9768       SCIP_VAR* var;
9769       SCIP_Real val;
9770       SCIP_Real absval;
9771       SCIP_Real varlb;
9772       SCIP_Real varub;
9773       SCIP_Bool iscont;
9774       int nlocks;
9775 
9776       assert(vars != NULL);
9777       assert(vals != NULL);
9778 
9779       var = vars[v];
9780       assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= 1); /* because variable is locked in this equality */
9781       assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= 1);
9782       varlb = SCIPvarGetLbGlobal(var);
9783       varub = SCIPvarGetUbGlobal(var);
9784 
9785       val = vals[v];
9786       absval = REALABS(val);
9787       assert(SCIPisPositive(scip, absval));
9788 
9789       /* calculate minimal and maximal absolute value */
9790       if( absval < minabsval )
9791          minabsval = absval;
9792       if( absval > maxabsval )
9793          maxabsval = absval;
9794 
9795       /* do not try to multi aggregate, when numerical bad */
9796       if( maxabsval / minabsval > conshdlrdata->maxmultaggrquot )
9797          return SCIP_OKAY;
9798 
9799       slacktype = SCIPvarGetType(var);
9800       coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9801       coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9802       varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9803       iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9804 
9805       /* update candidates for continuous -> implint and integer -> implint conversion */
9806       if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9807       {
9808          ncontvars++;
9809          contvarpos = v;
9810       }
9811       else if( slacktype == SCIP_VARTYPE_IMPLINT )
9812       {
9813          ++nimplvars;
9814       }
9815       else if( slacktype == SCIP_VARTYPE_INTEGER )
9816       {
9817          nintvars++;
9818          intvarpos = v;
9819       }
9820 
9821       /* check, if variable is already fixed or aggregated */
9822       if( !SCIPvarIsActive(var) )
9823          continue;
9824 
9825       /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9826       nlocks = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) + SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
9827 
9828       if( nlocks > maxnlocksremove )
9829          continue;
9830 
9831       /* check, if variable can be used as a slack variable */
9832       if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9833          !SCIPdoNotMultaggrVar(scip, var) )
9834       {
9835          SCIP_Bool better;
9836          SCIP_Bool equal;
9837          SCIP_Real slackdomrng;
9838 
9839          if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9840             slackdomrng = SCIPinfinity(scip);
9841          /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9842          else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9843             return SCIP_OKAY;
9844          else
9845          {
9846             slackdomrng = (varub - varlb)*absval;
9847             assert(!SCIPisInfinity(scip, slackdomrng));
9848          }
9849          equal = FALSE;
9850          better = (slacktype > bestslacktype) || (bestslackpos == -1);
9851          if( !better && slacktype == bestslacktype )
9852          {
9853             better = (nlocks < bestnlocks);
9854             if( nlocks == bestnlocks && !bestremovescons )
9855             {
9856                better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9857                equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9858             }
9859          }
9860 
9861          if( better || equal )
9862          {
9863             SCIP_Real minresactivity;
9864             SCIP_Real maxresactivity;
9865             SCIP_Real newlhs;
9866             SCIP_Real newrhs;
9867             SCIP_Bool removescons;
9868             SCIP_Bool minisrelax;
9869             SCIP_Bool maxisrelax;
9870             SCIP_Bool isminsettoinfinity;
9871             SCIP_Bool ismaxsettoinfinity;
9872 
9873             /* check if the constraint becomes redundant after multi-aggregation */
9874             consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9875                &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9876 
9877             /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9878              * activity
9879              */
9880             if( minisrelax || maxisrelax )
9881                continue;
9882 
9883             getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9884             removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9885 
9886             /* check resactivities for reliability */
9887             if( removescons )
9888             {
9889                if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9890                   consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9891 
9892                if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9893                   && SCIPisFeasLE(scip, newlhs, minresactivity))
9894                   consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9895 
9896                removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9897             }
9898 
9899             /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9900             if( conshdlrdata->multaggrremove && !removescons )
9901                continue;
9902 
9903             /* prefer variables that make the constraints redundant */
9904             if( bestremovescons && !removescons )
9905                continue;
9906 
9907             /* if the constraint does not become redundant, only accept the variable if it does not appear in
9908              * other constraints
9909              */
9910             if( !removescons && nlocks > maxnlocksstay )
9911                continue;
9912 
9913             better = better || (!bestremovescons && removescons);
9914             if( better )
9915             {
9916                bestslackpos = v;
9917                bestslacktype = slacktype;
9918                bestnlocks = nlocks;
9919                bestslackdomrng = slackdomrng;
9920                bestremovescons = removescons;
9921             }
9922          }
9923       }
9924    }
9925 
9926    /* if all coefficients and variables are integral, the right hand side must also be integral */
9927    if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9928    {
9929       SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9930       SCIPdebugPrintCons(scip, cons, NULL);
9931       *cutoff = TRUE;
9932       return SCIP_OKAY;
9933    }
9934 
9935    supinf = 0;
9936    infinf = 0;
9937    samevar = FALSE;
9938 
9939    /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9940    for( v = 0; v < consdata->nvars; ++v )
9941    {
9942       if( v != bestslackpos )
9943       {
9944          if( SCIPisPositive(scip, consdata->vals[v]) )
9945          {
9946             if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9947             {
9948                ++supinf;
9949                if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9950                {
9951                   ++infinf;
9952                   samevar = TRUE;
9953                }
9954             }
9955             else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9956                ++infinf;
9957          }
9958          else if( SCIPisNegative(scip, consdata->vals[v]) )
9959          {
9960             if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9961             {
9962                ++supinf;
9963                if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9964                {
9965                   ++infinf;
9966                   samevar = TRUE;
9967                }
9968             }
9969             else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9970                ++infinf;
9971          }
9972       }
9973    }
9974    assert(!samevar || (supinf > 0 && infinf > 0));
9975 
9976    /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9977     * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9978    if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9979    {
9980       SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9981       return SCIP_OKAY;
9982    }
9983 
9984    /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9985     * we cannot aggregate the variable, because the integrality condition would get lost
9986     * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9987     * loose the integrality condition for this variable.
9988     */
9989    if( bestslackpos >= 0
9990       && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9991          || (coefsintegral && varsintegral && nimplvars == 0)) )
9992    {
9993       SCIP_VAR* slackvar;
9994       SCIP_Real* scalars;
9995       SCIP_Real slackcoef;
9996       SCIP_Real aggrconst;
9997       SCIP_Real newlhs;
9998       SCIP_Real newrhs;
9999       SCIP_Bool aggregated;
10000 
10001       /* we found a slack variable that only occurs in at most one other constraint:
10002        *   a_1*x_1 + ... + a_k*x_k + a'*s == rhs  ->  s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
10003        */
10004       assert(bestslackpos < consdata->nvars);
10005 
10006       /* do not multi aggregate binary variables */
10007       if( SCIPvarIsBinary(vars[bestslackpos]) )
10008          return SCIP_OKAY;
10009 
10010       /* convert equality into inequality by deleting the slack variable:
10011        *  x + a*s == b, l <= s <= u   ->  b - a*u <= x <= b - a*l
10012        */
10013       slackvar = vars[bestslackpos];
10014       slackcoef = vals[bestslackpos];
10015       assert(!SCIPisZero(scip, slackcoef));
10016       aggrconst = consdata->rhs/slackcoef;
10017 
10018       getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
10019       assert(SCIPisLE(scip, newlhs, newrhs));
10020       SCIP_CALL( chgLhs(scip, cons, newlhs) );
10021       SCIP_CALL( chgRhs(scip, cons, newrhs) );
10022       SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
10023 
10024       /* allocate temporary memory */
10025       SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
10026 
10027       /* set up the multi-aggregation */
10028       SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
10029       for( v = 0; v < consdata->nvars; ++v )
10030       {
10031          scalars[v] = -consdata->vals[v]/slackcoef;
10032          SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
10033       }
10034       SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
10035          aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
10036          bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
10037 
10038       /* perform the multi-aggregation */
10039       SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
10040             &infeasible, &aggregated) );
10041       assert(aggregated);
10042 
10043       /* free temporary memory */
10044       SCIPfreeBufferArray(scip, &scalars);
10045 
10046       /* check for infeasible aggregation */
10047       if( infeasible )
10048       {
10049          SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10050          *cutoff = TRUE;
10051          return SCIP_OKAY;
10052       }
10053 
10054       (*naggrvars)++;
10055 
10056       /* delete the constraint if it became redundant */
10057       if( bestremovescons )
10058       {
10059          SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
10060          SCIP_CALL( SCIPdelCons(scip, cons) );
10061 
10062          if( !consdata->upgraded )
10063             (*ndelconss)++;
10064       }
10065    }
10066    else if( ncontvars == 1 )
10067    {
10068       SCIP_VAR* var;
10069 
10070       assert(0 <= contvarpos && contvarpos < consdata->nvars);
10071       var = vars[contvarpos];
10072       assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
10073 
10074       if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
10075       {
10076          /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
10077          if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
10078          {
10079             /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10080             SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
10081                SCIPconsGetName(cons), SCIPvarGetName(var));
10082             SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10083             if( infeasible )
10084             {
10085                SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10086                *cutoff = TRUE;
10087 
10088                return SCIP_OKAY;
10089             }
10090          }
10091          /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
10092          /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
10093          else if( !SCIPdoNotAggr(scip) )
10094          {
10095             SCIP_VAR* newvar;
10096             SCIP_Real absval;
10097             char newvarname[SCIP_MAXSTRLEN];
10098             SCIP_Bool redundant;
10099             SCIP_Bool aggregated;
10100 
10101             absval = REALABS(vals[contvarpos]);
10102 
10103             (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
10104 
10105             /* create new implicit variable for aggregation */
10106             SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
10107                   SCIP_VARTYPE_IMPLINT, SCIPvarIsInitial(var), SCIPvarIsRemovable(var), NULL, NULL, NULL, NULL, NULL) );
10108 
10109             /* add new variable to problem */
10110             SCIP_CALL( SCIPaddVar(scip, newvar) );
10111 
10112 #ifdef WITH_DEBUG_SOLUTION
10113             if( SCIPdebugIsMainscip(scip) )
10114             {
10115                SCIP_Real varval;
10116                SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
10117                SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
10118             }
10119 #endif
10120 
10121             /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
10122             SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
10123                SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
10124 
10125             /* aggregate continuous and implicit variable */
10126             SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
10127 
10128             if( infeasible )
10129             {
10130                SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
10131                   SCIPvarGetName(var), SCIPvarGetName(newvar));
10132                *cutoff = TRUE;
10133 
10134                /* release implicit variable */
10135                SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10136 
10137                return SCIP_OKAY;
10138             }
10139 
10140             /* release implicit variable */
10141             SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
10142 
10143             if( aggregated )
10144                (*naggrvars)++;
10145             else
10146                return SCIP_OKAY;
10147          }
10148 
10149          /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
10150           * again
10151           */
10152          consdata->boundstightened = 0;
10153          consdata->rangedrowpropagated = 0;
10154          consdata->presolved = FALSE;
10155       }
10156    }
10157    else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
10158    {
10159       SCIP_VAR* var;
10160 
10161       /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
10162        *  -> we don't convert integers into implints if the row is a 0/1-row
10163        */
10164       assert(varsintegral);
10165       assert(0 <= intvarpos && intvarpos < consdata->nvars);
10166       var = vars[intvarpos];
10167       assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10168 
10169       if( coefsintegral
10170          && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
10171          && SCIPisFeasIntegral(scip, consdata->rhs) )
10172       {
10173          /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
10174          SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
10175             SCIPconsGetName(cons), SCIPvarGetName(var));
10176          SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
10177          if( infeasible )
10178          {
10179             SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
10180             *cutoff = TRUE;
10181 
10182             return SCIP_OKAY;
10183          }
10184       }
10185    }
10186 
10187    return SCIP_OKAY;
10188 }
10189 
10190 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
10191 static
checkEqualObjective(SCIP * scip,SCIP_CONSDATA * consdata,SCIP_Real * scale,SCIP_Real * offset)10192 SCIP_Bool checkEqualObjective(
10193    SCIP*                 scip,               /**< SCIP data structure */
10194    SCIP_CONSDATA*        consdata,           /**< linear constraint data */
10195    SCIP_Real*            scale,              /**< pointer to store the scaling factor between the constraint and the
10196 					      *   objective function */
10197    SCIP_Real*            offset              /**< pointer to store the offset of the objective function resulting by
10198 					      *   this constraint */
10199    )
10200 {
10201    SCIP_VAR** vars;
10202    SCIP_VAR* var;
10203    SCIP_Real objval;
10204    SCIP_Bool negated;
10205    int nvars;
10206    int v;
10207 
10208    vars = consdata->vars;
10209    nvars = consdata->nvars;
10210 
10211    assert(vars != NULL);
10212 
10213    for( v = 0; v < nvars; ++v )
10214    {
10215       negated = FALSE;
10216       var = vars[v];
10217       assert(var != NULL);
10218 
10219       if( SCIPvarIsNegated(var) )
10220       {
10221          negated = TRUE;
10222          var = SCIPvarGetNegatedVar(var);
10223          assert(var != NULL);
10224       }
10225 
10226       objval = SCIPvarGetObj(var);
10227 
10228       /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
10229        * function
10230        */
10231       if( SCIPisZero(scip, objval) )
10232          return FALSE;
10233       else
10234       {
10235          SCIP_Real val;
10236 
10237          val = consdata->vals[v];
10238 
10239          if( negated )
10240          {
10241             if( v == 0 )
10242             {
10243                /* the first variable defines the scale */
10244                (*scale) = val / -objval;
10245 
10246                (*offset) += val;
10247             }
10248             else if( SCIPisEQ(scip, -objval * (*scale), val) )
10249                (*offset) += val;
10250             else
10251                return FALSE;
10252          }
10253          else if( v == 0 )
10254          {
10255             /* the first variable defines the scale */
10256             (*scale) = val / objval;
10257          }
10258          else if( !SCIPisEQ(scip, objval * (*scale), val) )
10259             return FALSE;
10260       }
10261    }
10262 
10263    return TRUE;
10264 }
10265 
10266 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
10267  *  objective coefficients and add an objective offset
10268  */
10269 static
checkPartialObjective(SCIP * scip,SCIP_CONS * cons,SCIP_CONSHDLRDATA * conshdlrdata)10270 SCIP_RETCODE checkPartialObjective(
10271    SCIP*                 scip,               /**< SCIP data structure */
10272    SCIP_CONS*            cons,               /**< linear equation constraint */
10273    SCIP_CONSHDLRDATA*    conshdlrdata        /**< linear constraint handler data */
10274    )
10275 {
10276    SCIP_CONSDATA* consdata;
10277    SCIP_Real offset;
10278    SCIP_Real scale;
10279    SCIP_Bool applicable;
10280    int nobjvars;
10281    int nvars;
10282    int v;
10283 
10284    assert(scip != NULL);
10285    assert(cons != NULL);
10286    assert(conshdlrdata != NULL);
10287 
10288    consdata = SCIPconsGetData(cons);
10289    assert(consdata != NULL);
10290    assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
10291 
10292    nvars = consdata->nvars;
10293    nobjvars = SCIPgetNObjVars(scip);
10294 
10295    /* check if the linear equality constraints does not have more variables than the objective function */
10296    if( nvars > nobjvars || nvars == 0 )
10297       return SCIP_OKAY;
10298 
10299    /* check for allowance of algorithm */
10300    if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
10301       (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
10302       return SCIP_OKAY;
10303 
10304    offset = consdata->rhs;
10305    scale = 1.0;
10306 
10307    /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10308    applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10309 
10310    if( applicable )
10311    {
10312       SCIP_VAR** vars;
10313 
10314       vars = consdata->vars;
10315       assert(vars != NULL);
10316 
10317       offset /= scale;
10318 
10319       SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10320          SCIPconsGetName(cons), consdata->rhs, offset);
10321 
10322       /* set all objective coefficient to zero */
10323       for( v = 0; v < nvars; ++v )
10324       {
10325          SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10326       }
10327 
10328       /* add an objective offset */
10329       SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10330    }
10331 
10332    return SCIP_OKAY;
10333 }
10334 
10335 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10336 static
updateCutoffbound(SCIP * scip,SCIP_CONS * cons,SCIP_Real primalbound)10337 SCIP_RETCODE updateCutoffbound(
10338    SCIP*                 scip,               /**< SCIP data structure */
10339    SCIP_CONS*            cons,               /**< constraint */
10340    SCIP_Real             primalbound         /**< feasible primal bound */
10341    )
10342 {
10343    SCIP_Real cutoffbound;
10344 
10345    /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10346     * accepted
10347     */
10348    cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10349 
10350    if( cutoffbound < SCIPgetCutoffbound(scip) )
10351    {
10352       SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10353 
10354       SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10355    }
10356    else
10357    {
10358       SCIP_CONSDATA* consdata;
10359 
10360       consdata = SCIPconsGetData(cons);
10361       assert(consdata != NULL);
10362 
10363       /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10364        * resulted from one side
10365        */
10366       if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10367       {
10368          /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10369           * propagation
10370           */
10371          SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
10372          SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
10373       }
10374    }
10375 
10376    return SCIP_OKAY;
10377 }
10378 
10379 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10380  *  constraint enters the LP by setting the initial and separated flag to FALSE
10381  */
10382 static
checkParallelObjective(SCIP * scip,SCIP_CONS * cons,SCIP_CONSHDLRDATA * conshdlrdata)10383 SCIP_RETCODE checkParallelObjective(
10384    SCIP*                 scip,               /**< SCIP data structure */
10385    SCIP_CONS*            cons,               /**< linear constraint */
10386    SCIP_CONSHDLRDATA*    conshdlrdata        /**< linear constraint handler data */
10387    )
10388 {
10389    SCIP_CONSDATA* consdata;
10390    SCIP_Real offset;
10391    SCIP_Real scale;
10392    SCIP_Bool applicable;
10393    int nobjvars;
10394    int nvars;
10395 
10396    assert(scip != NULL);
10397    assert(cons != NULL);
10398    assert(conshdlrdata != NULL);
10399 
10400    consdata = SCIPconsGetData(cons);
10401    assert(consdata != NULL);
10402 
10403    /* ignore equalities since these are covered by the method checkPartialObjective() */
10404    if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10405       return SCIP_OKAY;
10406 
10407    nvars = consdata->nvars;
10408    nobjvars = SCIPgetNObjVars(scip);
10409 
10410    /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10411     * initial and/or separated flag is set to FALSE
10412     */
10413    if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10414       return SCIP_OKAY;
10415 
10416    offset = 0.0;
10417    scale = 1.0;
10418 
10419    /* There are no variables in the ojective function and in the constraint. Thus, the constraint is redundant or proves
10420     * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10421     */
10422    if( nobjvars == 0 )
10423       return SCIP_OKAY;
10424 
10425    /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10426    applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10427 
10428    if( applicable )
10429    {
10430       SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10431       SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10432 
10433       if( SCIPisPositive(scip, scale) )
10434       {
10435          if( conshdlrdata->detectcutoffbound && rhsfinite )
10436          {
10437             SCIP_Real primalbound;
10438 
10439             primalbound = (consdata->rhs - offset) / scale;
10440 
10441             SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10442                SCIPconsGetName(cons), primalbound);
10443 
10444             SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10445          }
10446 
10447          if( conshdlrdata->detectlowerbound && lhsfinite )
10448          {
10449             SCIP_Real lowerbound;
10450 
10451             lowerbound = (consdata->lhs - offset) / scale;
10452 
10453             SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10454                SCIPconsGetName(cons), lowerbound);
10455 
10456             SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10457          }
10458 
10459          if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10460             (conshdlrdata->detectlowerbound && !rhsfinite) )
10461          {
10462             /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10463             SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10464             SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10465          }
10466       }
10467       else
10468       {
10469          if( conshdlrdata->detectlowerbound && rhsfinite )
10470          {
10471             SCIP_Real lowerbound;
10472 
10473             lowerbound = (consdata->rhs - offset) / scale;
10474 
10475             SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10476                SCIPconsGetName(cons), lowerbound);
10477 
10478             SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10479          }
10480 
10481          if( conshdlrdata->detectcutoffbound && lhsfinite )
10482          {
10483             SCIP_Real primalbound;
10484 
10485             primalbound = (consdata->lhs - offset) / scale;
10486 
10487             SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10488                SCIPconsGetName(cons), primalbound);
10489 
10490             SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10491          }
10492 
10493          if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10494             (conshdlrdata->detectlowerbound && !lhsfinite) )
10495          {
10496             /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10497             SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10498             SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10499          }
10500       }
10501    }
10502 
10503    return SCIP_OKAY;
10504 }
10505 
10506 /** converts special equalities */
10507 static
convertEquality(SCIP * scip,SCIP_CONS * cons,SCIP_CONSHDLRDATA * conshdlrdata,SCIP_Bool * cutoff,int * nfixedvars,int * naggrvars,int * ndelconss)10508 SCIP_RETCODE convertEquality(
10509    SCIP*                 scip,               /**< SCIP data structure */
10510    SCIP_CONS*            cons,               /**< linear constraint */
10511    SCIP_CONSHDLRDATA*    conshdlrdata,       /**< linear constraint handler data */
10512    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
10513    int*                  nfixedvars,         /**< pointer to count number of fixed variables */
10514    int*                  naggrvars,          /**< pointer to count number of aggregated variables */
10515    int*                  ndelconss           /**< pointer to count number of deleted constraints */
10516    )
10517 {
10518    SCIP_CONSDATA* consdata;
10519 
10520    assert(scip != NULL);
10521    assert(cons != NULL);
10522    assert(conshdlrdata != NULL);
10523    assert(cutoff != NULL);
10524    assert(nfixedvars != NULL);
10525    assert(naggrvars != NULL);
10526    assert(ndelconss != NULL);
10527 
10528    consdata = SCIPconsGetData(cons);
10529    assert(consdata != NULL);
10530    assert(consdata->removedfixings);
10531 
10532    /* do nothing on inequalities */
10533    if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10534       return SCIP_OKAY;
10535 
10536    /* depending on the number of variables, call a special conversion method */
10537    if( consdata->nvars == 1 )
10538    {
10539       /* fix variable */
10540       SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10541    }
10542    else if( consdata->nvars == 2 )
10543    {
10544       /* aggregate one of the variables */
10545       SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10546    }
10547    else
10548    {
10549       /* check if the equality is part of the objective function */
10550       SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10551 
10552       /* try to multi-aggregate one of the variables */
10553       SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10554    }
10555 
10556    return SCIP_OKAY;
10557 }
10558 
10559 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10560  *  integral
10561  */
10562 static
consdataIsResidualIntegral(SCIP * scip,SCIP_CONSDATA * consdata,int pos,SCIP_Real val)10563 SCIP_Bool consdataIsResidualIntegral(
10564    SCIP*                 scip,               /**< SCIP data structure */
10565    SCIP_CONSDATA*        consdata,           /**< linear constraint */
10566    int                   pos,                /**< position of variable to be left out */
10567    SCIP_Real             val                 /**< value to divide the coefficients by */
10568    )
10569 {
10570    int v;
10571 
10572    assert(scip != NULL);
10573    assert(consdata != NULL);
10574    assert(0 <= pos && pos < consdata->nvars);
10575 
10576    for( v = 0; v < consdata->nvars; ++v )
10577    {
10578       if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10579          return FALSE;
10580    }
10581 
10582    return TRUE;
10583 }
10584 
10585 /** check if \f$lhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$,
10586  *  check if \f$rhs/a_i - \sum_{j \neq i} a_j/a_i x_j\f$ is always inside the bounds of \f$x_i\f$
10587  */
10588 static
calculateMinvalAndMaxval(SCIP * scip,SCIP_Real side,SCIP_Real val,SCIP_Real minresactivity,SCIP_Real maxresactivity,SCIP_Real * minval,SCIP_Real * maxval)10589 void calculateMinvalAndMaxval(
10590    SCIP*                 scip,               /**< SCIP data structure */
10591    SCIP_Real             side,               /**< lhs or rhs */
10592    SCIP_Real             val,                /**< coefficient */
10593    SCIP_Real             minresactivity,     /**< minimal residual activity */
10594    SCIP_Real             maxresactivity,     /**< maximal residual activity */
10595    SCIP_Real*            minval,             /**< pointer to store calculated minval */
10596    SCIP_Real*            maxval              /**< pointer to store calculated maxval */
10597    )
10598 {
10599    assert(scip != NULL);
10600    assert(minval != NULL);
10601    assert(maxval != NULL);
10602 
10603    if( val > 0.0 )
10604    {
10605       if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10606          *minval = -maxresactivity;
10607       else
10608          *minval = (side - maxresactivity)/val;
10609 
10610       if( SCIPisInfinity(scip, ABS(minresactivity)) )
10611          *maxval = -minresactivity;
10612       else
10613          *maxval = (side - minresactivity)/val;
10614    }
10615    else
10616    {
10617       if( SCIPisInfinity(scip, ABS(minresactivity)) )
10618          *minval = minresactivity;
10619       else
10620          *minval = (side - minresactivity)/val;
10621 
10622       if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10623          *maxval = maxresactivity;
10624       else
10625          *maxval = (side - maxresactivity)/val;
10626    }
10627 }
10628 
10629 
10630 /** applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10631  *  linear inequality
10632  */
10633 static
dualPresolve(SCIP * scip,SCIP_CONSHDLRDATA * conshdlrdata,SCIP_CONS * cons,SCIP_Bool * cutoff,int * nfixedvars,int * naggrvars,int * ndelconss)10634 SCIP_RETCODE dualPresolve(
10635    SCIP*                 scip,               /**< SCIP data structure */
10636    SCIP_CONSHDLRDATA*    conshdlrdata,       /**< linear constraint handler data */
10637    SCIP_CONS*            cons,               /**< linear constraint */
10638    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
10639    int*                  nfixedvars,         /**< pointer to count number of fixed variables */
10640    int*                  naggrvars,          /**< pointer to count number of aggregated variables */
10641    int*                  ndelconss           /**< pointer to count number of deleted constraints */
10642    )
10643 {
10644    SCIP_CONSDATA* consdata;
10645    SCIP_Bool lhsexists;
10646    SCIP_Bool rhsexists;
10647    SCIP_Bool bestisint;
10648    SCIP_Bool bestislhs;
10649    SCIP_Real minabsval;
10650    SCIP_Real maxabsval;
10651    int bestpos;
10652    int i;
10653    int maxotherlocks;
10654 
10655    assert(scip != NULL);
10656    assert(cons != NULL);
10657    assert(cutoff != NULL);
10658    assert(nfixedvars != NULL);
10659    assert(naggrvars != NULL);
10660    assert(ndelconss != NULL);
10661 
10662    /* only process checked constraints (for which the locks are increased);
10663     * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10664     * dualfix presolver
10665     */
10666    if( !SCIPconsIsChecked(cons) )
10667       return SCIP_OKAY;
10668 
10669    consdata = SCIPconsGetData(cons);
10670    assert(consdata != NULL);
10671 
10672    lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10673    rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10674 
10675    /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10676     * can use it safely for aggregation and break the search loop
10677     */
10678    bestpos = -1;
10679    bestisint = TRUE;
10680    bestislhs = FALSE;
10681 
10682    /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10683     * everything else would produce fill-in. Exceptions:
10684     * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10685     *   produced.
10686     * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10687     *   six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10688     *   six nonzeros (two variables per substitution).
10689     * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10690     *   six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10691     *   six nonzeros (three variables per substitution). God exists!
10692     */
10693    if( consdata->nvars <= 2 )
10694       maxotherlocks = INT_MAX;
10695    else if( consdata->nvars == 3 )
10696       maxotherlocks = 3;
10697    else if( consdata->nvars == 4 )
10698       maxotherlocks = 2;
10699    else
10700       maxotherlocks = 1;
10701 
10702    /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10703    if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10704       maxotherlocks++;
10705 
10706    minabsval = SCIPinfinity(scip);
10707    maxabsval = -1.0;
10708    for( i = 0; i < consdata->nvars && bestisint; ++i )
10709    {
10710       SCIP_VAR* var;
10711       SCIP_Bool isint;
10712       SCIP_Real val;
10713       SCIP_Real absval;
10714       SCIP_Real obj;
10715       SCIP_Real lb;
10716       SCIP_Real ub;
10717       SCIP_Bool agglhs;
10718       SCIP_Bool aggrhs;
10719 
10720       val = consdata->vals[i];
10721       absval = REALABS(val);
10722 
10723       /* calculate minimal and maximal absolute value */
10724       if( absval < minabsval )
10725          minabsval = absval;
10726       if( absval > maxabsval )
10727          maxabsval = absval;
10728 
10729       /* do not try to multi aggregate, when numerical bad */
10730       if( maxabsval / minabsval > conshdlrdata->maxdualmultaggrquot )
10731          return SCIP_OKAY;
10732 
10733       var = consdata->vars[i];
10734       isint = (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY || SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
10735 
10736       /* if we already found a candidate, skip integers */
10737       if( bestpos >= 0 && isint )
10738          continue;
10739 
10740       /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10741        * active, fixed, or single-aggregated with another binary variable
10742        */
10743       if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10744          continue;
10745 
10746       if ( SCIPdoNotMultaggrVar(scip, var) )
10747          continue;
10748 
10749       val = consdata->vals[i];
10750       obj = SCIPvarGetObj(var);
10751       lb = SCIPvarGetLbGlobal(var);
10752       ub = SCIPvarGetUbGlobal(var);
10753 
10754       /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10755        *
10756        * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10757        *  - constraint is the only one that forbids fixing the variable to its lower bound
10758        *  - fix x_i to the smallest value for this constraint: x_i := lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
10759        *
10760        * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10761        *  - constraint is the only one that forbids fixing the variable to its upper bound
10762        *  - fix x_i to the largest value for this constraint: x_i := lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
10763        *
10764        * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10765        *  - constraint is the only one that forbids fixing the variable to its upper bound
10766        *  - fix x_i to the largest value for this constraint: x_i := rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
10767        *
10768        * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10769        *  - constraint is the only one that forbids fixing the variable to its lower bound
10770        *  - fix x_i to the smallest value for this constraint: x_i := rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j
10771        *
10772        * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10773        *      of all x_j
10774        * furthermore: we only want to apply this, if no fill-in will be produced
10775        */
10776       agglhs = lhsexists
10777          && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10778                && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10779             || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10780                && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10781       aggrhs = rhsexists
10782          && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 1
10783                && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks)
10784             || (val < 0.0 && !SCIPisNegative(scip, obj)  && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 1
10785                && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= maxotherlocks));
10786       if( agglhs || aggrhs )
10787       {
10788          SCIP_Real minresactivity;
10789          SCIP_Real maxresactivity;
10790          SCIP_Real minval;
10791          SCIP_Real maxval;
10792          SCIP_Bool minisrelax;
10793          SCIP_Bool maxisrelax;
10794          SCIP_Bool isminsettoinfinity;
10795          SCIP_Bool ismaxsettoinfinity;
10796 
10797          /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10798          consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10799             &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
10800          assert(SCIPisLE(scip, minresactivity, maxresactivity));
10801 
10802          /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10803           * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10804           * This is needed, because we do not want to rely on relaxed finite resactivities.
10805           */
10806          assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
10807 
10808          if( agglhs )
10809          {
10810             /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10811             calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10812 
10813             assert(SCIPisLE(scip, minval, maxval));
10814             if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10815                (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10816             {
10817                SCIP_Real oldmaxresactivity;
10818                SCIP_Real oldminresactivity;
10819                SCIP_Bool recalculated;
10820 
10821                recalculated = FALSE;
10822                oldmaxresactivity = maxresactivity;
10823                oldminresactivity = minresactivity;
10824 
10825                /* check minresactivity for reliability */
10826                if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10827                {
10828                   consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10829                   recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10830                   isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10831                }
10832 
10833                /* check maxresactivity for reliability */
10834                if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10835                {
10836                   consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10837                   recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10838                   ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10839                }
10840 
10841                /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10842                if( recalculated )
10843                {
10844                   assert(SCIPisLE(scip, minresactivity, maxresactivity));
10845 
10846                   /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10847                   calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10848 
10849                   assert(SCIPisLE(scip, minval, maxval));
10850                }
10851 
10852                if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10853                {
10854                   /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10855                    * in the multi-aggregation
10856                    */
10857                   if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10858                   {
10859                      bestpos = i;
10860                      bestisint = isint;
10861                      bestislhs = TRUE;
10862                      continue; /* no need to also look at the right hand side */
10863                   }
10864                }
10865             }
10866          }
10867 
10868          if( aggrhs )
10869          {
10870             /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10871             calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10872 
10873             assert(SCIPisLE(scip,minval,maxval));
10874             if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10875                (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10876             {
10877                SCIP_Real oldmaxresactivity;
10878                SCIP_Real oldminresactivity;
10879                SCIP_Bool recalculated;
10880 
10881                recalculated = FALSE;
10882                oldmaxresactivity = maxresactivity;
10883                oldminresactivity = minresactivity;
10884 
10885                /* check minresactivity for reliability */
10886                if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10887                {
10888                   consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10889                   recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10890                }
10891 
10892                /* check maxresactivity for reliability */
10893                if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10894                {
10895                   consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10896                   recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10897                }
10898 
10899                /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10900                if( recalculated )
10901                {
10902                   /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10903                   calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10904                   assert(SCIPisLE(scip,minval,maxval));
10905                }
10906 
10907                if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10908                {
10909                   /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10910                    * in the multi-aggregation
10911                    */
10912                   if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10913                   {
10914                      bestpos = i;
10915                      bestisint = isint;
10916                      bestislhs = FALSE;
10917                   }
10918                }
10919             }
10920          }
10921       }
10922    }
10923 
10924    if( bestpos >= 0 )
10925    {
10926       SCIP_VAR** aggrvars;
10927       SCIP_Real* aggrcoefs;
10928       SCIP_Real aggrconst;
10929       SCIP_VAR* bestvar;
10930       SCIP_Real bestval;
10931       SCIP_Real epsilon;
10932       int naggrs;
10933       int j;
10934       SCIP_Bool infeasible;
10935       SCIP_Bool aggregated;
10936       SCIP_Bool samevar;
10937       int supinf;                            /* counter for infinite contributions to the supremum of a possible
10938                                               * multi-aggregation
10939                                               */
10940       int infinf;                            /* counter for infinite contributions to the infimum of a possible
10941                                               * multi-aggregation
10942                                               */
10943 
10944       assert(!bestislhs || lhsexists);
10945       assert(bestislhs || rhsexists);
10946 
10947       bestvar = consdata->vars[bestpos];
10948       bestval = consdata->vals[bestpos];
10949       assert(bestisint ==
10950          (SCIPvarGetType(bestvar) == SCIP_VARTYPE_BINARY || SCIPvarGetType(bestvar) == SCIP_VARTYPE_INTEGER));
10951 
10952       /* allocate temporary memory */
10953       SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10954       SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10955 
10956       /* set up the multi-aggregation */
10957       SCIPdebugPrintCons(scip, cons, NULL);
10958       SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10959       naggrs = 0;
10960       supinf = 0;
10961       infinf = 0;
10962       samevar = FALSE;
10963       epsilon = SCIPepsilon(scip);
10964 
10965       for( j = 0; j < consdata->nvars; ++j )
10966       {
10967          if( j != bestpos )
10968          {
10969             SCIP_Real absaggrcoef;
10970 
10971             aggrvars[naggrs] = consdata->vars[j];
10972             aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10973             SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10974 
10975             absaggrcoef = REALABS(aggrcoefs[naggrs]);
10976 
10977             /* do not try to multi aggregate, when numerical bad */
10978             if( absaggrcoef < epsilon )
10979             {
10980                SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10981 
10982                /* free temporary memory */
10983                SCIPfreeBufferArray(scip, &aggrcoefs);
10984                SCIPfreeBufferArray(scip, &aggrvars);
10985 
10986                return SCIP_OKAY;
10987             }
10988 
10989             if( bestisint )
10990             {
10991                /* coefficient must be integral: round it to exact integral value */
10992                assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10993                aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10994             }
10995 
10996             if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10997             {
10998                if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10999                {
11000                   ++supinf;
11001                   if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11002                   {
11003                      ++infinf;
11004                      samevar = TRUE;
11005                   }
11006                }
11007                else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11008                   ++infinf;
11009             }
11010             else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
11011             {
11012                if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
11013                {
11014                   ++supinf;
11015                   if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11016                   {
11017                      ++infinf;
11018                      samevar = TRUE;
11019                   }
11020                }
11021                else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
11022                   ++infinf;
11023             }
11024 
11025             naggrs++;
11026          }
11027       }
11028       assert(!samevar || (supinf > 0 && infinf > 0));
11029 
11030       aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
11031       SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
11032          SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
11033       assert(naggrs == consdata->nvars-1);
11034 
11035       /* right hand side must be integral: round it to exact integral value */
11036       if( bestisint )
11037       {
11038          assert(SCIPisIntegral(scip, aggrconst));
11039          aggrconst = SCIPfloor(scip, aggrconst+0.5);
11040       }
11041 
11042       aggregated = FALSE;
11043       infeasible = FALSE;
11044 
11045       /* perform the multi-aggregation */
11046       if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
11047       {
11048          /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
11049           * also convertLongEquality() early termination due to coefficients
11050           */
11051          SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
11052       }
11053       else
11054       {
11055          /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
11056           * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
11057          SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
11058       }
11059       /* free temporary memory */
11060       SCIPfreeBufferArray(scip, &aggrcoefs);
11061       SCIPfreeBufferArray(scip, &aggrvars);
11062 
11063       /* check for infeasible aggregation */
11064       if( infeasible )
11065       {
11066          SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
11067          *cutoff = TRUE;
11068          return SCIP_OKAY;
11069       }
11070 
11071       /* delete the constraint, if the aggregation was successful */
11072       if( aggregated )
11073       {
11074          SCIP_CALL( SCIPdelCons(scip, cons) );
11075 
11076          if( !consdata->upgraded )
11077             (*ndelconss)++;
11078          (*naggrvars)++;
11079       }
11080       else
11081       {
11082          SCIPdebugMsg(scip, "aggregation non successful!\n");
11083       }
11084    }
11085 
11086    return SCIP_OKAY;
11087 }
11088 
11089 #define BINWEIGHT  1
11090 #define INTWEIGHT  4
11091 #define CONTWEIGHT 8
11092 
11093 /** gets weight for variable in a "weighted number of variables" sum */
11094 static
getVarWeight(SCIP_VAR * var)11095 int getVarWeight(
11096    SCIP_VAR*             var                 /**< variable to get weight for */
11097    )
11098 {
11099    switch( SCIPvarGetType(var) )
11100    {
11101    case SCIP_VARTYPE_BINARY:
11102       return BINWEIGHT;
11103    case SCIP_VARTYPE_INTEGER:
11104    case SCIP_VARTYPE_IMPLINT:
11105       return INTWEIGHT;
11106    case SCIP_VARTYPE_CONTINUOUS:
11107       return CONTWEIGHT;
11108    default:
11109       SCIPerrorMessage("invalid variable type\n");
11110       SCIPABORT();
11111       return 0; /*lint !e527*/
11112    }
11113 }
11114 
11115 /** tries to aggregate variables in equations a^Tx = lhs
11116  *  in case there are at most two binary variables with an odd coefficient and all other
11117  *  variables are not continuous and have an even coefficient then:
11118  *  - exactly one odd binary variables
11119  *    this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
11120  *     - lhs is odd ->  y = 1
11121  *     - lhs is even -> y = 0
11122  *  - exactly two odd binary variables
11123  *    aggregate the two binary variables with odd coefficient
11124  *     - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11125  *     - lhs is even -> both have to take the same value -> var1 - var2 = 0
11126  */
11127 static
aggregateVariables(SCIP * scip,SCIP_CONS * cons,SCIP_Bool * cutoff,int * nfixedvars,int * naggrvars)11128 SCIP_RETCODE aggregateVariables(
11129    SCIP*                 scip,               /**< SCIP data structure */
11130    SCIP_CONS*            cons,               /**< linear constraint */
11131    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
11132    int*                  nfixedvars,         /**< pointer to count number of fixed variables */
11133    int*                  naggrvars           /**< pointer to count number of aggregated variables */
11134    )
11135 {  /*lint --e{715}*/
11136    SCIP_CONSDATA* consdata;
11137    SCIP_Bool success;
11138 
11139    assert( scip != NULL );
11140    assert( cons != NULL );
11141 
11142    consdata = SCIPconsGetData(cons);
11143    assert( consdata != NULL );
11144 
11145    /* check if the linear constraint is an equation with integral right hand side */
11146    if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
11147       return SCIP_OKAY;
11148 
11149    /* try to fix and aggregated variables until nothing is possible anymore */
11150    do
11151    {
11152       int v;
11153       int nvars;
11154       SCIP_VAR** vars;
11155       SCIP_Real* vals;
11156       SCIP_Real lhs;
11157       SCIP_Bool lhsodd;
11158 
11159       SCIP_Bool infeasible;
11160       SCIP_Bool fixed;
11161       SCIP_Bool aggregated;
11162       SCIP_Bool redundant;
11163 
11164       SCIP_VAR* var1;
11165       SCIP_VAR* var2;
11166       int noddvars;
11167 
11168       success = FALSE;
11169 
11170       lhs = consdata->lhs;
11171       vars = consdata->vars;
11172       vals = consdata->vals;
11173       nvars = consdata->nvars;
11174 
11175       assert( !SCIPisInfinity(scip, ABS(lhs)) );
11176 
11177       var1 = NULL;
11178       var2 = NULL;
11179       noddvars = 0;
11180 
11181       /* search for binary variables with an odd coefficient */
11182       for( v = 0; v < nvars && noddvars < 3; ++v )
11183       {
11184          SCIP_Longint val;
11185 
11186          /* all coefficients and variables have to be integral */
11187          if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11188             return SCIP_OKAY;
11189 
11190          val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
11191          if( val % 2 != 0 )
11192          {
11193             /* the odd values have to belong to binary variables */
11194             if( !SCIPvarIsBinary(vars[v]) )
11195                return SCIP_OKAY;
11196 
11197             if( noddvars == 0 )
11198                var1 = vars[v];
11199             else
11200                var2 = vars[v];
11201 
11202             noddvars++;
11203          }
11204       }
11205 
11206       /* check lhs is odd or even */
11207       lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
11208 
11209       if( noddvars == 1 )
11210       {
11211          assert( var1 != NULL );
11212 
11213          SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
11214             SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
11215 
11216          SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
11217 
11218          /* check for infeasibility of fixing */
11219          if( infeasible )
11220          {
11221             SCIPdebugMsg(scip, " -> infeasible fixing\n");
11222             *cutoff = TRUE;
11223             return SCIP_OKAY;
11224          }
11225 
11226          if( fixed )
11227          {
11228             SCIPdebugMsg(scip, " -> feasible fixing\n");
11229             (*nfixedvars)++;
11230             success = TRUE;
11231          }
11232       }
11233       else if( noddvars == 2 )
11234       {
11235          assert( var1 != NULL );
11236          assert( var2 != NULL );
11237 
11238          /* aggregate the two variables with odd coefficient
11239           * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
11240           * - lhs is even -> both have to take the same value -> var1 - var2 = 0
11241           */
11242          SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
11243             SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
11244 
11245          SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
11246                lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
11247 
11248          /* check for infeasibility of aggregation */
11249          if( infeasible )
11250          {
11251             SCIPdebugMsg(scip, " -> infeasible aggregation\n");
11252             *cutoff = TRUE;
11253             return SCIP_OKAY;
11254          }
11255 
11256          /* count the aggregation */
11257          if( aggregated )
11258          {
11259             SCIPdebugMsg(scip, " -> feasible aggregation\n");
11260             (*naggrvars)++;
11261             success = TRUE;
11262          }
11263       }
11264 
11265       if( success )
11266       {
11267          /* apply fixings and aggregation to successfully rerun this presolving step */
11268          SCIP_CALL( applyFixings(scip, cons, &infeasible) );
11269 
11270          if( infeasible )
11271          {
11272             SCIPdebugMsg(scip, " -> infeasible fixing\n");
11273             *cutoff = TRUE;
11274             return SCIP_OKAY;
11275          }
11276 
11277          /* normalize constraint */
11278          SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
11279 
11280          if( infeasible )
11281          {
11282             SCIPdebugMsg(scip, " -> infeasible normalization\n");
11283             *cutoff = TRUE;
11284             return SCIP_OKAY;
11285          }
11286       }
11287    }
11288    while( success );
11289 
11290    return SCIP_OKAY;
11291 }
11292 
11293 
11294 
11295 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
11296  *  the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
11297  *  coefficients
11298  */
11299 static
SCIP_DECL_SORTINDCOMP(consdataCompSim)11300 SCIP_DECL_SORTINDCOMP(consdataCompSim)
11301 {  /*lint --e{715}*/
11302    SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
11303    SCIP_VARTYPE vartype1;
11304    SCIP_VARTYPE vartype2;
11305    SCIP_Real value;
11306 
11307    assert(consdata != NULL);
11308    assert(0 <= ind1 && ind1 < consdata->nvars);
11309    assert(0 <= ind2 && ind2 < consdata->nvars);
11310 
11311    vartype1 = SCIPvarGetType(consdata->vars[ind1]);
11312    vartype2 = SCIPvarGetType(consdata->vars[ind2]);
11313 
11314    if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
11315    {
11316       /* continuous varibles will be sorted to the back */
11317       if( vartype2 != vartype1 )
11318          return +1;
11319       /* both variables are continuous */
11320       else
11321          return 0;
11322    }
11323    /* continuous variables will be sorted to the back */
11324    else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
11325       return -1;
11326 
11327    value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
11328 
11329    /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
11330    return (value > 0 ? +1 : (value < 0 ? -1 : 0));
11331 }
11332 
11333 /** tries to simplify coefficients and delete variables in ranged row of the form lhs <= a^Tx <= rhs, e.g. using the greatest
11334  *  common divisor
11335  *
11336  *  1. lhs <= a^Tx <= rhs, forall a_i >= lhs, a_i <= rhs, and forall pairs a_i + a_j > rhs then we can change this
11337  *     constraint to 1^Tx = 1
11338  */
11339 static
rangedRowSimplify(SCIP * scip,SCIP_CONS * cons,int * nchgcoefs,int * nchgsides)11340 SCIP_RETCODE rangedRowSimplify(
11341    SCIP*                 scip,               /**< SCIP data structure */
11342    SCIP_CONS*            cons,               /**< linear constraint */
11343    int*                  nchgcoefs,          /**< pointer to store the amount of changed coefficients */
11344    int*                  nchgsides           /**< pointer to store the amount of changed sides */
11345    )
11346 {
11347    SCIP_CONSDATA* consdata;
11348    SCIP_VAR** vars;
11349    SCIP_Real* vals;
11350    SCIP_Real minval;
11351    SCIP_Real secondminval;
11352    SCIP_Real maxval;
11353    SCIP_Real lhs;
11354    SCIP_Real rhs;
11355    int nvars;
11356    int v;
11357 
11358    /* we must not change a modifiable constraint in any way */
11359    if( SCIPconsIsModifiable(cons) )
11360       return SCIP_OKAY;
11361 
11362    if( SCIPconsIsDeleted(cons) )
11363       return SCIP_OKAY;
11364 
11365    consdata = SCIPconsGetData(cons);
11366    assert(consdata != NULL);
11367 
11368    nvars = consdata->nvars;
11369 
11370    /* do not check empty or bound-constraints */
11371    if( nvars < 2 )
11372       return SCIP_OKAY;
11373 
11374    vals = consdata->vals;
11375    vars = consdata->vars;
11376    assert(vars != NULL);
11377    assert(vals != NULL);
11378 
11379    lhs = consdata->lhs;
11380    rhs = consdata->rhs;
11381    assert(!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs));
11382    assert(!SCIPisNegative(scip, rhs));
11383 
11384    minval = SCIP_INVALID;
11385    secondminval = SCIP_INVALID;
11386    maxval = -SCIP_INVALID;
11387 
11388    for( v = nvars - 1; v >= 0; --v )
11389    {
11390       if( SCIPvarIsBinary(vars[v]) )
11391       {
11392          if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11393          {
11394             secondminval = minval;
11395             minval = vals[v];
11396          }
11397          else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11398             secondminval = vals[v];
11399 
11400          if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11401             maxval = vals[v];
11402       }
11403       else
11404          break;
11405    }
11406 
11407    /* check if all variables are binary */
11408    if( v == -1 )
11409    {
11410       if( SCIPisEQ(scip, minval, maxval) && SCIPisEQ(scip, lhs, rhs) )
11411          return SCIP_OKAY;
11412 
11413       /* check if we can and need to choose exactly one binary variable */
11414       if( SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) && SCIPisGT(scip, minval + secondminval, rhs) )
11415       {
11416          /* change all coefficients to 1.0 */
11417          for( v = nvars - 1; v >= 0; --v )
11418          {
11419             SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11420          }
11421          (*nchgcoefs) += nvars;
11422 
11423          /* replace old right and left hand side with 1.0 */
11424          SCIP_CALL( chgRhs(scip, cons, 1.0) );
11425          SCIP_CALL( chgLhs(scip, cons, 1.0) );
11426          (*nchgsides) += 2;
11427       }
11428    }
11429 
11430    return SCIP_OKAY;
11431 }
11432 
11433 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11434  *  for equations @see rangedRowSimplify() will be called
11435  *
11436  *  there are several different coefficient reduction steps which will be applied
11437  *
11438  *  1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11439  *
11440  *     e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11441  *
11442  *  2. We try to remove redundant fractional parts in a constraint
11443  *
11444  *     e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3  => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11445  *
11446  *  3. We are using the greatest common divisor for further reductions
11447  *
11448  *     e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15  => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11449  *          integral
11450  */
11451 static
simplifyInequalities(SCIP * scip,SCIP_CONS * cons,int * nchgcoefs,int * nchgsides,SCIP_Bool * infeasible)11452 SCIP_RETCODE simplifyInequalities(
11453    SCIP*                 scip,               /**< SCIP data structure */
11454    SCIP_CONS*            cons,               /**< linear constraint */
11455    int*                  nchgcoefs,          /**< pointer to store the amount of changed coefficients */
11456    int*                  nchgsides,          /**< pointer to store the amount of changed sides */
11457    SCIP_Bool*            infeasible          /**< pointer to store whether infeasibility was detected */
11458    )
11459 {
11460    SCIP_CONSDATA* consdata;
11461    SCIP_VAR** vars;
11462    SCIP_Real* vals;
11463    int* perm;
11464    SCIP_Real minactsub;
11465    SCIP_Real maxactsub;
11466    SCIP_Real siderest;
11467    SCIP_Real feastol;
11468    SCIP_Real newcoef;
11469    SCIP_Real absval;
11470    SCIP_Real side;
11471    SCIP_Real lhs;
11472    SCIP_Real rhs;
11473    SCIP_Real lb;
11474    SCIP_Real ub;
11475    SCIP_Longint restcoef;
11476    SCIP_Longint oldgcd;
11477    SCIP_Longint rest;
11478    SCIP_Longint gcd;
11479    SCIP_Bool isminsettoinfinity;
11480    SCIP_Bool ismaxsettoinfinity;
11481    SCIP_Bool isminrelax;
11482    SCIP_Bool ismaxrelax;
11483    SCIP_Bool allcoefintegral;
11484    SCIP_Bool onlybin;
11485    SCIP_Bool hasrhs;
11486    SCIP_Bool haslhs;
11487    int oldnchgcoefs;
11488    int oldnchgsides;
11489    int foundbin;
11490    int candpos;
11491    int candpos2;
11492    int offsetv;
11493    int nvars;
11494    int v;
11495    int w;
11496 
11497    assert(scip != NULL);
11498    assert(cons != NULL);
11499    assert(nchgcoefs != NULL);
11500    assert(nchgsides != NULL);
11501 
11502    *infeasible = FALSE;
11503 
11504    /* we must not change a modifiable constraint in any way */
11505    if( SCIPconsIsModifiable(cons) )
11506       return SCIP_OKAY;
11507 
11508    if( SCIPconsIsDeleted(cons) )
11509       return SCIP_OKAY;
11510 
11511    consdata = SCIPconsGetData(cons);
11512    assert(consdata != NULL);
11513 
11514    nvars = consdata->nvars;
11515 
11516    /* do not check empty or bound-constraints */
11517    if( nvars <= 2 )
11518       return SCIP_OKAY;
11519 
11520    /* update maximal activity delta if necessary */
11521    if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11522       consdataRecomputeMaxActivityDelta(scip, consdata);
11523 
11524    assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11525    assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11526    checkMaxActivityDelta(scip, consdata);
11527 
11528    /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11529     *       accordingly
11530     */
11531    /* can only work with valid non-infinity activities per variable */
11532    if( SCIPisInfinity(scip, consdata->maxactdelta) )
11533       return SCIP_OKAY;
11534 
11535    /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11536     *        but the eventsystem seems to be full
11537     */
11538    consdata->normalized = FALSE;
11539 
11540    /* normalize constraint */
11541    SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11542    assert(nvars == consdata->nvars);
11543 
11544    if( *infeasible )
11545       return SCIP_OKAY;
11546 
11547    if( !consdata->normalized )
11548       return SCIP_OKAY;
11549 
11550    lhs = consdata->lhs;
11551    rhs = consdata->rhs;
11552    assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11553    assert(!SCIPisNegative(scip, rhs));
11554 
11555    if( !SCIPisInfinity(scip, -lhs) )
11556       haslhs = TRUE;
11557    else
11558       haslhs = FALSE;
11559 
11560    if( !SCIPisInfinity(scip, rhs) )
11561       hasrhs = TRUE;
11562    else
11563       hasrhs = FALSE;
11564 
11565    SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11566    SCIPdebug( oldnchgsides = *nchgsides; )
11567 
11568    /* @todo also work on ranged rows */
11569    if( haslhs && hasrhs )
11570    {
11571       SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11572 
11573       return SCIP_OKAY;
11574    }
11575    assert(haslhs != hasrhs);
11576 
11577    /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11578    assert(!hasrhs || !SCIPisNegative(scip, rhs));
11579    assert(!haslhs || !SCIPisNegative(scip, lhs));
11580 
11581    /* get temporary memory to store the sorted permutation */
11582    SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11583 
11584    /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11585     * value of their coefficients
11586     */
11587    SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11588 
11589    /* perform sorting after permutation array */
11590    permSortConsdata(consdata, perm, nvars);
11591    consdata->indexsorted = FALSE;
11592    consdata->coefsorted = FALSE;
11593 
11594    vars = consdata->vars;
11595    vals = consdata->vals;
11596    assert(vars != NULL);
11597    assert(vals != NULL);
11598    assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11599 
11600    /* free temporary memory */
11601    SCIPfreeBufferArray(scip, &perm);
11602 
11603    /* only check constraints with at least two non continuous variables */
11604    if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11605       return SCIP_OKAY;
11606 
11607    /* do not process constraints when all coefficients are 1.0 */
11608    if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11609       return SCIP_OKAY;
11610 
11611    feastol = SCIPfeastol(scip);
11612 
11613    SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11614    SCIPdebugPrintCons(scip, cons, NULL);
11615 
11616    /* get global activities */
11617    consdataGetGlbActivityBounds(scip, consdata, FALSE, &minactsub, &maxactsub,
11618       &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11619 
11620    /* cannot work with infinite activities */
11621    if( isminsettoinfinity || ismaxsettoinfinity )
11622       return SCIP_OKAY;
11623 
11624    assert(!isminrelax);
11625    assert(!ismaxrelax);
11626    assert(maxactsub > minactsub);
11627    assert(!SCIPisInfinity(scip, -minactsub));
11628    assert(!SCIPisInfinity(scip, maxactsub));
11629 
11630    v = 0;
11631    offsetv = -1;
11632    side = haslhs ? lhs : rhs;
11633 
11634    /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11635     * do not need to look at the large coefficients
11636     *
11637     * e.g.  all x are binary, z are positive integer
11638     *       c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5   (x5 is redundant and does not change (in-)feasibility of this constraint)
11639     *       c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4   (gcd (without the coefficient of x5) after the large coefficients is 3
11640     *       c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11641     *
11642     *       can be changed to
11643     *
11644     *       c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6        (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11645     *       c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6  (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11646     *       c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11647     */
11648 
11649    /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11650     * hand side, we cannot apply the extra reduction step and need to reset v
11651     *
11652     * e.g. 7x1 + 7x2 - 4x3 - 4x4 >= 7 => xi = 1 for all i is not a solution, but if we would do a change on the
11653     *      coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11654     *      for all i is a solution
11655     *
11656     * also redundancy of variables would not be correctly determined in such a case
11657     */
11658    if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11659    {
11660       v = 1;
11661 
11662       while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11663       {
11664          /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11665           * extra step, which might have worked
11666           */
11667          if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11668          {
11669             v = 0;
11670             break;
11671          }
11672 
11673          ++v;
11674       }
11675 
11676       /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11677       /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11678       if( v == nvars )
11679          return SCIP_OKAY;
11680 
11681       /* cannot work with continuous variables which have a big coefficient */
11682       if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11683          return SCIP_OKAY;
11684 
11685       /* big negative coefficient, do not try to use the extra coefficient reduction step */
11686       if( SCIPisEQ(scip, side, -vals[v]) )
11687          v = 0;
11688 
11689       /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11690        * reduction
11691        */
11692       if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11693          v = 0;
11694 
11695       if( v > 0 )
11696       {
11697          assert(v < nvars);
11698 
11699          offsetv = v - 1;
11700 
11701          for( w = 0; w < v; ++w )
11702          {
11703             lb = SCIPvarGetLbGlobal(vars[w]);
11704             ub = SCIPvarGetUbGlobal(vars[w]);
11705 
11706             assert(vals[w] > 0);
11707 
11708             /* update residual activities */
11709             maxactsub -= ub * vals[w];
11710             minactsub -= lb * vals[w];
11711             assert(maxactsub > minactsub);
11712          }
11713       }
11714    }
11715 
11716    /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11717     *
11718     * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11719     *
11720     *        15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11721     * to
11722     *        15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11723     */
11724    if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11725    {
11726       SCIP_Bool redundant = FALSE;
11727 
11728       gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11729       assert(gcd >= 1);
11730 
11731       if( v == 0 )
11732       {
11733          lb = SCIPvarGetLbGlobal(vars[0]);
11734          ub = SCIPvarGetUbGlobal(vars[0]);
11735 
11736          /* update residual activities */
11737          if( vals[0] > 0 )
11738          {
11739             maxactsub -= ub * vals[0];
11740             minactsub -= lb * vals[0];
11741          }
11742          else
11743          {
11744             maxactsub -= lb * vals[0];
11745             minactsub -= ub * vals[0];
11746          }
11747          assert(maxactsub > minactsub);
11748          ++v;
11749       }
11750 
11751       siderest = -SCIP_INVALID;
11752       allcoefintegral = TRUE;
11753 
11754       /* check if some variables always fit into the given constraint */
11755       for( ; v < nvars - 1; ++v )
11756       {
11757          if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11758             break;
11759 
11760          if( !SCIPisIntegral(scip, vals[v]) )
11761          {
11762             allcoefintegral = FALSE;
11763             break;
11764          }
11765 
11766          /* calculate greatest common divisor for all general and binary variables */
11767          gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11768 
11769          if( gcd == 1 )
11770             break;
11771 
11772          lb = SCIPvarGetLbGlobal(vars[v]);
11773          ub = SCIPvarGetUbGlobal(vars[v]);
11774 
11775          assert(!SCIPisInfinity(scip, -lb));
11776          assert(!SCIPisInfinity(scip, ub));
11777 
11778          /* update residual activities */
11779          if( vals[v] > 0 )
11780          {
11781             maxactsub -= ub * vals[v];
11782             minactsub -= lb * vals[v];
11783          }
11784          else
11785          {
11786             maxactsub -= lb * vals[v];
11787             minactsub -= ub * vals[v];
11788          }
11789          assert(SCIPisGE(scip, maxactsub, minactsub));
11790 
11791          if( hasrhs )
11792          {
11793             /* determine the remainder of the right hand side and the gcd */
11794             siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11795          }
11796          else
11797          {
11798             /* determine the remainder of the left hand side and the gcd */
11799             siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11800             if( SCIPisZero(scip, siderest) )
11801                siderest = gcd;
11802          }
11803 
11804          /* early termination if the activities deceed the gcd */
11805          if( (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) ||
11806                (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd) )
11807          {
11808             redundant = TRUE;
11809             break;
11810          }
11811       }
11812       assert(v < nvars || (offsetv >= 0 && gcd > 1));
11813 
11814       if( !redundant )
11815       {
11816          if( hasrhs )
11817          {
11818             /* determine the remainder of the right hand side and the gcd */
11819             siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11820          }
11821          else
11822          {
11823             /* determine the remainder of the left hand side and the gcd */
11824             siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11825             if( SCIPisZero(scip, siderest) )
11826                siderest = gcd;
11827          }
11828       }
11829       else
11830          ++v;
11831 
11832       SCIPdebugMsg(scip, "stopped at pos %d (of %d), subactivities [%g, %g], redundant = %u, hasrhs = %u, siderest = %g, gcd = %" SCIP_LONGINT_FORMAT ", offset position for 'side' coefficients = %d\n",
11833             v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11834 
11835       /* check if we can remove redundant variables */
11836       if( v < nvars && (redundant ||
11837                         (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) ||
11838                         (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd)) )
11839       {
11840          SCIP_Real oldcoef;
11841 
11842          /* double check the redundancy */
11843 #ifndef NDEBUG
11844          SCIP_Real tmpminactsub = 0.0;
11845          SCIP_Real tmpmaxactsub = 0.0;
11846 
11847          /* recompute residual activities */
11848          for( w = v; w < nvars; ++w )
11849          {
11850             lb = SCIPvarGetLbGlobal(vars[w]);
11851             ub = SCIPvarGetUbGlobal(vars[w]);
11852 
11853             assert(!SCIPisInfinity(scip, -lb));
11854             assert(!SCIPisInfinity(scip, ub));
11855 
11856             /* update residual activities */
11857             if( vals[w] > 0 )
11858             {
11859                tmpmaxactsub += ub * vals[w];
11860                tmpminactsub += lb * vals[w];
11861             }
11862             else
11863             {
11864                tmpmaxactsub += lb * vals[w];
11865                tmpminactsub += ub * vals[w];
11866             }
11867             assert(tmpmaxactsub >= tmpminactsub);
11868          }
11869 
11870          if( hasrhs )
11871          {
11872             assert(offsetv == -1);
11873 
11874             /* determine the remainder of the right hand side and the gcd */
11875             siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11876          }
11877          else
11878          {
11879             /* determine the remainder of the left hand side and the gcd */
11880             siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11881             if( SCIPisZero(scip, siderest) )
11882                siderest = gcd;
11883          }
11884 
11885          /* is the redundancy really fulfilled */
11886          assert((hasrhs && SCIPisFeasLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) ||
11887                (haslhs && tmpmaxactsub < siderest && SCIPisFeasGE(scip, tmpminactsub, siderest - gcd)));
11888 #endif
11889 
11890          SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11891             nvars - v, SCIPconsGetName(cons));
11892 
11893          /* remove redundant variables */
11894          for( w = nvars - 1; w >= v; --w )
11895          {
11896             SCIP_CALL( delCoefPos(scip, cons, w) );
11897          }
11898          (*nchgcoefs) += (nvars - v);
11899 
11900          assert(w >= 0);
11901 
11902          oldcoef = vals[w];
11903 
11904          /* normalize constraint */
11905          SCIP_CALL( normalizeCons(scip, cons, infeasible) );
11906          assert(vars == consdata->vars);
11907          assert(vals == consdata->vals);
11908          assert(w < consdata->nvars);
11909 
11910          if( *infeasible )
11911             return SCIP_OKAY;
11912 
11913          /* compute new greatest common divisor due to normalization */
11914          gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11915          assert(gcd >= 1);
11916 
11917          /* update side */
11918          if( hasrhs )
11919          {
11920             /* replace old with new right hand side */
11921             SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11922             rhs = consdata->rhs;
11923          }
11924          else
11925          {
11926             if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11927             {
11928                SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11929                lhs = consdata->lhs;
11930             }
11931             else
11932                assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11933          }
11934          ++(*nchgsides);
11935 
11936          assert(!hasrhs || !SCIPisNegative(scip, rhs));
11937          assert(!haslhs || !SCIPisNegative(scip, lhs));
11938 
11939          /* get new constraint data */
11940          nvars = consdata->nvars;
11941          assert(nvars > 0);
11942 
11943          allcoefintegral = TRUE;
11944 
11945 #ifndef NDEBUG
11946          /* check integrality */
11947          for( w = offsetv + 1; w < nvars; ++w )
11948          {
11949             assert(SCIPisIntegral(scip, vals[w]));
11950          }
11951 #endif
11952          SCIPdebugPrintCons(scip, cons, NULL);
11953       }
11954 
11955       /* try to find a better gcd, when having large coefficients */
11956       if( offsetv >= 0 && gcd == 1 )
11957       {
11958          /* calculate greatest common divisor for all general variables */
11959          gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11960 
11961          if( gcd > 1 )
11962          {
11963             gcd = -1;
11964             candpos = -1;
11965 
11966             for( v = nvars - 1; v > offsetv; --v )
11967             {
11968                assert(!SCIPisZero(scip, vals[v]));
11969                if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11970                   break;
11971 
11972                if( !SCIPisIntegral(scip, vals[v]) )
11973                {
11974                   allcoefintegral = FALSE;
11975                   break;
11976                }
11977 
11978                oldgcd = gcd;
11979 
11980                if( gcd == -1 )
11981                {
11982                   gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11983                   assert(gcd >= 1);
11984                }
11985                else
11986                {
11987                   /* calculate greatest common divisor for all general and binary variables */
11988                   gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11989                }
11990 
11991                /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11992                 * can stop searching
11993                 */
11994                if( gcd == 1 )
11995                {
11996                   if( !SCIPvarIsBinary(vars[v]) )
11997                      break;
11998 
11999                   /* found candidate */
12000                   if( candpos == -1 )
12001                   {
12002                      gcd = oldgcd;
12003                      candpos = v;
12004                   }
12005                   /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12006                   else
12007                      break;
12008                }
12009             }
12010             assert(v > offsetv || candpos > offsetv);
12011          }
12012          else
12013             candpos = -1;
12014       }
12015       else
12016          candpos = nvars - 1;
12017 
12018       /* check last coefficient for integrality */
12019       if( gcd > 1 && allcoefintegral && !redundant )
12020       {
12021          if( !SCIPisIntegral(scip, vals[nvars - 1]) )
12022             allcoefintegral = FALSE;
12023       }
12024 
12025       /* check for further necessary coefficient adjustments */
12026       if( offsetv >= 0 && gcd > 1 && allcoefintegral )
12027       {
12028          assert(offsetv + 1 < nvars);
12029          assert(0 <= candpos && candpos < nvars);
12030 
12031          if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
12032          {
12033             SCIP_Bool notchangable = FALSE;
12034 
12035 #ifndef NDEBUG
12036             /* check integrality */
12037             for( w = offsetv + 1; w < nvars; ++w )
12038             {
12039                assert(SCIPisIntegral(scip, vals[w]));
12040             }
12041 #endif
12042 
12043             if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
12044                SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
12045             {
12046                /* determine the remainder of the side and the gcd */
12047                if( hasrhs )
12048                   rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12049                else
12050                   rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12051                assert(rest >= 0);
12052                assert(rest < gcd);
12053 
12054                /* determine the remainder of the coefficient candidate and the gcd */
12055                restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12056                assert(restcoef >= 1);
12057                assert(restcoef < gcd);
12058 
12059                if( hasrhs )
12060                {
12061                   /* calculate new coefficient */
12062                   if( restcoef > rest )
12063                      newcoef = vals[candpos] - restcoef + gcd;
12064                   else
12065                      newcoef = vals[candpos] - restcoef;
12066                }
12067                else
12068                {
12069                   /* calculate new coefficient */
12070                   if( rest == 0 || restcoef < rest )
12071                      newcoef = vals[candpos] - restcoef;
12072                   else
12073                      newcoef = vals[candpos] - restcoef + gcd;
12074                }
12075 
12076                /* done */
12077 
12078                /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
12079                 * another with the big coefficient was set to 1
12080                 */
12081                if( hasrhs && SCIPisZero(scip, newcoef) )
12082                {
12083                   notchangable = TRUE;
12084                }
12085                else if( SCIPisZero(scip, newcoef) )
12086                {
12087                   /* delete old redundant coefficient */
12088                   SCIP_CALL( delCoefPos(scip, cons, candpos) );
12089                   ++(*nchgcoefs);
12090                }
12091                else
12092                {
12093                   /* replace old with new coefficient */
12094                   SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12095                   ++(*nchgcoefs);
12096                }
12097             }
12098             else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
12099             {
12100                gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
12101             }
12102 
12103             /* correct side and big coefficients */
12104             if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
12105                ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
12106             {
12107                if( haslhs )
12108                {
12109                   newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
12110 
12111                   SCIP_CALL( chgLhs(scip, cons, newcoef) );
12112                   ++(*nchgsides);
12113                }
12114                else
12115                {
12116                   assert(hasrhs);
12117                   newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
12118 
12119                   SCIP_CALL( chgRhs(scip, cons, newcoef) );
12120                   ++(*nchgsides);
12121                }
12122 
12123                /* correct coefficients up front */
12124                for( w = offsetv; w >= 0; --w )
12125                {
12126                   assert(vals[w] > 0);
12127 
12128                   SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
12129                }
12130                (*nchgcoefs) += (offsetv + 1);
12131             }
12132 
12133             if( !notchangable )
12134             {
12135                /* normalize constraint */
12136                SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12137                assert(vars == consdata->vars);
12138                assert(vals == consdata->vals);
12139 
12140                if( *infeasible )
12141                   return SCIP_OKAY;
12142 
12143                /* get new constraint data */
12144                nvars = consdata->nvars;
12145                assert(nvars >= 2);
12146 
12147                SCIPdebugPrintCons(scip, cons, NULL);
12148 
12149                lhs = consdata->lhs;
12150                rhs = consdata->rhs;
12151                assert(!hasrhs || !SCIPisNegative(scip, rhs));
12152                assert(!haslhs || !SCIPisNegative(scip, lhs));
12153             }
12154          }
12155       }
12156    }
12157 
12158    /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
12159    /* no continuous variables are left over */
12160    if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
12161       return SCIP_OKAY;
12162 
12163    onlybin = TRUE;
12164    allcoefintegral = TRUE;
12165    /* check if all variables are of binary type */
12166    for( v = nvars - 1; v >= 0; --v )
12167    {
12168       if( !SCIPvarIsBinary(vars[v]) )
12169          onlybin = FALSE;
12170       if( !SCIPisIntegral(scip, vals[v]) )
12171          allcoefintegral = FALSE;
12172    }
12173 
12174    /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
12175     * hand side or bigger than the left hand side respectively, so we can make all of them integral
12176     *
12177     * @todo there are some steps missing ....
12178     */
12179    if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
12180    {
12181       SCIP_Real val;
12182       SCIP_Real newval;
12183       SCIP_Real frac = 0.0;
12184       SCIP_Bool found = FALSE;
12185 
12186       if( hasrhs )
12187       {
12188          if( allcoefintegral )
12189          {
12190             /* replace old with new right hand side */
12191             SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12192             ++(*nchgsides);
12193          }
12194          else
12195          {
12196             siderest = rhs - SCIPfloor(scip, rhs);
12197 
12198             /* try to round down all non-integral coefficients */
12199             for( v = nvars - 1; v >= 0; --v )
12200             {
12201                val = vals[v];
12202 
12203                /* add up all possible fractional parts */
12204                if( !SCIPisIntegral(scip, val) )
12205                {
12206                   lb = SCIPvarGetLbGlobal(vars[v]);
12207                   ub = SCIPvarGetUbGlobal(vars[v]);
12208 
12209                   /* at least one bound need to be at zero */
12210                   if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12211                      return SCIP_OKAY;
12212 
12213                   /* swap bounds for 'standard' form */
12214                   if( !SCIPisFeasZero(scip, lb) )
12215                   {
12216                      ub = lb;
12217                      val *= -1;
12218                   }
12219 
12220                   found = TRUE;
12221 
12222                   frac += (val - SCIPfloor(scip, val)) * ub;
12223 
12224                   /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
12225                    *
12226                    * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
12227                    *      x3, x4 set to 1 would be infeasible but feasible after flooring
12228                    */
12229                   if( SCIPisGT(scip, frac, siderest) )
12230                      return SCIP_OKAY;
12231                }
12232             }
12233             assert(v == -1);
12234 
12235             SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
12236 
12237             /* round rhs and coefficients to integral values */
12238             if( found )
12239             {
12240                for( v = nvars - 1; v >= 0; --v )
12241                {
12242                   val = vals[v];
12243 
12244                   /* add the whole fractional part */
12245                   if( !SCIPisIntegral(scip, val) )
12246                   {
12247                      lb = SCIPvarGetLbGlobal(vars[v]);
12248 
12249                      if( SCIPisFeasZero(scip, lb) )
12250                         newval = SCIPfloor(scip, val);
12251                      else
12252                         newval = SCIPceil(scip, val);
12253 
12254                      if( SCIPisZero(scip, newval) )
12255                      {
12256                         /* delete old redundant coefficient */
12257                         SCIP_CALL( delCoefPos(scip, cons, v) );
12258                         ++(*nchgcoefs);
12259                      }
12260                      else
12261                      {
12262                         /* replace old with new coefficient */
12263                         SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12264                         ++(*nchgcoefs);
12265                      }
12266                   }
12267                }
12268             }
12269 
12270             /* replace old with new right hand side */
12271             SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
12272             ++(*nchgsides);
12273          }
12274       }
12275       else
12276       {
12277          if( allcoefintegral )
12278          {
12279             /* replace old with new left hand side */
12280             SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
12281             ++(*nchgsides);
12282          }
12283          else
12284          {
12285             /* cannot floor left hand side to zero */
12286             if( SCIPisLT(scip, lhs, 1.0) )
12287                return SCIP_OKAY;
12288 
12289             siderest = lhs - SCIPfloor(scip, lhs);
12290 
12291             /* try to round down all non-integral coefficients */
12292             for( v = nvars - 1; v >= 0; --v )
12293             {
12294                val = vals[v];
12295 
12296                /* add up all possible fractional parts */
12297                if( !SCIPisIntegral(scip, val) )
12298                {
12299                   lb = SCIPvarGetLbGlobal(vars[v]);
12300                   ub = SCIPvarGetUbGlobal(vars[v]);
12301 
12302                   /* at least one bound need to be at zero */
12303                   if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
12304                      return SCIP_OKAY;
12305 
12306                   /* swap bounds for 'standard' form */
12307                   if( !SCIPisFeasZero(scip, lb) )
12308                   {
12309                      ub = lb;
12310                      val *= -1;
12311                   }
12312 
12313                   /* cannot floor to zero */
12314                   if( SCIPisLT(scip, val, 1.0) )
12315                      return SCIP_OKAY;
12316 
12317                   /* the fractional part on each variable need to exceed the fractional part on the left hand side */
12318                   if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
12319                      return SCIP_OKAY;
12320 
12321                   found = TRUE;
12322 
12323                   frac += (val - SCIPfloor(scip, val)) * ub;
12324 
12325                   /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
12326                    * fractional parts of the variables, we cannot tighten the coefficients
12327                    *
12328                    * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
12329                    *      x2-x4 set to 1 would be feasible but not after flooring
12330                    */
12331                   if( SCIPisGE(scip, frac, 1 + siderest) )
12332                      return SCIP_OKAY;
12333                }
12334                /* all coefficients need to be integral, otherwise we might do an invalid reduction */
12335                else
12336                   return SCIP_OKAY;
12337             }
12338             assert(v == -1);
12339 
12340             SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
12341 
12342             /* round lhs and coefficients to integral values */
12343             if( found )
12344             {
12345                for( v = nvars - 1; v >= 0; --v )
12346                {
12347                   val = vals[v];
12348 
12349                   /* add the whole fractional part */
12350                   if( !SCIPisIntegral(scip, val) )
12351                   {
12352                      lb = SCIPvarGetLbGlobal(vars[v]);
12353 
12354                      if( SCIPisFeasZero(scip, lb) )
12355                         newval = SCIPfloor(scip, val);
12356                      else
12357                         newval = SCIPceil(scip, val);
12358 
12359                      if( SCIPisZero(scip, newval) )
12360                      {
12361                         /* delete old redundant coefficient */
12362                         SCIP_CALL( delCoefPos(scip, cons, v) );
12363                         ++(*nchgcoefs);
12364                      }
12365                      else
12366                      {
12367                         /* replace old with new coefficient */
12368                         SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12369                         ++(*nchgcoefs);
12370                      }
12371                   }
12372                }
12373             }
12374 
12375             /* replace old with new left hand side */
12376             SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12377             ++(*nchgsides);
12378          }
12379       }
12380 
12381       /* normalize constraint */
12382       SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12383       assert(vars == consdata->vars);
12384       assert(vals == consdata->vals);
12385 
12386       if( *infeasible )
12387          return SCIP_OKAY;
12388 
12389       rhs = consdata->rhs;
12390       lhs = consdata->lhs;
12391 
12392       assert(!hasrhs || !SCIPisNegative(scip, rhs));
12393       assert(!haslhs || !SCIPisNegative(scip, lhs));
12394 
12395       SCIPdebugPrintCons(scip, cons, NULL);
12396 
12397       nvars = consdata->nvars;
12398       if( nvars < 2 )
12399          return SCIP_OKAY;
12400 
12401       allcoefintegral = TRUE;
12402 #ifndef NDEBUG
12403       /* debug check if all coefficients are really integral */
12404       for( v = nvars - 1; v >= 0; --v )
12405          assert(SCIPisIntegral(scip, vals[v]));
12406 #endif
12407    }
12408 
12409    /* @todo following can also work on non integral coefficients, need more investigation */
12410    /* only check constraints with integral coefficients on all integral variables */
12411    if( !allcoefintegral )
12412       return SCIP_OKAY;
12413 
12414    /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12415    if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12416       return SCIP_OKAY;
12417 
12418    /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12419    if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12420       return SCIP_OKAY;
12421 
12422    /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12423    if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12424       return SCIP_OKAY;
12425 
12426    assert(nvars >= 2);
12427 
12428    /* start gcd procedure for all variables */
12429    do
12430    {
12431       SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12432       SCIPdebug( oldnchgsides = *nchgsides; )
12433 
12434       /* stop if we have two coeffcients which are one in absolute value */
12435       if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12436          return SCIP_OKAY;
12437 
12438       gcd = -1;
12439 
12440       /* calculate greatest common divisor over all integer variables; note that the onlybin flag needs to be recomputed
12441        * because coefficients of non-binary variables might have changed to zero */
12442       if( !onlybin )
12443       {
12444          foundbin = -1;
12445          onlybin = TRUE;
12446 
12447          for( v = nvars - 1; v >= 0; --v )
12448          {
12449             assert(!SCIPisZero(scip, vals[v]));
12450             assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12451 
12452             if( SCIPvarIsBinary(vars[v]) )
12453             {
12454                if( foundbin == -1 )
12455                   foundbin = v;
12456                continue;
12457             }
12458             else
12459                onlybin = FALSE;
12460 
12461             absval = REALABS(vals[v]);
12462             /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12463              * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12464              */
12465             assert(SCIPisFeasIntegral(scip, absval));
12466 
12467             if( gcd == -1 )
12468             {
12469                gcd = (SCIP_Longint)(absval + feastol);
12470                assert(gcd >= 1);
12471             }
12472             else
12473             {
12474                /* calculate greatest common divisor for all general variables */
12475                gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12476             }
12477             if( gcd == 1 )
12478                break;
12479          }
12480       }
12481       else
12482          foundbin = nvars - 1;
12483 
12484       /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12485       if( gcd == 1 || foundbin == -1)
12486          return SCIP_OKAY;
12487 
12488       assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12489 
12490       candpos = -1;
12491       candpos2 = -1;
12492 
12493       /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12494        * change the coefficient
12495        */
12496       for( v = foundbin; v >= 0; --v )
12497       {
12498          if( onlybin || SCIPvarIsBinary(vars[v]) )
12499          {
12500             absval = REALABS(vals[v]);
12501             /* arithmetic precision can lead to the absolute value only being integral up to feasibility tolerance,
12502              * even though the value itself is feasible up to epsilon, but since we add feastol later, this is enough
12503              */
12504             assert(SCIPisFeasIntegral(scip, absval));
12505 
12506             oldgcd = gcd;
12507 
12508             if( gcd == -1 )
12509             {
12510                gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12511                assert(gcd >= 1);
12512             }
12513             else
12514             {
12515                /* calculate greatest common divisor for all general and binary variables */
12516                gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12517             }
12518 
12519             /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12520              * can terminate
12521              */
12522             if( gcd == 1 )
12523             {
12524                /* found candidate */
12525                if( candpos == -1 )
12526                {
12527                   gcd = oldgcd;
12528                   candpos = v;
12529 
12530                   /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12531                    * the coefficient change
12532                    */
12533                   if( onlybin && v == foundbin - 1 )
12534                      candpos2 = foundbin;
12535                }
12536                /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12537                else
12538                {
12539                   if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12540                   {
12541                      assert(candpos2 == nvars - 1);
12542 
12543                      /* take new candidates */
12544                      candpos = candpos2;
12545 
12546                      /* recalculate gcd from scratch */
12547                      gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12548                      assert(gcd >= 1);
12549 
12550                      /* calculate greatest common divisor for all general and binary variables */
12551                      gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12552                      if( gcd == 1 )
12553                         return SCIP_OKAY;
12554                   }
12555                   else
12556                      /* cannot determine a possible coefficient for reduction */
12557                      return SCIP_OKAY;
12558                }
12559             }
12560          }
12561       }
12562       assert(gcd >= 2);
12563 
12564       /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12565        * further
12566        */
12567       assert(candpos >= 0 && candpos < nvars);
12568 
12569       /* all variables and all coefficients are integral, so the side should be too */
12570       assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12571 
12572       /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12573        * @see normalizeCons()
12574        */
12575       assert(!hasrhs || !SCIPisNegative(scip, rhs));
12576       assert(!haslhs || !SCIPisNegative(scip, lhs));
12577 
12578       /* determine the remainder of the side and the gcd */
12579       if( hasrhs )
12580          rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12581       else
12582          rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12583       assert(rest >= 0);
12584       assert(rest < gcd);
12585 
12586       /* determine the remainder of the coefficient candidate and the gcd */
12587       if( vals[candpos] < 0 )
12588       {
12589          restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12590          assert(restcoef <= -1);
12591          restcoef += gcd;
12592       }
12593       else
12594          restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12595       assert(restcoef >= 1);
12596       assert(restcoef < gcd);
12597 
12598       if( hasrhs )
12599       {
12600          if( rest > 0 )
12601          {
12602             /* replace old with new right hand side */
12603             SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12604             ++(*nchgsides);
12605          }
12606 
12607          /* calculate new coefficient */
12608          if( restcoef > rest )
12609             newcoef = vals[candpos] - restcoef + gcd;
12610          else
12611             newcoef = vals[candpos] - restcoef;
12612       }
12613       else
12614       {
12615          if( rest > 0 )
12616          {
12617             /* replace old with new left hand side */
12618             SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12619             ++(*nchgsides);
12620          }
12621 
12622          /* calculate new coefficient */
12623          if( rest == 0 || restcoef < rest )
12624             newcoef = vals[candpos] - restcoef;
12625          else
12626             newcoef = vals[candpos] - restcoef + gcd;
12627       }
12628       assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12629 
12630       SCIPdebugMsg(scip, "gcd = %" SCIP_LONGINT_FORMAT ", rest = %" SCIP_LONGINT_FORMAT ", restcoef = %" SCIP_LONGINT_FORMAT "; changing coef of variable <%s> to %g and %s by %" SCIP_LONGINT_FORMAT "\n", gcd, rest, restcoef, SCIPvarGetName(vars[candpos]), newcoef, hasrhs ? "reduced rhs" : "increased lhs", hasrhs ? rest : (rest > 0 ? gcd - rest : 0));
12631 
12632       if( SCIPisZero(scip, newcoef) )
12633       {
12634          /* delete redundant coefficient */
12635          SCIP_CALL( delCoefPos(scip, cons, candpos) );
12636       }
12637       else
12638       {
12639          /* replace old with new coefficient */
12640          SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12641       }
12642       ++(*nchgcoefs);
12643 
12644       /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12645       SCIP_CALL( normalizeCons(scip, cons, infeasible) );
12646       assert(vars == consdata->vars);
12647       assert(vals == consdata->vals);
12648 
12649       if( *infeasible )
12650          return SCIP_OKAY;
12651 
12652       SCIPdebugPrintCons(scip, cons, NULL);
12653 
12654       rhs = consdata->rhs;
12655       lhs = consdata->lhs;
12656       assert(!hasrhs || !SCIPisNegative(scip, rhs));
12657       assert(!haslhs || !SCIPisNegative(scip, lhs));
12658 
12659       nvars = consdata->nvars;
12660 
12661       SCIPdebugMsg(scip, "we did %d coefficient changes and %d side changes on constraint %s when applying one round of the gcd algorithm\n", *nchgcoefs - oldnchgcoefs, *nchgsides - oldnchgsides, SCIPconsGetName(cons));
12662    }
12663    while( nvars >= 2 );
12664 
12665    return SCIP_OKAY;
12666 }
12667 
12668 
12669 /** tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12670  *   cons0 := a * cons0 + b * cons1,
12671  *  where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12672  *  for numerical stability, we will only accept integral a and b;
12673  *  the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12674  *  each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12675  */
12676 static
aggregateConstraints(SCIP * scip,SCIP_CONS * cons0,SCIP_CONS * cons1,int * commonidx0,int * commonidx1,int * diffidx0minus1,int * diffidx1minus0,int nvarscommon,int commonidxweight,int diffidx0minus1weight,int diffidx1minus0weight,SCIP_Real maxaggrnormscale,int * nchgcoefs,SCIP_Bool * aggregated,SCIP_Bool * infeasible)12677 SCIP_RETCODE aggregateConstraints(
12678    SCIP*                 scip,               /**< SCIP data structure */
12679    SCIP_CONS*            cons0,              /**< (in)equality to modify */
12680    SCIP_CONS*            cons1,              /**< equality to use for aggregation of cons0 */
12681    int*                  commonidx0,         /**< array with indices of variables in cons0, that appear also in cons1 */
12682    int*                  commonidx1,         /**< array with indices of variables in cons1, that appear also in cons0 */
12683    int*                  diffidx0minus1,     /**< array with indices of variables in cons0, that don't appear in cons1 */
12684    int*                  diffidx1minus0,     /**< array with indices of variables in cons1, that don't appear in cons0 */
12685    int                   nvarscommon,        /**< number of variables, that appear in both constraints */
12686    int                   commonidxweight,    /**< variable weight sum of common variables */
12687    int                   diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12688    int                   diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12689    SCIP_Real             maxaggrnormscale,   /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12690    int*                  nchgcoefs,          /**< pointer to count the number of changed coefficients */
12691    SCIP_Bool*            aggregated,         /**< pointer to store whether an aggregation was made */
12692    SCIP_Bool*            infeasible          /**< pointer to store whether infeasibility was detected */
12693    )
12694 {
12695    SCIP_CONSDATA* consdata0;
12696    SCIP_CONSDATA* consdata1;
12697    SCIP_Real a;
12698    SCIP_Real b;
12699    SCIP_Real aggrcoef;
12700    SCIP_Real scalarsum;
12701    SCIP_Real bestscalarsum;
12702    SCIP_Bool betterscalarsum;
12703    SCIP_Bool commonvarlindependent;  /* indicates whether coefficient vector of common variables in linearly dependent */
12704    int varweight;
12705    int nvars;
12706    int bestvarweight;
12707    int bestnvars;
12708    int bestv;
12709    int v;
12710    int i;
12711 
12712    assert(scip != NULL);
12713    assert(cons0 != NULL);
12714    assert(cons1 != NULL);
12715    assert(commonidx0 != NULL);
12716    assert(commonidx1 != NULL);
12717    assert(diffidx0minus1 != NULL);
12718    assert(diffidx1minus0 != NULL);
12719    assert(nvarscommon >= 1);
12720    assert(commonidxweight >= nvarscommon);
12721    assert(nchgcoefs != NULL);
12722    assert(aggregated != NULL);
12723 
12724    assert(SCIPconsIsActive(cons0));
12725    assert(SCIPconsIsActive(cons1));
12726 
12727    *infeasible = FALSE;
12728 
12729    SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12730 
12731    /* cons0 is an (in)equality */
12732    consdata0 = SCIPconsGetData(cons0);
12733    assert(consdata0 != NULL);
12734    assert(consdata0->nvars >= 1);
12735    assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12736    assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12737 
12738    /* cons1 is an equality */
12739    consdata1 = SCIPconsGetData(cons1);
12740    assert(consdata1 != NULL);
12741    assert(consdata1->nvars >= 1);
12742    assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12743    assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12744 
12745    *aggregated = FALSE;
12746 
12747    /* search for the best common variable such that
12748     *   val1[var] * consdata0 - val0[var] * consdata1
12749     * has least weighted number of variables
12750     */
12751    bestvarweight = commonidxweight + diffidx0minus1weight;
12752    bestnvars = consdata0->nvars;
12753    bestv = -1;
12754    bestscalarsum = 0.0;
12755    commonvarlindependent = TRUE;
12756    for( v = 0; v < nvarscommon; ++v )
12757    {
12758       assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12759       a = consdata1->vals[commonidx1[v]];
12760       b = -consdata0->vals[commonidx0[v]];
12761 
12762       /* only try aggregation, if coefficients are integral (numerical stability) */
12763       if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12764       {
12765          /* count the number of variables in the potential new constraint  a * consdata0 + b * consdata1 */
12766          varweight = diffidx0minus1weight + diffidx1minus0weight;
12767          nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12768          scalarsum = REALABS(a) + REALABS(b);
12769          betterscalarsum = (scalarsum < bestscalarsum);
12770          for( i = 0; i < nvarscommon
12771                  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12772          {
12773             aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12774             if( !SCIPisZero(scip, aggrcoef) )
12775             {
12776                varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12777                nvars++;
12778             }
12779          }
12780          if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12781          {
12782             bestv = v;
12783             bestvarweight = varweight;
12784             bestnvars = nvars;
12785             bestscalarsum = scalarsum;
12786          }
12787       }
12788 
12789       /* update commonvarlindependent flag, if still TRUE:
12790        * v's common coefficient in cons1 / v's common coefficient in cons0 should be constant, i.e., equal 0's common coefficient in cons1 / 0's common coefficient in cons0
12791        */
12792       if( commonvarlindependent && v > 0 )
12793          commonvarlindependent = SCIPisEQ(scip,
12794             consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12795             consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12796    }
12797 
12798    /* if better aggregation was found, create new constraint and delete old one */
12799    if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12800    {
12801       SCIP_CONS* newcons;
12802       SCIP_CONSDATA* newconsdata;
12803       SCIP_VAR** newvars;
12804       SCIP_Real* newvals;
12805       SCIP_Real newlhs;
12806       SCIP_Real newrhs;
12807       int newnvars;
12808 
12809       if( bestv != -1 )
12810       {
12811          /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12812          if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12813          {
12814             a = consdata1->vals[commonidx1[bestv]];
12815             b = -consdata0->vals[commonidx0[bestv]];
12816          }
12817          else
12818          {
12819             a = -consdata1->vals[commonidx1[bestv]];
12820             b = consdata0->vals[commonidx0[bestv]];
12821          }
12822          assert(SCIPisIntegral(scip, a));
12823          assert(SCIPisPositive(scip, a));
12824          assert(SCIPisIntegral(scip, b));
12825          assert(!SCIPisZero(scip, b));
12826       }
12827       else
12828       {
12829          assert(commonvarlindependent);
12830          if( consdata1->vals[commonidx1[0]] > 0.0 )
12831          {
12832             a =  consdata1->vals[commonidx1[0]];
12833             b = -consdata0->vals[commonidx0[0]];
12834          }
12835          else
12836          {
12837             a = -consdata1->vals[commonidx1[0]];
12838             b =  consdata0->vals[commonidx0[0]];
12839          }
12840          assert(SCIPisPositive(scip, a));
12841          assert(!SCIPisZero(scip, b));
12842 
12843          /* if a/b is integral, then we can easily choose integer multipliers */
12844          if( SCIPisIntegral(scip, a/b) )
12845          {
12846             if( a/b > 0 )
12847             {
12848                a /= b;
12849                b = 1.0;
12850             }
12851             else
12852             {
12853                a /= -b;
12854                b = -1.0;
12855             }
12856          }
12857 
12858          /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12859          SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12860          bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12861       }
12862 
12863       SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s>  ->  nvars: %d -> %d, weight: %d -> %d\n",
12864          SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12865          consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12866       SCIPdebugPrintCons(scip, cons0, NULL);
12867       SCIPdebugPrintCons(scip, cons1, NULL);
12868 
12869       /* get temporary memory for creating the new linear constraint */
12870       SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12871       SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12872 
12873       /* calculate the common coefficients, if we have not recognized linear dependency */
12874       newnvars = 0;
12875       if( !commonvarlindependent )
12876       {
12877          for( i = 0; i < nvarscommon; ++i )
12878          {
12879             assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12880             assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12881 
12882             aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12883             if( !SCIPisZero(scip, aggrcoef) )
12884             {
12885                assert(newnvars < bestnvars);
12886                newvars[newnvars] = consdata0->vars[commonidx0[i]];
12887                newvals[newnvars] = aggrcoef;
12888                newnvars++;
12889             }
12890          }
12891       }
12892       else
12893       {
12894          /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12895 #ifndef NDEBUG
12896          for( i = 0; i < nvarscommon; ++i )
12897          {
12898             assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12899             assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12900 
12901             aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12902             assert(SCIPisZero(scip, aggrcoef));
12903          }
12904 #endif
12905       }
12906 
12907       /* calculate the coefficients appearing in cons0 but not in cons1 */
12908       for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12909       {
12910          assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12911 
12912          aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12913          assert(!SCIPisZero(scip, aggrcoef));
12914          assert(newnvars < bestnvars);
12915          newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12916          newvals[newnvars] = aggrcoef;
12917          newnvars++;
12918       }
12919 
12920       /* calculate the coefficients appearing in cons1 but not in cons0 */
12921       for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12922       {
12923          assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12924 
12925          aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12926          assert(!SCIPisZero(scip, aggrcoef));
12927          assert(newnvars < bestnvars);
12928          newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12929          newvals[newnvars] = aggrcoef;
12930          newnvars++;
12931       }
12932       assert(newnvars == bestnvars);
12933 
12934       /* calculate the new left and right hand side of the (in)equality */
12935       assert(!SCIPisInfinity(scip, -consdata1->lhs));
12936       assert(!SCIPisInfinity(scip, consdata1->rhs));
12937       if( SCIPisInfinity(scip, -consdata0->lhs) )
12938          newlhs = -SCIPinfinity(scip);
12939       else
12940          newlhs = a * consdata0->lhs + b * consdata1->lhs;
12941       if( SCIPisInfinity(scip, consdata0->rhs) )
12942          newrhs = SCIPinfinity(scip);
12943       else
12944          newrhs = a * consdata0->rhs + b * consdata1->rhs;
12945 
12946       /* create the new linear constraint */
12947       SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12948             SCIPconsIsInitial(cons0), SCIPconsIsSeparated(cons0), SCIPconsIsEnforced(cons0),
12949             SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
12950             SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
12951             SCIPconsIsDynamic(cons0), SCIPconsIsRemovable(cons0), SCIPconsIsStickingAtNode(cons0)) );
12952 
12953       newconsdata = SCIPconsGetData(newcons);
12954       assert(newconsdata != NULL);
12955 
12956       /* copy the upgraded flag from the old cons0 to the new constraint */
12957       newconsdata->upgraded = consdata0->upgraded;
12958 
12959       /* normalize the new constraint */
12960       SCIP_CALL( normalizeCons(scip, newcons, infeasible) );
12961 
12962       if( *infeasible )
12963          goto TERMINATE;
12964 
12965       /* check, if we really want to use the new constraint instead of the old one:
12966        * use the new one, if the maximum norm doesn't grow too much
12967        */
12968       if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12969       {
12970          SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12971          SCIPdebugPrintCons(scip, newcons, NULL);
12972 
12973          /* update the statistics: we changed all coefficients */
12974          if( !consdata0->upgraded )
12975             (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12976          *aggregated = TRUE;
12977 
12978          /* delete the old constraint, and add the new linear constraint to the problem */
12979          SCIP_CALL( SCIPdelCons(scip, cons0) );
12980          SCIP_CALL( SCIPaddCons(scip, newcons) );
12981       }
12982 
12983      TERMINATE:
12984       /* release the new constraint */
12985       SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12986 
12987       /* free temporary memory */
12988       SCIPfreeBufferArray(scip, &newvals);
12989       SCIPfreeBufferArray(scip, &newvars);
12990    }
12991 
12992    return SCIP_OKAY;
12993 }
12994 
12995 /** gets the key of the given element */
12996 static
SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)12997 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12998 {  /*lint --e{715}*/
12999    /* the key is the element itself */
13000    return elem;
13001 }
13002 
13003 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
13004  *  coefficients are either equal or negated
13005  */
13006 static
SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)13007 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
13008 {
13009    SCIP* scip;
13010    SCIP_CONSDATA* consdata1;
13011    SCIP_CONSDATA* consdata2;
13012    SCIP_Real cons1scale;
13013    SCIP_Real cons2scale;
13014    int i;
13015 
13016    assert(key1 != NULL);
13017    assert(key2 != NULL);
13018    consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
13019    consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
13020    assert(consdata1->indexsorted);
13021    assert(consdata2->indexsorted);
13022 
13023    scip = (SCIP*)userptr;
13024    assert(scip != NULL);
13025 
13026    /* if it is the same constraint we dont need to check anything */
13027    if( key1 == key2 )
13028       return TRUE;
13029 
13030    /* checks trivial case */
13031    if( consdata1->nvars != consdata2->nvars )
13032       return FALSE;
13033 
13034    /* tests if variables are equal */
13035    for( i = 0; i < consdata1->nvars; ++i )
13036    {
13037       if( consdata1->vars[i] != consdata2->vars[i] )
13038       {
13039          assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
13040             SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
13041          return FALSE;
13042       }
13043       assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
13044    }
13045 
13046    /* compute scale before comparing coefficients of constraints */
13047    cons1scale = COPYSIGN(1.0/consdata1->maxabsval, consdata1->vals[0]);
13048    cons2scale = COPYSIGN(1.0/consdata2->maxabsval, consdata2->vals[0]);
13049 
13050    /* tests if coefficients are equal with the computed scale */
13051    for( i = 0; i < consdata1->nvars; ++i )
13052    {
13053       SCIP_Real val1;
13054       SCIP_Real val2;
13055 
13056       val1 = consdata1->vals[i] * cons1scale;
13057       val2 = consdata2->vals[i] * cons2scale;
13058 
13059       if( !SCIPisEQ(scip, val1, val2) )
13060          return FALSE;
13061    }
13062 
13063    return TRUE;
13064 }
13065 
13066 /** returns the hash value of the key */
13067 static
SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)13068 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
13069 {
13070    SCIP_CONSDATA* consdata;
13071    int minidx;
13072    int mididx;
13073    int maxidx;
13074    SCIP_Real scale;
13075 #ifndef NDEBUG
13076    SCIP* scip;
13077 
13078    scip = (SCIP*)userptr;
13079    assert(scip != NULL);
13080 #endif
13081 
13082    assert(key != NULL);
13083    consdata = SCIPconsGetData((SCIP_CONS*)key);
13084    assert(consdata != NULL);
13085    assert(consdata->nvars > 0);
13086 
13087    assert(consdata->indexsorted);
13088 
13089    minidx = SCIPvarGetIndex(consdata->vars[0]);
13090    mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
13091    maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
13092    scale = COPYSIGN(1.0/consdata->maxabsval, consdata->vals[0]);
13093 
13094    /* using only the variable indices as hash, since the values are compared by epsilon */
13095    return SCIPhashSeven(consdata->nvars, minidx, SCIPrealHashCode(consdata->vals[0] * scale),
13096                         mididx, SCIPrealHashCode(consdata->vals[consdata->nvars / 2] * scale),
13097                         maxidx, SCIPrealHashCode(consdata->vals[consdata->nvars - 1] * scale));
13098 }
13099 
13100 /** returns the key for deciding which of two parallel constraints should be kept (smaller key should be kept);
13101  *  prefers non-upgraded constraints and as second criterion the constraint with the smallest position
13102  */
13103 static
getParallelConsKey(SCIP_CONS * cons)13104 unsigned int getParallelConsKey(
13105    SCIP_CONS*            cons                /**< linear constraint */
13106    )
13107 {
13108    SCIP_CONSDATA* consdata;
13109 
13110    assert(cons != NULL);
13111 
13112    consdata = SCIPconsGetData(cons);
13113    assert(consdata != NULL);
13114 
13115    return (((unsigned int)consdata->upgraded)<<31) + (unsigned int)SCIPconsGetPos(cons); /*lint !e571*/
13116 }
13117 
13118 /** updates the hashtable such that out of all constraints in the hashtable that are detected
13119  *  to be parallel to *querycons, only one is kept in the hashtable and stored into *querycons,
13120  *  and all others are removed from the hashtable and stored in the given array
13121  */
13122 static
retrieveParallelConstraints(SCIP_HASHTABLE * hashtable,SCIP_CONS ** querycons,SCIP_CONS ** parallelconss,int * nparallelconss)13123 SCIP_RETCODE retrieveParallelConstraints(
13124    SCIP_HASHTABLE*       hashtable,          /**< hashtable containing linear constraints */
13125    SCIP_CONS**           querycons,          /**< pointer to linear constraint used to look for duplicates in the hash table;
13126                                               *   upon return will contain the constraint that should be kept */
13127    SCIP_CONS**           parallelconss,      /**< array to return constraints that are parallel to the given;
13128                                               *   these constraints where removed from the hashtable */
13129    int*                  nparallelconss      /**< pointer to return number of parallel constraints */
13130    )
13131 {
13132    SCIP_CONS* parallelcons;
13133    unsigned int querykey;
13134 
13135    *nparallelconss = 0;
13136    querykey = getParallelConsKey(*querycons);
13137 
13138    while( (parallelcons = (SCIP_CONS*)SCIPhashtableRetrieve(hashtable, (void*)(*querycons))) != NULL )
13139    {
13140       unsigned int conskey = getParallelConsKey(parallelcons);
13141 
13142       if( conskey < querykey )
13143       {
13144          parallelconss[(*nparallelconss)++] = *querycons;
13145          *querycons = parallelcons;
13146          querykey = conskey;
13147       }
13148       else
13149       {
13150          parallelconss[(*nparallelconss)++] = parallelcons;
13151       }
13152 
13153       /* if the constraint that just came out of the hash table is the one that is kept,
13154        * we do not need to look into the hashtable again, since the invariant is that
13155        * in the hashtable only pair-wise non-parallel constraints are contained.
13156        * For the original querycons, however, multiple constraints that compare equal (=parallel)
13157        * could be contained due to non-transitivity of the equality comparison.
13158        * Also we can return immediately, since parallelcons is already contained in the
13159        * hashtable and we do not need to remove and reinsert it.
13160        */
13161       if( *querycons == parallelcons )
13162          return SCIP_OKAY;
13163 
13164       /* remove parallelcons from the hashtable, since it will be replaced by querycons */
13165       SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) parallelcons) );
13166    }
13167 
13168    /* in debug mode we make sure, that the hashtable cannot contain a constraint that
13169     * comnpares equal to querycons at this point
13170     */
13171 #ifndef NDEBUG
13172    SCIP_CALL_ABORT( SCIPhashtableSafeInsert(hashtable, *querycons) );
13173 #else
13174    SCIP_CALL( SCIPhashtableInsert(hashtable, *querycons) );
13175 #endif
13176 
13177    return SCIP_OKAY;
13178 }
13179 
13180 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
13181  *  accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
13182  */
13183 static
detectRedundantConstraints(SCIP * scip,BMS_BLKMEM * blkmem,SCIP_CONS ** conss,int nconss,int * firstchange,SCIP_Bool * cutoff,int * ndelconss,int * nchgsides)13184 SCIP_RETCODE detectRedundantConstraints(
13185    SCIP*                 scip,               /**< SCIP data structure */
13186    BMS_BLKMEM*           blkmem,             /**< block memory */
13187    SCIP_CONS**           conss,              /**< constraint set */
13188    int                   nconss,             /**< number of constraints in constraint set */
13189    int*                  firstchange,        /**< pointer to store first changed constraint */
13190    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
13191    int*                  ndelconss,          /**< pointer to count number of deleted constraints */
13192    int*                  nchgsides           /**< pointer to count number of changed left/right hand sides */
13193    )
13194 {
13195    SCIP_HASHTABLE* hashtable;
13196    SCIP_CONS** parallelconss;
13197    int nparallelconss;
13198    int hashtablesize;
13199    int c;
13200 
13201    assert(scip != NULL);
13202    assert(blkmem != NULL);
13203    assert(conss != NULL);
13204    assert(firstchange != NULL);
13205    assert(cutoff != NULL);
13206    assert(ndelconss != NULL);
13207    assert(nchgsides != NULL);
13208 
13209    /* create a hash table for the constraint set */
13210    hashtablesize = nconss;
13211    SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
13212          hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
13213 
13214    SCIP_CALL( SCIPallocBufferArray(scip, &parallelconss, nconss) );
13215 
13216    /* check all constraints in the given set for redundancy */
13217    for( c = 0; c < nconss; ++c )
13218    {
13219       SCIP_CONS* cons0;
13220       SCIP_CONSDATA* consdata0;
13221 
13222       cons0 = conss[c];
13223 
13224       if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
13225          continue;
13226 
13227       /* check for interuption */
13228       if( c % 1000 == 0 && SCIPisStopped(scip) )
13229          break;
13230 
13231       /* sorts the constraint */
13232       consdata0 = SCIPconsGetData(cons0);
13233       assert(consdata0 != NULL);
13234       SCIP_CALL( consdataSort(scip, consdata0) );
13235       assert(consdata0->indexsorted);
13236 
13237       /* get constraints from current hash table with same variables as cons0 and with coefficients equal
13238        * to the ones of cons0 when both are scaled such that maxabsval is 1.0 and the coefficient of the
13239        * first variable is positive
13240        * Also inserts cons0 into the hashtable.
13241        */
13242       SCIP_CALL( retrieveParallelConstraints(hashtable, &cons0, parallelconss, &nparallelconss) );
13243 
13244       if( nparallelconss != 0 )
13245       {
13246          SCIP_Real lhs;
13247          SCIP_Real rhs;
13248 
13249          int i;
13250 
13251          /* cons0 may have been changed in retrieveParallelConstraints() */
13252          consdata0 = SCIPconsGetData(cons0);
13253 
13254          lhs = consdata0->lhs;
13255          rhs = consdata0->rhs;
13256 
13257          for( i = 0; i < nparallelconss; ++i )
13258          {
13259             SCIP_CONS* consdel;
13260             SCIP_CONSDATA* consdatadel;
13261             SCIP_Real scale;
13262 
13263             consdel = parallelconss[i];
13264             consdatadel = SCIPconsGetData(consdel);
13265 
13266             assert(SCIPconsIsActive(consdel));
13267             assert(!SCIPconsIsModifiable(consdel));
13268 
13269             /* constraint found: create a new constraint with same coefficients and best left and right hand side;
13270              * delete old constraints afterwards
13271              */
13272             assert(consdatadel != NULL);
13273             assert(consdata0->nvars >= 1 && consdata0->nvars == consdatadel->nvars);
13274 
13275             assert(consdatadel->indexsorted);
13276             assert(consdata0->vars[0] == consdatadel->vars[0]);
13277 
13278             scale = consdata0->vals[0] / consdatadel->vals[0];
13279             assert(scale != 0.0);
13280 
13281             /* in debug mode, check that all coefficients are equal with respect to epsilon
13282              * if the constraints are in equilibrium scale
13283              */
13284 #ifndef NDEBUG
13285             {
13286                int k;
13287                SCIP_Real scale0 = 1.0 / consdata0->maxabsval;
13288                SCIP_Real scaledel = COPYSIGN(1.0 / consdatadel->maxabsval, scale);
13289 
13290                for( k = 0; k < consdata0->nvars; ++k )
13291                {
13292                   assert(SCIPisEQ(scip, scale0 * consdata0->vals[k], scaledel * consdatadel->vals[k]));
13293                }
13294             }
13295 #endif
13296 
13297             if( scale > 0.0 )
13298             {
13299                /* the coefficients of both constraints are parallel with a positive scale */
13300                SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
13301                             SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13302                SCIPdebugPrintCons(scip, cons0, NULL);
13303                SCIPdebugPrintCons(scip, consdel, NULL);
13304 
13305                if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13306                   lhs = MAX(scale * consdatadel->lhs, lhs);
13307 
13308                if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13309                   rhs = MIN(scale * consdatadel->rhs, rhs);
13310             }
13311             else
13312             {
13313                /* the coefficients of both rows are negations */
13314                SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
13315                             SCIPconsGetName(cons0), SCIPconsGetName(consdel));
13316                SCIPdebugPrintCons(scip, cons0, NULL);
13317                SCIPdebugPrintCons(scip, consdel, NULL);
13318 
13319                if( ! SCIPisInfinity(scip, consdatadel->rhs) )
13320                   lhs = MAX(scale * consdatadel->rhs, lhs);
13321 
13322                if( ! SCIPisInfinity(scip, -consdatadel->lhs) )
13323                   rhs = MIN(scale * consdatadel->lhs, rhs);
13324             }
13325 
13326             /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13327             SCIP_CALL( SCIPupdateConsFlags(scip, cons0, consdel) );
13328 
13329             /* delete consdel */
13330             assert( ! consdata0->upgraded || consdatadel->upgraded );
13331             SCIP_CALL( SCIPdelCons(scip, consdel) );
13332             if( !consdatadel->upgraded )
13333                (*ndelconss)++;
13334          }
13335 
13336          if( SCIPisFeasLT(scip, rhs, lhs) )
13337          {
13338             SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13339             *cutoff = TRUE;
13340             break;
13341          }
13342 
13343          /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
13344          if( lhs > rhs )
13345          {
13346             rhs = (lhs + rhs)/2;
13347             lhs = rhs;
13348          }
13349 
13350          /* update lhs and rhs of cons0 */
13351          SCIP_CALL( chgLhs(scip, cons0, lhs) );
13352          SCIP_CALL( chgRhs(scip, cons0, rhs) );
13353 
13354          /* update the first changed constraint to begin the next aggregation round with */
13355          if( consdata0->changed && SCIPconsGetPos(cons0) < *firstchange )
13356             *firstchange = SCIPconsGetPos(cons0);
13357 
13358          assert(SCIPconsIsActive(cons0));
13359       }
13360    }
13361 #ifdef  SCIP_MORE_DEBUG
13362    SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
13363    SCIPhashtablePrintStatistics(hashtable, SCIPgetMessagehdlr(scip));
13364 #endif
13365 
13366    SCIPfreeBufferArray(scip, &parallelconss);
13367 
13368    /* free hash table */
13369    SCIPhashtableFree(&hashtable);
13370 
13371    return SCIP_OKAY;
13372 }
13373 
13374 /** compares constraint with all prior constraints for possible redundancy or aggregation,
13375  *  and removes or changes constraint accordingly
13376  */
13377 static
preprocessConstraintPairs(SCIP * scip,SCIP_CONS ** conss,int firstchange,int chkind,SCIP_Real maxaggrnormscale,SCIP_Bool * cutoff,int * ndelconss,int * nchgsides,int * nchgcoefs)13378 SCIP_RETCODE preprocessConstraintPairs(
13379    SCIP*                 scip,               /**< SCIP data structure */
13380    SCIP_CONS**           conss,              /**< constraint set */
13381    int                   firstchange,        /**< first constraint that changed since last pair preprocessing round */
13382    int                   chkind,             /**< index of constraint to check against all prior indices upto startind */
13383    SCIP_Real             maxaggrnormscale,   /**< maximal allowed relative gain in maximum norm for constraint aggregation */
13384    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
13385    int*                  ndelconss,          /**< pointer to count number of deleted constraints */
13386    int*                  nchgsides,          /**< pointer to count number of changed left/right hand sides */
13387    int*                  nchgcoefs           /**< pointer to count number of changed coefficients */
13388    )
13389 {
13390    SCIP_CONS* cons0;
13391    SCIP_CONSDATA* consdata0;
13392    int* commonidx0;
13393    int* commonidx1;
13394    int* diffidx0minus1;
13395    int* diffidx1minus0;
13396    uint64_t possignature0;
13397    uint64_t negsignature0;
13398    SCIP_Bool cons0changed;
13399    SCIP_Bool cons0isequality;
13400    int diffidx1minus0size;
13401    int c;
13402    SCIP_Real cons0lhs;
13403    SCIP_Real cons0rhs;
13404    SCIP_Bool cons0upgraded;
13405 
13406    assert(scip != NULL);
13407    assert(conss != NULL);
13408    assert(firstchange <= chkind);
13409    assert(cutoff != NULL);
13410    assert(ndelconss != NULL);
13411    assert(nchgsides != NULL);
13412    assert(nchgcoefs != NULL);
13413 
13414    /* get the constraint to be checked against all prior constraints */
13415    cons0 = conss[chkind];
13416    assert(cons0 != NULL);
13417    assert(SCIPconsIsActive(cons0));
13418    assert(!SCIPconsIsModifiable(cons0));
13419 
13420    consdata0 = SCIPconsGetData(cons0);
13421    assert(consdata0 != NULL);
13422    assert(consdata0->nvars >= 1);
13423    cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
13424 
13425    /* sort the constraint */
13426    SCIP_CALL( consdataSort(scip, consdata0) );
13427 
13428    /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
13429    consdataCalcSignatures(consdata0);
13430    possignature0 = consdata0->possignature;
13431    negsignature0 = consdata0->negsignature;
13432 
13433    /* get temporary memory for indices of common variables */
13434    SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
13435    SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
13436    SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
13437    SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
13438    diffidx1minus0size = consdata0->nvars;
13439 
13440    cons0lhs = consdata0->lhs;
13441    cons0rhs = consdata0->rhs;
13442    cons0upgraded = consdata0->upgraded;
13443 
13444    /* check constraint against all prior constraints */
13445    cons0changed = consdata0->changed;
13446    consdata0->changed = FALSE;
13447    for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
13448    {
13449       SCIP_CONS* cons1;
13450       SCIP_CONSDATA* consdata1;
13451       uint64_t possignature1;
13452       uint64_t negsignature1;
13453       SCIP_Bool cons0dominateslhs;
13454       SCIP_Bool cons1dominateslhs;
13455       SCIP_Bool cons0dominatesrhs;
13456       SCIP_Bool cons1dominatesrhs;
13457       SCIP_Bool cons1isequality;
13458       SCIP_Bool coefsequal;
13459       SCIP_Bool coefsnegated;
13460       SCIP_Bool tryaggregation;
13461       int nvarscommon;
13462       int nvars0minus1;
13463       int nvars1minus0;
13464       int commonidxweight;
13465       int diffidx0minus1weight;
13466       int diffidx1minus0weight;
13467       int v0;
13468       int v1;
13469 
13470       assert(cons0lhs == consdata0->lhs);  /*lint !e777*/
13471       assert(cons0rhs == consdata0->rhs);  /*lint !e777*/
13472       assert(cons0upgraded == consdata0->upgraded);
13473 
13474       cons1 = conss[c];
13475 
13476       /* cons1 has become inactive during presolving of constraint pairs */
13477       if( cons1 == NULL )
13478          continue;
13479 
13480       assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13481       assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13482 
13483       consdata1 = SCIPconsGetData(cons1);
13484       assert(consdata1 != NULL);
13485 
13486       /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13487          SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13488          SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13489 
13490       /* if both constraints didn't change since last pair processing, we can ignore the pair */
13491       if( !cons0changed && !consdata1->changed )
13492          continue;
13493 
13494       /* if both constraints are already upgraded, skip the pair;
13495        * because changes on these constraints cannot be applied to the instance anymore */
13496       if( cons0upgraded && consdata1->upgraded )
13497          continue;
13498 
13499       assert(consdata1->nvars >= 1);
13500 
13501       /* sort the constraint */
13502       SCIP_CALL( consdataSort(scip, consdata1) );
13503 
13504       /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13505       consdataCalcSignatures(consdata1);
13506       possignature1 = consdata1->possignature;
13507       negsignature1 = consdata1->negsignature;
13508 
13509       /* the signatures give a quick test to check for domination and equality of coefficients */
13510       coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13511       coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13512       cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13513          && ((possignature0 | possignature1) == possignature1)  /* possignature0 <= possignature1 (as bit vector) */
13514          && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13515       cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13516          && ((possignature0 | possignature1) == possignature0)  /* possignature0 >= possignature1 (as bit vector) */
13517          && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13518       cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13519          && ((possignature0 | possignature1) == possignature0)  /* possignature0 >= possignature1 (as bit vector) */
13520          && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13521       cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13522          && ((possignature0 | possignature1) == possignature1)  /* possignature0 <= possignature1 (as bit vector) */
13523          && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13524       cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13525       tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13526       if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13527          && !coefsequal && !coefsnegated && !tryaggregation )
13528          continue;
13529 
13530       /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13531       if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13532       {
13533          SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13534          diffidx1minus0size = consdata1->nvars;
13535       }
13536 
13537       /* check consdata0 against consdata1:
13538        * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13539        *   consdata0 dominates consdata1 w.r.t. left hand side
13540        * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13541        *   consdata0 dominates consdata1 w.r.t. right hand side
13542        * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13543        *   ranged row (or equality)
13544        * - if at least one constraint is an equality, count the weighted number of common variables W_c
13545        *   and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13546        *   where the weight of each variable depends on its type, such that aggregations in order to remove the
13547        *   number of continuous and integer variables are preferred:
13548        *   - if W_c > W_1, try to aggregate  consdata0 := a * consdata0 + b * consdata1  in order to decrease the
13549        *     variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13550        *     the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13551        *     to be positive to not switch the sense of the (in)equality cons0
13552        *   - if W_c > W_0, try to aggregate  consdata1 := a * consdata1 + b * consdata0  in order to decrease the
13553        *     variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13554        *     the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13555        *     to be positive to not switch the sense of the (in)equality cons1
13556        */
13557 
13558       /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13559       nvarscommon = 0;
13560       commonidxweight = 0;
13561       nvars0minus1 = 0;
13562       diffidx0minus1weight = 0;
13563       nvars1minus0 = 0;
13564       diffidx1minus0weight = 0;
13565       v0 = 0;
13566       v1 = 0;
13567       while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13568          && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13569             || coefsequal || coefsnegated || tryaggregation) )
13570       {
13571          SCIP_VAR* var;
13572          SCIP_Real val0;
13573          SCIP_Real val1;
13574          int varcmp;
13575 
13576          /* test, if variable appears in only one or in both constraints */
13577          if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13578             varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13579          else if( v0 < consdata0->nvars )
13580             varcmp = -1;
13581          else
13582             varcmp = +1;
13583 
13584          switch( varcmp )
13585          {
13586          case -1:
13587             /* variable doesn't appear in consdata1 */
13588             var = consdata0->vars[v0];
13589             val0 = consdata0->vals[v0];
13590             val1 = 0.0;
13591             if( tryaggregation )
13592             {
13593                diffidx0minus1[nvars0minus1] = v0;
13594                nvars0minus1++;
13595                diffidx0minus1weight += getVarWeight(var);
13596             }
13597             v0++;
13598             coefsequal = FALSE;
13599             coefsnegated = FALSE;
13600             break;
13601 
13602          case +1:
13603             /* variable doesn't appear in consdata0 */
13604             var = consdata1->vars[v1];
13605             val0 = 0.0;
13606             val1 = consdata1->vals[v1];
13607             if( tryaggregation )
13608             {
13609                diffidx1minus0[nvars1minus0] = v1;
13610                nvars1minus0++;
13611                diffidx1minus0weight += getVarWeight(var);
13612             }
13613             v1++;
13614             coefsequal = FALSE;
13615             coefsnegated = FALSE;
13616             break;
13617 
13618          case 0:
13619             /* variable appears in both constraints */
13620             assert(consdata0->vars[v0] == consdata1->vars[v1]);
13621             var = consdata0->vars[v0];
13622             val0 = consdata0->vals[v0];
13623             val1 = consdata1->vals[v1];
13624             if( tryaggregation )
13625             {
13626                commonidx0[nvarscommon] = v0;
13627                commonidx1[nvarscommon] = v1;
13628                nvarscommon++;
13629                commonidxweight += getVarWeight(var);
13630             }
13631             v0++;
13632             v1++;
13633             coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13634             coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13635             break;
13636 
13637          default:
13638             SCIPerrorMessage("invalid comparison result\n");
13639             SCIPABORT();
13640             var = NULL;
13641             val0 = 0.0;
13642             val1 = 0.0;
13643          }
13644          assert(var != NULL);
13645 
13646          /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13647          if( SCIPisGT(scip, val0, val1) )
13648          {
13649             if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13650             {
13651                cons0dominatesrhs = FALSE;
13652                cons1dominateslhs = FALSE;
13653             }
13654             if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13655             {
13656                cons0dominateslhs = FALSE;
13657                cons1dominatesrhs = FALSE;
13658             }
13659          }
13660          else if( SCIPisLT(scip, val0, val1) )
13661          {
13662             if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13663             {
13664                cons0dominateslhs = FALSE;
13665                cons1dominatesrhs = FALSE;
13666             }
13667             if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13668             {
13669                cons0dominatesrhs = FALSE;
13670                cons1dominateslhs = FALSE;
13671             }
13672          }
13673       }
13674 
13675       /* check for disaggregated ranged rows */
13676       if( coefsequal || coefsnegated )
13677       {
13678          SCIP_CONS* consstay;
13679          SCIP_CONS* consdel;
13680 #ifndef NDEBUG
13681          SCIP_CONSDATA* consdatastay;
13682 #endif
13683          SCIP_CONSDATA* consdatadel;
13684          SCIP_Real lhs;
13685          SCIP_Real rhs;
13686          int consinddel;
13687 
13688          /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13689           * best left and right hand sides; delete the old constraints afterwards
13690           */
13691          SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13692             SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13693          SCIPdebugPrintCons(scip, cons0, NULL);
13694          SCIPdebugPrintCons(scip, cons1, NULL);
13695 
13696          if( coefsequal )
13697          {
13698             /* the coefficients of both rows are equal */
13699             lhs = MAX(consdata0->lhs, consdata1->lhs);
13700             rhs = MIN(consdata0->rhs, consdata1->rhs);
13701          }
13702          else
13703          {
13704             /* the coefficients of both rows are negations */
13705             lhs = MAX(consdata0->lhs, -consdata1->rhs);
13706             rhs = MIN(consdata0->rhs, -consdata1->lhs);
13707          }
13708          if( SCIPisFeasLT(scip, rhs, lhs) )
13709          {
13710             SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13711             *cutoff = TRUE;
13712             break;
13713          }
13714 
13715          /* check which constraint has to stay;
13716           * changes applied to an upgraded constraint will not be considered in the instance */
13717          if( consdata0->upgraded )
13718          {
13719             assert(!consdata1->upgraded);
13720             consstay = cons1;
13721 #ifndef NDEBUG
13722             consdatastay = consdata1;
13723 #endif
13724 
13725             consdel = cons0;
13726             consdatadel = consdata0;
13727             consinddel = chkind;
13728          }
13729          else
13730          {
13731             consstay = cons0;
13732 #ifndef NDEBUG
13733             consdatastay = consdata0;
13734 #endif
13735 
13736             consdel = cons1;
13737             consdatadel = consdata1;
13738             consinddel = c;
13739          }
13740 
13741          /* update the sides of consstay */
13742          SCIP_CALL( chgLhs(scip, consstay, lhs) );
13743          SCIP_CALL( chgRhs(scip, consstay, rhs) );
13744          if( !consdata0->upgraded )
13745          {
13746             assert(consstay == cons0);
13747             cons0lhs = consdata0->lhs;
13748             cons0rhs = consdata0->rhs;
13749          }
13750 
13751          /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13752          SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13753 
13754          assert( !consdatastay->upgraded );
13755          /* delete consdel */
13756          SCIP_CALL( SCIPdelCons(scip, consdel) );
13757          conss[consinddel] = NULL;
13758          if( !consdatadel->upgraded )
13759             (*ndelconss)++;
13760          continue;
13761       }
13762 
13763       /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13764        * redundant
13765        */
13766       if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13767       {
13768          /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13769          SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13770             SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13771          SCIPdebugPrintCons(scip, cons0, NULL);
13772          SCIPdebugPrintCons(scip, cons1, NULL);
13773 
13774          /* check for infeasibility */
13775          if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13776          {
13777             SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13778             *cutoff = TRUE;
13779             break;
13780          }
13781 
13782          /* remove redundant left hand side */
13783          if( !SCIPisInfinity(scip, -consdata0->lhs) )
13784          {
13785             SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13786             cons0lhs = consdata0->lhs;
13787             cons0isequality = FALSE;
13788             if( !consdata0->upgraded )
13789             {
13790                /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13791                SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13792 
13793                (*nchgsides)++;
13794             }
13795          }
13796       }
13797       else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13798       {
13799          /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13800          SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13801             SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13802          SCIPdebugPrintCons(scip, cons1, NULL);
13803          SCIPdebugPrintCons(scip, cons0, NULL);
13804 
13805          /* check for infeasibility */
13806          if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13807          {
13808             SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13809             *cutoff = TRUE;
13810             break;
13811          }
13812 
13813          /* remove redundant left hand side */
13814          if( !SCIPisInfinity(scip, -consdata1->lhs) )
13815          {
13816             SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13817             cons1isequality = FALSE;
13818             if( !consdata1->upgraded )
13819             {
13820                /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13821                SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13822 
13823                (*nchgsides)++;
13824             }
13825          }
13826       }
13827       if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13828       {
13829          /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13830          SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13831             SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13832          SCIPdebugPrintCons(scip, cons0, NULL);
13833          SCIPdebugPrintCons(scip, cons1, NULL);
13834 
13835          /* check for infeasibility */
13836          if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13837          {
13838             SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13839             *cutoff = TRUE;
13840             break;
13841          }
13842 
13843          /* remove redundant right hand side */
13844          if( !SCIPisInfinity(scip, consdata0->rhs) )
13845          {
13846             SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13847             cons0rhs = consdata0->rhs;
13848             cons0isequality = FALSE;
13849             if( !consdata0->upgraded )
13850             {
13851                /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13852                SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13853 
13854                (*nchgsides)++;
13855             }
13856          }
13857       }
13858       else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13859       {
13860          /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13861          SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13862             SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13863          SCIPdebugPrintCons(scip, cons1, NULL);
13864          SCIPdebugPrintCons(scip, cons0, NULL);
13865 
13866          /* check for infeasibility */
13867          if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13868          {
13869             SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13870             *cutoff = TRUE;
13871             break;
13872          }
13873 
13874          /* remove redundant right hand side */
13875          if( !SCIPisInfinity(scip, consdata1->rhs) )
13876          {
13877             SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13878             cons1isequality = FALSE;
13879             if( !consdata1->upgraded )
13880             {
13881                /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13882                SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13883 
13884                (*nchgsides)++;
13885             }
13886          }
13887       }
13888 
13889       /* check for now redundant constraints */
13890       if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13891       {
13892          /* consdata0 became redundant */
13893          SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13894          SCIP_CALL( SCIPdelCons(scip, cons0) );
13895          conss[chkind] = NULL;
13896          if( !consdata0->upgraded )
13897          {
13898             /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13899             SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13900 
13901             (*ndelconss)++;
13902          }
13903          continue;
13904       }
13905       if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13906       {
13907          /* consdata1 became redundant */
13908          SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13909          SCIP_CALL( SCIPdelCons(scip, cons1) );
13910          conss[c] = NULL;
13911          if( !consdata1->upgraded )
13912          {
13913             /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13914             SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13915 
13916             (*ndelconss)++;
13917          }
13918          continue;
13919       }
13920 
13921       /* check, if we want to aggregate an (in)equality with an equality:
13922        *   consdata0 := a * consdata0 + b * consdata1  or  consdata1 := a * consdata1 + b * consdata0
13923        */
13924       if( tryaggregation )
13925       {
13926          SCIP_Bool aggregated;
13927 
13928          assert(consdata0->nvars == nvarscommon + nvars0minus1);
13929          assert(consdata1->nvars == nvarscommon + nvars1minus0);
13930 
13931          aggregated = FALSE;
13932          if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13933          {
13934             /* W_c > W_1: try to aggregate  consdata0 := a * consdata0 + b * consdata1 */
13935             SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13936                   nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13937                   nchgcoefs, &aggregated, cutoff) );
13938 
13939             if( *cutoff )
13940                break;
13941 
13942             /* update array of active constraints */
13943             if( aggregated )
13944             {
13945                assert(!SCIPconsIsActive(cons0));
13946                assert(SCIPconsIsActive(cons1));
13947                conss[chkind] = NULL;
13948             }
13949          }
13950          if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13951          {
13952             /* W_c > W_0: try to aggregate  consdata1 := a * consdata1 + b * consdata0 */
13953             SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13954                   nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13955                   nchgcoefs, &aggregated, cutoff) );
13956 
13957             if( *cutoff )
13958                break;
13959 
13960             /* update array of active constraints */
13961             if( aggregated )
13962             {
13963                assert(!SCIPconsIsActive(cons1));
13964                assert(SCIPconsIsActive(cons0));
13965                conss[c] = NULL;
13966             }
13967          }
13968       }
13969    }
13970 
13971    /* free temporary memory */
13972    SCIPfreeBufferArray(scip, &diffidx1minus0);
13973    SCIPfreeBufferArray(scip, &diffidx0minus1);
13974    SCIPfreeBufferArray(scip, &commonidx1);
13975    SCIPfreeBufferArray(scip, &commonidx0);
13976 
13977    return SCIP_OKAY;
13978 }
13979 
13980 /** do stuffing presolving on a single constraint */
13981 static
presolStuffing(SCIP * scip,SCIP_CONS * cons,SCIP_Bool singletonstuffing,SCIP_Bool singlevarstuffing,SCIP_Bool * cutoff,int * nfixedvars,int * nchgbds)13982 SCIP_RETCODE presolStuffing(
13983    SCIP*                 scip,               /**< SCIP data structure */
13984    SCIP_CONS*            cons,               /**< linear constraint */
13985    SCIP_Bool             singletonstuffing,  /**< should stuffing of singleton continuous variables be performed? */
13986    SCIP_Bool             singlevarstuffing,  /**< should single variable stuffing be performed, which tries to fulfill
13987                                               *   constraints using the cheapest variable? */
13988    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
13989    int*                  nfixedvars,         /**< pointer to count the total number of fixed variables */
13990    int*                  nchgbds             /**< pointer to count the total number of tightened bounds */
13991    )
13992 {
13993    SCIP_CONSDATA* consdata;
13994    SCIP_Real* ratios;
13995    int* varpos;
13996    SCIP_Bool* swapped;
13997    SCIP_VAR** vars;
13998    SCIP_Real* vals;
13999    SCIP_VAR* var;
14000    SCIP_Real lb;
14001    SCIP_Real ub;
14002    SCIP_Real minactivity;
14003    SCIP_Real maxactivity;
14004    SCIP_Real maxcondactivity;
14005    SCIP_Real mincondactivity;
14006    SCIP_Real rhs;
14007    SCIP_Real val;
14008    SCIP_Real obj;
14009    SCIP_Real factor;
14010    SCIP_Bool minactisrelax;
14011    SCIP_Bool maxactisrelax;
14012    SCIP_Bool isminsettoinfinity;
14013    SCIP_Bool ismaxsettoinfinity;
14014    SCIP_Bool tryfixing;
14015    int nsingletons;
14016    int idx;
14017    int v;
14018    int nvars;
14019 
14020    assert(scip != NULL);
14021    assert(cons != NULL);
14022    assert(nfixedvars != NULL);
14023 
14024    consdata = SCIPconsGetData(cons);
14025 
14026    /* we only want to run for inequalities */
14027    if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
14028       return SCIP_OKAY;
14029 
14030    if( singlevarstuffing )
14031    {
14032       consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
14033          &isminsettoinfinity, &ismaxsettoinfinity);
14034    }
14035    else
14036    {
14037       minactivity = SCIP_INVALID;
14038       maxactivity = SCIP_INVALID;
14039       isminsettoinfinity = FALSE;
14040       ismaxsettoinfinity = FALSE;
14041    }
14042 
14043    /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
14044     * the new maxactivity is minus the old minactivity then
14045     */
14046    if( SCIPisInfinity(scip, consdata->rhs) )
14047    {
14048       rhs = -consdata->lhs;
14049       factor = -1.0;
14050       maxactivity = -minactivity;
14051       ismaxsettoinfinity = isminsettoinfinity;
14052    }
14053    else
14054    {
14055       assert(SCIPisInfinity(scip, -consdata->lhs));
14056       rhs = consdata->rhs;
14057       factor = 1.0;
14058    }
14059 
14060    nvars = consdata->nvars;
14061    vars = consdata->vars;
14062    vals = consdata->vals;
14063 
14064    /* check for continuous singletons */
14065    if( singletonstuffing )
14066    {
14067       for( v = 0; v < nvars; ++v )
14068       {
14069          var = vars[v];
14070 
14071          if( (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) + SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL)) == 1
14072             && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
14073             break;
14074       }
14075    }
14076    else
14077       /* we don't want to go into the next block */
14078       v = nvars;
14079 
14080    /* a singleton was found -> perform singleton variable stuffing */
14081    if( v < nvars )
14082    {
14083       assert(singletonstuffing);
14084 
14085       SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
14086       SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
14087       SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
14088 
14089       tryfixing = TRUE;
14090       nsingletons = 0;
14091       mincondactivity = 0.0;
14092       maxcondactivity = 0.0;
14093 
14094       for( v = 0; v < nvars; ++v )
14095       {
14096          var = vars[v];
14097          lb = SCIPvarGetLbGlobal(var);
14098          ub = SCIPvarGetUbGlobal(var);
14099          obj = SCIPvarGetObj(var);
14100          val = factor * vals[v];
14101 
14102          assert(!SCIPisZero(scip, val));
14103 
14104          /* the variable is a singleton and continuous */
14105          if( (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) + SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL)) == 1
14106             && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
14107          {
14108             if( SCIPisNegative(scip, obj) && val > 0 )
14109             {
14110                /* case 1: obj < 0 and coef > 0 */
14111                if( SCIPisInfinity(scip, -lb) )
14112                {
14113                   tryfixing = FALSE;
14114                   break;
14115                }
14116 
14117                maxcondactivity += val * lb;
14118                mincondactivity += val * lb;
14119                swapped[v] = FALSE;
14120                ratios[nsingletons] = obj / val;
14121                varpos[nsingletons] = v;
14122                nsingletons++;
14123             }
14124             else if( SCIPisPositive(scip, obj) && val < 0 )
14125             {
14126                /* case 2: obj > 0 and coef < 0 */
14127                if( SCIPisInfinity(scip, ub) )
14128                {
14129                   tryfixing = FALSE;
14130                   break;
14131                }
14132                /* multiply column by (-1) to become case 1.
14133                 * now bounds are swapped: ub := -lb, lb := -ub
14134                 */
14135 
14136                maxcondactivity += val * ub;
14137                mincondactivity += val * ub;
14138                swapped[v] = TRUE;
14139                ratios[nsingletons] = obj / val;
14140                varpos[nsingletons] = v;
14141                nsingletons++;
14142             }
14143             else if( val > 0 )
14144             {
14145                /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
14146                 *  we only consider the lower bound for the constants
14147                 */
14148                assert(!SCIPisNegative(scip, obj));
14149 
14150                if( SCIPisInfinity(scip, -lb) )
14151                {
14152                   /* maybe unbounded */
14153                   tryfixing = FALSE;
14154                   break;
14155                }
14156 
14157                maxcondactivity += val * lb;
14158                mincondactivity += val * lb;
14159             }
14160             else
14161             {
14162                /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
14163                 * we only consider the upper bound for the constants
14164                 */
14165                assert(!SCIPisPositive(scip, obj));
14166                assert(val < 0);
14167 
14168                if( SCIPisInfinity(scip, ub) )
14169                {
14170                   /* maybe unbounded */
14171                   tryfixing = FALSE;
14172                   break;
14173                }
14174 
14175                maxcondactivity += val * ub;
14176                mincondactivity += val * ub;
14177             }
14178          }
14179          else
14180          {
14181             /* consider contribution of discrete variables, non-singleton
14182              * continuous variables and variables with more than one lock
14183              */
14184             if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14185             {
14186                tryfixing = FALSE;
14187                break;
14188             }
14189 
14190             if( val > 0 )
14191             {
14192                maxcondactivity += val * ub;
14193                mincondactivity += val * lb;
14194             }
14195             else
14196             {
14197                maxcondactivity += val * lb;
14198                mincondactivity += val * ub;
14199             }
14200          }
14201       }
14202       if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
14203       {
14204          SCIP_Real delta;
14205          SCIP_Bool tightened;
14206 #ifdef SCIP_DEBUG
14207          int oldnfixedvars = *nfixedvars;
14208          int oldnchgbds = *nchgbds;
14209 #endif
14210 
14211          SCIPsortRealInt(ratios, varpos, nsingletons);
14212 
14213          /* verify which singleton continuous variables can be fixed */
14214          for( v = 0; v < nsingletons; ++v )
14215          {
14216             idx = varpos[v];
14217             var = vars[idx];
14218             val = factor * vals[idx];
14219             lb = SCIPvarGetLbGlobal(var);
14220             ub = SCIPvarGetUbGlobal(var);
14221 
14222             assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
14223             assert((val < 0) == swapped[idx]);
14224             val = REALABS(val);
14225 
14226             /* stop fixing if variable bounds are not finite */
14227             if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
14228                break;
14229 
14230             assert((SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL)
14231                + SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL)) == 1);
14232             assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14233 
14234             /* calculate the change in the row activities if this variable changes
14235              * its value from its worst to its best bound
14236              */
14237             if( swapped[idx] )
14238                delta = -(lb - ub) * val;
14239             else
14240                delta =  (ub - lb) * val;
14241 
14242             assert(!SCIPisNegative(scip, delta));
14243 
14244             if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
14245             {
14246                if( swapped[idx] )
14247                {
14248                   SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14249                   SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14250                }
14251                else
14252                {
14253                   SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14254                   SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14255                }
14256 
14257                if( *cutoff )
14258                   break;
14259                if( tightened )
14260                {
14261                   (*nfixedvars)++;
14262                }
14263             }
14264             /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
14265              *        since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
14266              *        anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
14267              *        troubles in case of large bounds.
14268              */
14269             else if( SCIPisLE(scip, rhs, mincondactivity) )
14270             {
14271                if( swapped[idx] )
14272                {
14273                   SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
14274                   SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
14275                }
14276                else
14277                {
14278                   SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
14279                   SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
14280                }
14281 
14282                if( *cutoff )
14283                   break;
14284                if( tightened )
14285                {
14286                   (*nfixedvars)++;
14287                }
14288             }
14289 
14290             maxcondactivity += delta;
14291             mincondactivity += delta;
14292          }
14293 
14294 #ifdef SCIP_DEBUG
14295          if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
14296          {
14297             SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14298          }
14299 #endif
14300       }
14301 
14302       SCIPfreeBufferArray(scip, &swapped);
14303       SCIPfreeBufferArray(scip, &ratios);
14304       SCIPfreeBufferArray(scip, &varpos);
14305    }
14306 
14307    /* perform single-variable stuffing:
14308     * for a linear inequality
14309     *  a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
14310     * with a_i > 0 and objective coefficients c_i < 0,
14311     * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
14312     * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
14313     * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
14314     * is redundant.
14315     * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
14316     * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
14317     * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
14318     * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
14319     * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
14320     * upper bound.
14321     * Note that the others variables may have downlocks from other constraints, which we do not need to care
14322     * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
14323     * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
14324     * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
14325     * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
14326     * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
14327     * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
14328     * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
14329     * filling the remaining gap in the constraint with the next-best variable. For this, we check that
14330     * c_k * ceil((maxactivity - rhs)/val) is still better than
14331     * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
14332     * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
14333     * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
14334     * sign of coefficients in constraint and objective prevent the use of this method.
14335     */
14336    if( singlevarstuffing && !ismaxsettoinfinity )
14337    {
14338       SCIP_Real bestratio = -SCIPinfinity(scip);
14339       SCIP_Real secondbestratio = -SCIPinfinity(scip);
14340       SCIP_Real ratio;
14341       int bestindex = -1;
14342       int bestuplocks = 0;
14343       int bestdownlocks = 1;
14344       int downlocks;
14345       int uplocks;
14346       SCIPdebug( int oldnfixedvars = *nfixedvars; )
14347       SCIPdebug( int oldnchgbds = *nchgbds; )
14348 
14349       /* loop over all variables to identify the best and second-best ratio */
14350       for( v = 0; v < nvars; ++v )
14351       {
14352          var = vars[v];
14353          obj = SCIPvarGetObj(var);
14354          val = factor * vals[v];
14355 
14356          assert(!SCIPisZero(scip, val));
14357 
14358          ratio = obj / val;
14359 
14360          /* if both objective and constraint push the variable to the same direction, we can do nothing here */
14361          if( !SCIPisNegative(scip, ratio) )
14362          {
14363             bestindex = -1;
14364             break;
14365          }
14366 
14367          if( val > 0 )
14368          {
14369             downlocks = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL);
14370             uplocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
14371          }
14372          else
14373          {
14374             downlocks = SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL);
14375             uplocks = SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL);
14376          }
14377 
14378          /* better ratio, update best candidate
14379           * @todo use some tolerance
14380           * @todo check size of domain and updated ratio for integer variables already?
14381           */
14382          if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
14383                   || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
14384                      && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
14385          {
14386             /* best index becomes second-best*/
14387             if( bestindex != -1 )
14388             {
14389                /* second-best index must not have more than 1 uplock */
14390                if( bestuplocks > 1 )
14391                {
14392                   bestindex = -1;
14393                   break;
14394                }
14395                else
14396                {
14397                   secondbestratio = bestratio;
14398                }
14399             }
14400             bestdownlocks = downlocks;
14401             bestuplocks = uplocks;
14402             bestratio = ratio;
14403             bestindex = v;
14404 
14405             /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
14406              * if it is not the best, it has too many uplocks -> not applicable
14407              */
14408             if( bestdownlocks > 0 && bestuplocks > 1 )
14409             {
14410                bestindex = -1;
14411                break;
14412             }
14413          }
14414          else
14415          {
14416             /* non-best index must not have more than 1 uplock */
14417             if( uplocks > 1 )
14418             {
14419                bestindex = -1;
14420                break;
14421             }
14422             /* update second-best ratio */
14423             if( ratio > secondbestratio )
14424             {
14425                secondbestratio = ratio;
14426             }
14427          }
14428       }
14429 
14430       /* check if we can apply single variable stuffing */
14431       if( bestindex != -1 && bestdownlocks == 0 )
14432       {
14433          SCIP_Bool tightened = FALSE;
14434          SCIP_Real bounddelta;
14435 
14436          var = vars[bestindex];
14437          obj = SCIPvarGetObj(var);
14438          val = factor * vals[bestindex];
14439          lb = SCIPvarGetLbGlobal(var);
14440          ub = SCIPvarGetUbGlobal(var);
14441          tryfixing = TRUE;
14442 
14443          if( val < 0 )
14444          {
14445             assert(!SCIPisNegative(scip, obj));
14446 
14447             /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14448             if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
14449             {
14450                SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
14451                SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
14452                assert(SCIPisPositive(scip, activitydelta));
14453 
14454                tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
14455 
14456                bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
14457                assert(SCIPisPositive(scip, bounddelta));
14458             }
14459             else
14460                bounddelta = (maxactivity - rhs)/-val;
14461 
14462             tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14463 
14464             if( tryfixing )
14465             {
14466                assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
14467 
14468                if( SCIPisEQ(scip, lb + bounddelta, ub) )
14469                {
14470                   SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
14471                   SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
14472                }
14473                else
14474                {
14475                   SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14476                   SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14477                }
14478             }
14479          }
14480          else
14481          {
14482             assert(!SCIPisPositive(scip, obj));
14483 
14484             /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14485             if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS  && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14486             {
14487                SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14488                SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14489                assert(SCIPisPositive(scip, activitydelta));
14490 
14491                tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14492 
14493                bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14494                assert(SCIPisPositive(scip, bounddelta));
14495             }
14496             else
14497                bounddelta = (maxactivity - rhs)/val;
14498 
14499             tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14500 
14501             if( tryfixing )
14502             {
14503                assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
14504 
14505                if( SCIPisEQ(scip, ub - bounddelta, lb) )
14506                {
14507                   SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14508                   SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14509                }
14510                else
14511                {
14512                   SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14513                   SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14514                }
14515             }
14516          }
14517 
14518          if( *cutoff )
14519             return SCIP_OKAY;
14520          if( tightened )
14521          {
14522             if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14523                ++(*nfixedvars);
14524             else
14525                ++(*nchgbds);
14526 
14527             SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14528             for( v = 0; v < nvars; ++v )
14529             {
14530                SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]),
14531                   SCIPvarGetLbGlobal(vars[v]), SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]),
14532                   SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL),
14533                   SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL),
14534                   SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14535             }
14536             SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14537 
14538             for( v = 0; v < nvars; ++v )
14539             {
14540                if( v == bestindex )
14541                   continue;
14542 
14543                if( factor * vals[v] < 0 )
14544                {
14545                   assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14546                   SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n",
14547                      SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14548                   SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14549                }
14550                else
14551                {
14552                   assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) == 1);
14553                   SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n",
14554                      SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14555                   SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14556                }
14557 
14558                if( *cutoff )
14559                   return SCIP_OKAY;
14560                if( tightened )
14561                   ++(*nfixedvars);
14562             }
14563             SCIPdebug( SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds); )
14564          }
14565       }
14566    }
14567 
14568    return SCIP_OKAY;
14569 }
14570 
14571 /** applies full dual presolving on variables that only appear in linear constraints */
14572 static
fullDualPresolve(SCIP * scip,SCIP_CONS ** conss,int nconss,SCIP_Bool * cutoff,int * nchgbds)14573 SCIP_RETCODE fullDualPresolve(
14574    SCIP*                 scip,               /**< SCIP data structure */
14575    SCIP_CONS**           conss,              /**< constraint set */
14576    int                   nconss,             /**< number of constraints */
14577    SCIP_Bool*            cutoff,             /**< pointer to store TRUE, if a cutoff was found */
14578    int*                  nchgbds             /**< pointer to count the number of bound changes */
14579    )
14580 {
14581    SCIP_Real* redlb;
14582    SCIP_Real* redub;
14583    int* nlocksdown;
14584    int* nlocksup;
14585    SCIP_Bool* isimplint;
14586    SCIP_VAR** origvars;
14587    SCIP_VAR** vars;
14588    SCIP_VAR** conscontvars;
14589    int nvars;
14590    int nbinvars;
14591    int nintvars;
14592    int ncontvars;
14593    int v;
14594    int c;
14595 
14596    /* we calculate redundancy bounds with the following meaning:
14597     *   redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14598     *   redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14599     * then:
14600     *   c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14601     *   c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14602     */
14603 
14604    /* Additionally, we detect continuous variables that are implicitly integral.
14605     * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14606     * and all constraints (including the bounds as trivial constraints) in which:
14607     *   c_j > 0: the variable is down-locked,
14608     *   c_j < 0: the variable is up-locked,
14609     *   c_j = 0: the variable appears
14610     * have, apart from j, only integer variables with integral coefficients and integral sides.
14611     * This is because then, the value of the variable is either determined by one of its bounds or
14612     * by one of these constraints, and in all cases, the value of the variable is integral.
14613     */
14614 
14615    assert(scip != NULL);
14616    assert(nconss == 0 || conss != NULL);
14617    assert(nchgbds != NULL);
14618    assert(!SCIPinProbing(scip));
14619 
14620    /* get active variables */
14621    nvars = SCIPgetNVars(scip);
14622    origvars = SCIPgetVars(scip);
14623 
14624    /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14625    nbinvars = SCIPgetNBinVars(scip);
14626    if( nbinvars == nvars )
14627       return SCIP_OKAY;
14628 
14629    /* get number of continuous variables */
14630    ncontvars = SCIPgetNContVars(scip);
14631    nintvars = nvars - ncontvars;
14632 
14633    /* copy the variable array since this array might change during the curse of this algorithm */
14634    nvars = nvars - nbinvars;
14635    SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14636 
14637    /* allocate temporary memory */
14638    SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14639    SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14640    SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14641    SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14642    SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14643    SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14644 
14645    /* initialize redundancy bounds */
14646    for( v = 0; v < nvars; ++v )
14647    {
14648       assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14649       redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14650       redub[v] = SCIPvarGetUbGlobal(vars[v]);
14651    }
14652    BMSclearMemoryArray(nlocksdown, nvars);
14653    BMSclearMemoryArray(nlocksup, nvars);
14654 
14655    /* Initialize isimplint array: variable may be implied integer if rounded to their best bound they are integral.
14656     * We better not use SCIPisFeasIntegral() in these checks.
14657     */
14658    for( v = 0; v < ncontvars; v++ )
14659    {
14660       SCIP_VAR* var;
14661       SCIP_Real obj;
14662       SCIP_Real lb;
14663       SCIP_Real ub;
14664 
14665       var = vars[v + nintvars - nbinvars];
14666       lb = SCIPvarGetLbGlobal(var);
14667       ub = SCIPvarGetUbGlobal(var);
14668 
14669       obj = SCIPvarGetObj(var);
14670       if( SCIPisZero(scip, obj) )
14671          isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14672       else
14673       {
14674          if( SCIPisPositive(scip, obj) )
14675             isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14676          else
14677          {
14678             assert(SCIPisNegative(scip, obj));
14679             isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14680          }
14681       }
14682    }
14683 
14684    /* scan all constraints */
14685    for( c = 0; c < nconss; ++c )
14686    {
14687       /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14688        * part of checked disjunctions)
14689        */
14690       if( SCIPconsIsLocked(conss[c]) )
14691       {
14692          SCIP_CONSDATA* consdata;
14693          SCIP_Bool lhsexists;
14694          SCIP_Bool rhsexists;
14695          SCIP_Bool hasimpliedpotential;
14696          SCIP_Bool integralcoefs;
14697          int nlockspos;
14698          int contvarpos;
14699          int nconscontvars;
14700          int i;
14701 
14702          consdata = SCIPconsGetData(conss[c]);
14703          assert(consdata != NULL);
14704 
14705          /* get number of times the constraint was locked */
14706          nlockspos = SCIPconsGetNLocksPos(conss[c]);
14707 
14708          /* we do not want to include constraints with locked negation (this would be too weird) */
14709          if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14710          {
14711             /* mark all continuous variables as not being implicit integral */
14712             for( i = 0; i < consdata->nvars; ++i )
14713             {
14714                SCIP_VAR* var;
14715 
14716                var = consdata->vars[i];
14717                if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
14718                {
14719                   int contv;
14720                   contv = SCIPvarGetProbindex(var) - nintvars;
14721                   assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14722                   isimplint[contv] = FALSE;
14723                }
14724             }
14725             continue;
14726          }
14727 
14728          /* check for existing sides */
14729          lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14730          rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14731 
14732          /* count locks and update redundancy bounds */
14733          contvarpos = -1;
14734          nconscontvars = 0;
14735          hasimpliedpotential = FALSE;
14736          integralcoefs = !SCIPconsIsModifiable(conss[c]);
14737 
14738          for( i = 0; i < consdata->nvars; ++i )
14739          {
14740             SCIP_VAR* var;
14741             SCIP_Real val;
14742             SCIP_Real minresactivity;
14743             SCIP_Real maxresactivity;
14744             SCIP_Real newredlb;
14745             SCIP_Real newredub;
14746             SCIP_Bool minisrelax;
14747             SCIP_Bool maxisrelax;
14748             SCIP_Bool isminsettoinfinity;
14749             SCIP_Bool ismaxsettoinfinity;
14750             int arrayindex;
14751 
14752             var = consdata->vars[i];
14753             val = consdata->vals[i];
14754 
14755             /* check if still all integer variables have integral coefficients */
14756             if( SCIPvarIsIntegral(var) )
14757                integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14758 
14759             /* we do not need to process binary variables */
14760             if( SCIPvarIsBinary(var) )
14761                continue;
14762 
14763             if( SCIPconsIsModifiable(conss[c]) )
14764             {
14765                minresactivity = -SCIPinfinity(scip);
14766                maxresactivity =  SCIPinfinity(scip);
14767                isminsettoinfinity = TRUE;
14768                ismaxsettoinfinity = TRUE;
14769             }
14770             else
14771             {
14772                /* calculate residual activity bounds if variable would be fixed to zero */
14773                consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14774                   &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
14775 
14776                /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14777                 * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14778                 * This is needed, because we do not want to rely on relaxed finite resactivities.
14779                 */
14780                assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
14781 
14782                /* check minresactivity for reliability */
14783                if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14784                   consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14785 
14786                /* check maxresactivity for reliability */
14787                if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14788                   consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14789             }
14790 
14791             arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14792 
14793             assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14794 
14795             newredlb = redlb[arrayindex];
14796             newredub = redub[arrayindex];
14797             if( val > 0.0 )
14798             {
14799                if( lhsexists )
14800                {
14801                   /* lhs <= d*x + a*y, d > 0  ->  redundant in y if  x >= (lhs - min{a*y})/d */
14802                   nlocksdown[arrayindex] += nlockspos;
14803                   newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14804                }
14805                if( rhsexists )
14806                {
14807                   /* d*x + a*y <= rhs, d > 0  ->  redundant in y if  x <= (rhs - max{a*y})/d */
14808                   nlocksup[arrayindex] += nlockspos;
14809                   newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14810                }
14811             }
14812             else
14813             {
14814                if( lhsexists )
14815                {
14816                   /* lhs <= d*x + a*y, d < 0  ->  redundant in y if  x <= (lhs - min{a*y})/d */
14817                   nlocksup[arrayindex] += nlockspos;
14818                   newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14819                }
14820                if( rhsexists )
14821                {
14822                   /* d*x + a*y <= rhs, d < 0  ->  redundant in y if  x >= (rhs - max{a*y})/d */
14823                   nlocksdown[arrayindex] += nlockspos;
14824                   newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14825                }
14826             }
14827 
14828             /* if the variable is integer, we have to round the value to the next integral value */
14829             if( SCIPvarIsIntegral(var) )
14830             {
14831                if( !SCIPisInfinity(scip, newredlb) )
14832                   newredlb = SCIPceil(scip, newredlb);
14833                if( !SCIPisInfinity(scip, -newredub) )
14834                   newredub = SCIPfloor(scip, newredub);
14835             }
14836 
14837             /* update redundancy bounds */
14838             redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14839             redub[arrayindex] = MIN(redub[arrayindex], newredub);
14840 
14841             /* collect the continuous variables of the constraint */
14842             if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS )
14843             {
14844                int contv;
14845 
14846                assert(nconscontvars < ncontvars);
14847                contvarpos = i;
14848                conscontvars[nconscontvars] = var;
14849                nconscontvars++;
14850 
14851                contv = SCIPvarGetProbindex(var) - nintvars;
14852                assert(0 <= contv && contv < ncontvars);
14853                hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14854             }
14855          }
14856 
14857          /* update implied integer status of continuous variables */
14858          if( hasimpliedpotential )
14859          {
14860             if( nconscontvars > 1 || !integralcoefs )
14861             {
14862                /* there is more than one continuous variable or the integer variables have fractional coefficients:
14863                 * none of the continuous variables is implied integer
14864                 */
14865                for( i = 0; i < nconscontvars; i++ )
14866                {
14867                   int contv;
14868                   contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14869                   assert(0 <= contv && contv < ncontvars);
14870                   isimplint[contv] = FALSE;
14871                }
14872             }
14873             else
14874             {
14875                SCIP_VAR* var;
14876                SCIP_Real val;
14877                SCIP_Real absval;
14878                int contv;
14879 
14880                /* there is exactly one continuous variable and the integer variables have integral coefficients:
14881                 * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14882                 * side(s) of the constraint is integral
14883                 */
14884                assert(nconscontvars == 1);
14885                assert(0 <= contvarpos && contvarpos < consdata->nvars);
14886                var = consdata->vars[contvarpos];
14887                val = consdata->vals[contvarpos];
14888                contv = SCIPvarGetProbindex(var) - nintvars;
14889                assert(0 <= contv && contv < ncontvars);
14890                assert(isimplint[contv]);
14891 
14892                absval = REALABS(val);
14893                if( !SCIPisEQ(scip, absval, 1.0) )
14894                   isimplint[contv] =  FALSE;
14895                else
14896                {
14897                   SCIP_Real obj;
14898 
14899                   obj = SCIPvarGetObj(var);
14900                   if( obj * val >= 0.0 && lhsexists )
14901                   {
14902                      /* the variable may be blocked by the constraint's left hand side */
14903                      isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14904                   }
14905                   if( obj * val <= 0.0 && rhsexists )
14906                   {
14907                      /* the variable may be blocked by the constraint's left hand side */
14908                      isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14909                   }
14910                }
14911             }
14912          }
14913       }
14914    }
14915 
14916    /* check if any bounds can be tightened due to optimality */
14917    for( v = 0; v < nvars; ++v )
14918    {
14919       SCIP_VAR* var;
14920       SCIP_Real obj;
14921       SCIP_Bool infeasible;
14922       SCIP_Bool tightened;
14923 
14924       assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14925       assert(SCIPvarGetNLocksDownType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14926       assert(SCIPvarGetNLocksUpType(vars[v], SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14927 
14928       var = vars[v];
14929       obj = SCIPvarGetObj(var);
14930       if( obj >= 0.0 )
14931       {
14932          /* making the variable as small as possible does not increase the objective:
14933           * check if all down locks of the variables are due to linear constraints;
14934           * if largest bound to make constraints redundant is -infinity, we better do nothing for numerical reasons
14935           */
14936          if( SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
14937             && !SCIPisInfinity(scip, -redlb[v])
14938             && redlb[v] < SCIPvarGetUbGlobal(var) )
14939          {
14940             SCIP_Real ub;
14941 
14942             /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14943              *  -> tighten upper bound to x_v <= redlb[v]
14944              */
14945             SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14946                SCIPvarGetName(var), SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var),
14947                redlb[v]);
14948             SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14949             assert(!infeasible);
14950 
14951             ub = SCIPvarGetUbGlobal(var);
14952             redub[v] = MIN(redub[v], ub);
14953             if( tightened )
14954                (*nchgbds)++;
14955          }
14956       }
14957       if( obj <= 0.0 )
14958       {
14959          /* making the variable as large as possible does not increase the objective:
14960           * check if all up locks of the variables are due to linear constraints;
14961           * if smallest bound to make constraints redundant is +infinity, we better do nothing for numerical reasons
14962           */
14963          if( SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v]
14964             && !SCIPisInfinity(scip, redub[v])
14965             && redub[v] > SCIPvarGetLbGlobal(var) )
14966          {
14967             SCIP_Real lb;
14968 
14969             /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14970              *  -> tighten lower bound to x_v >= redub[v]
14971              */
14972             SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14973                SCIPvarGetName(var), SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var),
14974                redub[v]);
14975             SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14976             assert(!infeasible);
14977 
14978             lb = SCIPvarGetLbGlobal(var);
14979             redlb[v] = MAX(redlb[v], lb);
14980             if( tightened )
14981                (*nchgbds)++;
14982          }
14983       }
14984    }
14985 
14986    /* upgrade continuous variables to implied integers */
14987    for( v = nintvars - nbinvars; v < nvars; ++v )
14988    {
14989       SCIP_VAR* var;
14990       SCIP_Bool infeasible;
14991 
14992       var = vars[v];
14993       assert(var != NULL);
14994 
14995       assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14996       assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) >= nlocksdown[v]);
14997       assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) >= nlocksup[v]);
14998       assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
14999 
15000       /* we can only conclude implied integrality if the variable appears in no other constraint */
15001       if( isimplint[v - nintvars + nbinvars]
15002          && SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == nlocksdown[v]
15003          && SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == nlocksup[v] )
15004       {
15005          /* since we locally copied the variable array we can change the variable type immediately */
15006          SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
15007 
15008          if( infeasible )
15009          {
15010             SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
15011             *cutoff = TRUE;
15012 
15013             break;
15014          }
15015 
15016          SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
15017             SCIPvarGetName(var), SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var));
15018       }
15019    }
15020 
15021    /* free temporary memory */
15022    SCIPfreeBufferArray(scip, &conscontvars);
15023    SCIPfreeBufferArray(scip, &isimplint);
15024    SCIPfreeBufferArray(scip, &nlocksup);
15025    SCIPfreeBufferArray(scip, &nlocksdown);
15026    SCIPfreeBufferArray(scip, &redub);
15027    SCIPfreeBufferArray(scip, &redlb);
15028 
15029    SCIPfreeBufferArray(scip, &vars);
15030 
15031    return SCIP_OKAY;
15032 }
15033 
15034 /** helper function to enforce constraints */
15035 static
enforceConstraint(SCIP * scip,SCIP_CONSHDLR * conshdlr,SCIP_CONS ** conss,int nconss,int nusefulconss,SCIP_SOL * sol,SCIP_RESULT * result)15036 SCIP_RETCODE enforceConstraint(
15037    SCIP*                 scip,               /**< SCIP data structure */
15038    SCIP_CONSHDLR*        conshdlr,           /**< constraint handler */
15039    SCIP_CONS**           conss,              /**< constraints to process */
15040    int                   nconss,             /**< number of constraints */
15041    int                   nusefulconss,       /**< number of useful (non-obsolete) constraints to process */
15042    SCIP_SOL*             sol,                /**< solution to enforce (NULL for the LP solution) */
15043    SCIP_RESULT*          result              /**< pointer to store the result of the enforcing call */
15044    )
15045 {
15046    SCIP_CONSHDLRDATA* conshdlrdata;
15047    SCIP_Bool checkrelmaxabs;
15048    SCIP_Bool violated;
15049    SCIP_Bool cutoff = FALSE;
15050    int c;
15051 
15052    assert(scip != NULL);
15053    assert(conshdlr != NULL);
15054    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15055    assert(result != NULL);
15056 
15057    conshdlrdata = SCIPconshdlrGetData(conshdlr);
15058    assert(conshdlrdata != NULL);
15059 
15060    checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15061 
15062    SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
15063 
15064    /* check for violated constraints
15065     * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
15066     */
15067    *result = SCIP_FEASIBLE;
15068 
15069    /* check all useful linear constraints for feasibility */
15070    for( c = 0; c < nusefulconss; ++c )
15071    {
15072       SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15073 
15074       if( violated )
15075       {
15076          /* insert LP row as cut */
15077          SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15078          if ( cutoff )
15079             *result = SCIP_CUTOFF;
15080          else
15081             *result = SCIP_SEPARATED;
15082       }
15083    }
15084 
15085    /* check all obsolete linear constraints for feasibility */
15086    for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
15087    {
15088       SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
15089 
15090       if( violated )
15091       {
15092          /* insert LP row as cut */
15093          SCIP_CALL( addRelaxation(scip, conss[c], &cutoff) );
15094          if ( cutoff )
15095             *result = SCIP_CUTOFF;
15096          else
15097             *result = SCIP_SEPARATED;
15098       }
15099    }
15100 
15101    SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15102 
15103    return SCIP_OKAY;
15104 }
15105 
15106 /*
15107  * Callback methods of constraint handler
15108  */
15109 
15110 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
15111 static
SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)15112 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
15113 {  /*lint --e{715}*/
15114    assert(scip != NULL);
15115    assert(conshdlr != NULL);
15116    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15117 
15118    /* call inclusion method of constraint handler */
15119    SCIP_CALL( SCIPincludeConshdlrLinear(scip) );
15120 
15121    *valid = TRUE;
15122 
15123    return SCIP_OKAY;
15124 }
15125 
15126 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
15127 static
SCIP_DECL_CONSFREE(consFreeLinear)15128 SCIP_DECL_CONSFREE(consFreeLinear)
15129 {  /*lint --e{715}*/
15130    SCIP_CONSHDLRDATA* conshdlrdata;
15131 
15132    assert(scip != NULL);
15133    assert(conshdlr != NULL);
15134    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15135 
15136    /* free constraint handler data */
15137    conshdlrdata = SCIPconshdlrGetData(conshdlr);
15138    assert(conshdlrdata != NULL);
15139 
15140    conshdlrdataFree(scip, &conshdlrdata);
15141 
15142    SCIPconshdlrSetData(conshdlr, NULL);
15143 
15144    return SCIP_OKAY;
15145 }
15146 
15147 
15148 /** initialization method of constraint handler (called after problem was transformed) */
15149 static
SCIP_DECL_CONSINIT(consInitLinear)15150 SCIP_DECL_CONSINIT(consInitLinear)
15151 {
15152    SCIP_CONSHDLRDATA* conshdlrdata;
15153    int c;
15154 
15155    assert(scip != NULL);
15156 
15157    /* check for event handler */
15158    conshdlrdata = SCIPconshdlrGetData(conshdlr);
15159    assert(conshdlrdata != NULL);
15160    assert(conshdlrdata->eventhdlr != NULL);
15161    assert(nconss == 0 || conss != NULL);
15162 
15163    /* catch events for the constraints */
15164    for( c = 0; c < nconss; ++c )
15165    {
15166       /* catch all events */
15167       SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15168    }
15169 
15170    return SCIP_OKAY;
15171 }
15172 
15173 
15174 /** deinitialization method of constraint handler (called before transformed problem is freed) */
15175 static
SCIP_DECL_CONSEXIT(consExitLinear)15176 SCIP_DECL_CONSEXIT(consExitLinear)
15177 {
15178    SCIP_CONSHDLRDATA* conshdlrdata;
15179    int c;
15180 
15181    assert(scip != NULL);
15182 
15183    /* check for event handler */
15184    conshdlrdata = SCIPconshdlrGetData(conshdlr);
15185    assert(conshdlrdata != NULL);
15186    assert(conshdlrdata->eventhdlr != NULL);
15187 
15188    /* drop events for the constraints */
15189    for( c = nconss - 1; c >= 0; --c )
15190    {
15191       SCIP_CONSDATA* consdata;
15192 
15193       consdata = SCIPconsGetData(conss[c]);
15194       assert(consdata != NULL);
15195 
15196       if( consdata->eventdata != NULL )
15197       {
15198          /* drop all events */
15199          SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
15200          assert(consdata->eventdata == NULL);
15201       }
15202    }
15203 
15204    return SCIP_OKAY;
15205 }
15206 
15207 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15208 static
isRangedRow(SCIP * scip,SCIP_Real lhs,SCIP_Real rhs)15209 SCIP_Bool isRangedRow(
15210    SCIP*                 scip,               /**< SCIP data structure */
15211    SCIP_Real             lhs,                /**< left hand side */
15212    SCIP_Real             rhs                 /**< right hand side */
15213    )
15214 {
15215    assert(scip != NULL);
15216 
15217    return !(SCIPisEQ(scip, lhs, rhs) || SCIPisInfinity(scip, -lhs) || SCIPisInfinity(scip, rhs) );
15218 }
15219 
15220 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
15221 static
isFiniteNonnegativeIntegral(SCIP * scip,SCIP_Real x)15222 SCIP_Bool isFiniteNonnegativeIntegral(
15223    SCIP*                 scip,               /**< SCIP data structure */
15224    SCIP_Real             x                   /**< value */
15225    )
15226 {
15227    assert(scip != NULL);
15228 
15229    return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
15230 }
15231 
15232 /** performs linear constraint type classification as used for MIPLIB
15233  *
15234  *  iterates through all linear constraints and stores relevant statistics in the linear constraint statistics \p linconsstats.
15235  *
15236  *  @note only constraints are iterated that belong to the linear constraint handler. If the problem has been presolved already,
15237  *  constraints that were upgraded to more special types such as, e.g., varbound constraints, will not be shown correctly anymore.
15238  *  Similarly, if specialized constraints were created through the API, these are currently not present.
15239  */
SCIPclassifyConstraintTypesLinear(SCIP * scip,SCIP_LINCONSSTATS * linconsstats)15240 SCIP_RETCODE SCIPclassifyConstraintTypesLinear(
15241    SCIP*                 scip,               /**< SCIP data structure */
15242    SCIP_LINCONSSTATS*    linconsstats        /**< linear constraint type classification */
15243    )
15244 {
15245    int c;
15246    SCIP_CONSHDLR* conshdlr;
15247    SCIP_CONS** conss;
15248    int nconss;
15249 
15250    assert(scip != NULL);
15251    assert(linconsstats != NULL);
15252    conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
15253    assert(conshdlr != NULL);
15254 
15255    if( SCIPgetStage(scip) == SCIP_STAGE_PROBLEM )
15256    {
15257       conss = SCIPgetConss(scip);
15258       nconss = SCIPgetNConss(scip);
15259    }
15260    else
15261    {
15262       conss = SCIPconshdlrGetConss(conshdlr);
15263       nconss = SCIPconshdlrGetNConss(conshdlr);
15264    }
15265 
15266    /* reset linear constraint type classification */
15267    SCIPlinConsStatsReset(linconsstats);
15268 
15269    /* loop through all constraints */
15270    for( c = 0; c < nconss; c++ )
15271    {
15272       SCIP_CONS* cons;
15273       SCIP_CONSDATA* consdata;
15274       SCIP_Real lhs;
15275       SCIP_Real rhs;
15276       int i;
15277 
15278       /* get constraint */
15279       cons = conss[c];
15280       assert(cons != NULL);
15281 
15282       /* skip constraints that are not handled by the constraint handler */
15283       if( SCIPconsGetHdlr(cons) != conshdlr )
15284          continue;
15285 
15286       /* get constraint data */
15287       consdata = SCIPconsGetData(cons);
15288       assert(consdata != NULL);
15289       rhs = consdata->rhs;
15290       lhs = consdata->lhs;
15291 
15292       /* merge multiples and delete variables with zero coefficient */
15293       SCIP_CALL( mergeMultiples(scip, cons) );
15294       for( i = 0; i < consdata->nvars; i++ )
15295       {
15296          assert(!SCIPisZero(scip, consdata->vals[i]));
15297       }
15298 
15299       /* is constraint of type SCIP_CONSTYPE_EMPTY? */
15300       if( consdata->nvars == 0 )
15301       {
15302          SCIPdebugMsg(scip, "classified as EMPTY: ");
15303          SCIPdebugPrintCons(scip, cons, NULL);
15304          SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_EMPTY, 1);
15305 
15306          continue;
15307       }
15308 
15309       /* is constraint of type SCIP_CONSTYPE_FREE? */
15310       if( SCIPisInfinity(scip, rhs) && SCIPisInfinity(scip, -lhs) )
15311       {
15312          SCIPdebugMsg(scip, "classified as FREE: ");
15313          SCIPdebugPrintCons(scip, cons, NULL);
15314          SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_FREE, 1);
15315 
15316          continue;
15317       }
15318 
15319       /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
15320       if( consdata->nvars == 1 )
15321       {
15322          SCIPdebugMsg(scip, "classified as SINGLETON: ");
15323          SCIPdebugPrintCons(scip, cons, NULL);
15324          SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15325 
15326          continue;
15327       }
15328 
15329       /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
15330       if( consdata->nvars == 2 && SCIPisEQ(scip, lhs, rhs) )
15331       {
15332          SCIPdebugMsg(scip, "classified as AGGREGATION: ");
15333          SCIPdebugPrintCons(scip, cons, NULL);
15334          SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_AGGREGATION, 1);
15335 
15336          continue;
15337       }
15338 
15339       /* is constraint of type SCIP_CONSTYPE_{VARBOUND,PRECEDENCE}? */
15340       if( consdata->nvars == 2 )
15341       {
15342          SCIP_LINCONSTYPE constype;
15343 
15344          /* precedence constraints have the same coefficient, but with opposite sign for the same variable type */
15345          if( SCIPisEQ(scip, consdata->vals[0], -consdata->vals[1])
15346                && SCIPvarGetType(consdata->vars[0]) == SCIPvarGetType(consdata->vars[1]))
15347          {
15348             constype = SCIP_LINCONSTYPE_PRECEDENCE;
15349             SCIPdebugMsg(scip, "classified as PRECEDENCE: ");
15350          }
15351          else
15352          {
15353             constype = SCIP_LINCONSTYPE_VARBOUND;
15354             SCIPdebugMsg(scip, "classified as VARBOUND: ");
15355          }
15356          SCIPdebugPrintCons(scip, cons, NULL);
15357 
15358          SCIPlinConsStatsIncTypeCount(linconsstats, constype, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15359 
15360          continue;
15361       }
15362 
15363       /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
15364       {
15365          SCIP_Real scale;
15366          SCIP_Real b;
15367          SCIP_Bool unmatched;
15368          int nnegbinvars;
15369 
15370          unmatched = FALSE;
15371          nnegbinvars = 0;
15372 
15373          scale = REALABS(consdata->vals[0]);
15374 
15375          /* scan through variables and detect if all variables are binary and have a coefficient +/-1 */
15376          for( i = 0; i < consdata->nvars && !unmatched; i++ )
15377          {
15378             unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15379             unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15380             unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15381             unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
15382 
15383             if( consdata->vals[i] < 0.0 )
15384                nnegbinvars++;
15385          }
15386 
15387          if( !unmatched )
15388          {
15389             if( SCIPisEQ(scip, lhs, rhs) )
15390             {
15391                b = rhs/scale + nnegbinvars;
15392                if( SCIPisEQ(scip, 1.0, b) )
15393                {
15394                   SCIPdebugMsg(scip, "classified as SETPARTITION: ");
15395                   SCIPdebugPrintCons(scip, cons, NULL);
15396                   SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SETPARTITION, 1);
15397 
15398                   continue;
15399                }
15400                else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15401                {
15402                   SCIPdebugMsg(scip, "classified as CARDINALITY: ");
15403                   SCIPdebugPrintCons(scip, cons, NULL);
15404                   SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_CARDINALITY, 1);
15405 
15406                   continue;
15407                }
15408             }
15409 
15410             /* compute right hand side divided by scale */
15411             if( !SCIPisInfinity(scip, rhs) )
15412                b = rhs/scale + nnegbinvars;
15413             else
15414                b = SCIPinfinity(scip);
15415 
15416             if( SCIPisEQ(scip, 1.0, b) )
15417             {
15418                SCIPdebugMsg(scip, "classified as SETPACKING: ");
15419                SCIPdebugPrintCons(scip, cons, NULL);
15420                SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SETPACKING, 1);
15421 
15422                /* relax right hand side to prevent further classifications */
15423                rhs = SCIPinfinity(scip);
15424             }
15425             else if( !SCIPisInfinity(scip, b) && SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
15426             {
15427                SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
15428                SCIPdebugPrintCons(scip, cons, NULL);
15429 
15430                SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_INVKNAPSACK, 1);;
15431 
15432                /* relax right hand side to prevent further classifications */
15433                rhs = SCIPinfinity(scip);
15434             }
15435 
15436             if( !SCIPisInfinity(scip, lhs) )
15437                b = lhs/scale + nnegbinvars;
15438             else
15439                b = SCIPinfinity(scip);
15440 
15441             if( SCIPisEQ(scip, 1.0, b) )
15442             {
15443                SCIPdebugMsg(scip, "classified as SETCOVERING: ");
15444                SCIPdebugPrintCons(scip, cons, NULL);
15445                SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_SETCOVERING, 1);
15446 
15447                /* relax left hand side to prevent further classifications */
15448                lhs = -SCIPinfinity(scip);
15449             }
15450 
15451             /* if both sides are infinite at this point, no further classification is necessary for this constraint */
15452             if( SCIPisInfinity(scip, -lhs) && SCIPisInfinity(scip, rhs) )
15453                continue;
15454          }
15455       }
15456 
15457       /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
15458       /* @todo If coefficients or rhs are not integral, we currently do not check
15459        * if the constraint could be scaled (finitely), such that they are.
15460        */
15461       {
15462          SCIP_Real b;
15463          SCIP_Bool unmatched;
15464 
15465          b = rhs;
15466          unmatched = FALSE;
15467          for( i = 0; i < consdata->nvars && !unmatched; i++ )
15468          {
15469             unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15470             unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
15471             unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
15472             unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15473 
15474             if( SCIPisNegative(scip, consdata->vals[i]) )
15475                b -= consdata->vals[i];
15476          }
15477          unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15478 
15479          if( !unmatched )
15480          {
15481             if( SCIPisEQ(scip, lhs, rhs) )
15482             {
15483                SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
15484                SCIPdebugPrintCons(scip, cons, NULL);
15485 
15486                SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_EQKNAPSACK, 1);
15487 
15488                continue;
15489             }
15490             else
15491             {
15492                SCIP_Bool matched;
15493 
15494                matched = FALSE;
15495                for( i = 0; i < consdata->nvars && !matched; i++ )
15496                {
15497                   matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
15498                }
15499 
15500                SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
15501                SCIPdebugPrintCons(scip, cons, NULL);
15502                SCIPlinConsStatsIncTypeCount(linconsstats, matched ? SCIP_LINCONSTYPE_BINPACKING : SCIP_LINCONSTYPE_KNAPSACK, 1);
15503             }
15504 
15505             /* check if finite left hand side allows for a second classification, relax already used right hand side */
15506             if( SCIPisInfinity(scip, -lhs) )
15507                continue;
15508             else
15509                rhs = SCIPinfinity(scip);
15510          }
15511       }
15512 
15513       /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
15514       {
15515          SCIP_Real b;
15516          SCIP_Bool unmatched;
15517 
15518          unmatched = FALSE;
15519 
15520          b = rhs;
15521          unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
15522 
15523          for( i = 0; i < consdata->nvars && !unmatched; i++ )
15524          {
15525             unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
15526             unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
15527             unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
15528             unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
15529          }
15530 
15531          if( !unmatched )
15532          {
15533             SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
15534             SCIPdebugPrintCons(scip, cons, NULL);
15535             SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_INTKNAPSACK, 1);
15536 
15537             /* check if finite left hand side allows for a second classification, relax already used right hand side */
15538             if( SCIPisInfinity(scip, -lhs) )
15539                continue;
15540             else
15541                rhs = SCIPinfinity(scip);
15542          }
15543       }
15544 
15545       /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
15546       {
15547          SCIP_Bool unmatched;
15548 
15549          unmatched = FALSE;
15550          for( i = 0; i < consdata->nvars && !unmatched; i++ )
15551          {
15552             if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15553                && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15554                   || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15555                unmatched = TRUE;
15556          }
15557 
15558          if( !unmatched )
15559          {
15560             SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, lhs, rhs) ? 2 : 1);
15561             SCIPdebugPrintCons(scip, cons, NULL);
15562             SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15563 
15564             continue;
15565          }
15566       }
15567 
15568       /* no special structure detected */
15569       SCIPdebugMsg(scip, "classified as GENERAL: ");
15570       SCIPdebugPrintCons(scip, cons, NULL);
15571       SCIPlinConsStatsIncTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL, isRangedRow(scip, lhs, rhs) ? 2 : 1);
15572    }
15573 
15574    return SCIP_OKAY;
15575 }
15576 
15577 
15578 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15579 static
SCIP_DECL_CONSEXITPRE(consExitpreLinear)15580 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15581 {  /*lint --e{715}*/
15582    int c;
15583 #ifdef SCIP_STATISTIC
15584    SCIP_CONSHDLRDATA* conshdlrdata;
15585    int ngoodconss;
15586    int nallconss;
15587 #endif
15588 
15589    /* delete all linear constraints that were upgraded to a more specific constraint type;
15590     * make sure, only active variables remain in the remaining constraints
15591     */
15592    assert(scip != NULL);
15593 
15594 #ifdef SCIP_STATISTIC
15595    /* count number of well behaved linear constraints */
15596    conshdlrdata = SCIPconshdlrGetData(conshdlr);
15597    assert(conshdlrdata != NULL);
15598 
15599    ngoodconss = 0;
15600    nallconss = 0;
15601 
15602    for( c = 0; c < nconss; ++c )
15603    {
15604       SCIP_CONSDATA* consdata;
15605 
15606       if( SCIPconsIsDeleted(conss[c]) )
15607          continue;
15608 
15609       consdata = SCIPconsGetData(conss[c]);
15610       assert(consdata != NULL);
15611 
15612       if( consdata->upgraded )
15613          continue;
15614 
15615       nallconss++;
15616 
15617       consdataRecomputeMaxActivityDelta(scip, consdata);
15618 
15619       if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15620          ngoodconss++;
15621    }
15622    if( nallconss )
15623    {
15624       SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15625    }
15626 #endif
15627 
15628    for( c = 0; c < nconss; ++c )
15629    {
15630       SCIP_CONSDATA* consdata;
15631 
15632       if( SCIPconsIsDeleted(conss[c]) )
15633          continue;
15634 
15635       consdata = SCIPconsGetData(conss[c]);
15636       assert(consdata != NULL);
15637 
15638       if( consdata->upgraded )
15639       {
15640          /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15641           * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15642           */
15643          SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15644       }
15645       else
15646       {
15647          /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15648          SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15649       }
15650    }
15651 
15652    return SCIP_OKAY;
15653 }
15654 
15655 
15656 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15657 static
SCIP_DECL_CONSEXITSOL(consExitsolLinear)15658 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15659 {  /*lint --e{715}*/
15660    int c;
15661 
15662    assert(scip != NULL);
15663 
15664    /* release the rows of all constraints */
15665    for( c = 0; c < nconss; ++c )
15666    {
15667       SCIP_CONSDATA* consdata;
15668 
15669       consdata = SCIPconsGetData(conss[c]);
15670       assert(consdata != NULL);
15671 
15672       if( consdata->row != NULL )
15673       {
15674          SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15675       }
15676    }
15677 
15678    /* if this is a restart, convert cutpool rows into linear constraints */
15679    if( restart )
15680    {
15681       int ncutsadded;
15682 
15683       ncutsadded = 0;
15684 
15685       /* create out of all active cuts in cutpool linear constraints */
15686       SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15687 
15688       if( ncutsadded > 0 )
15689       {
15690          SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL,
15691             "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15692          /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15693           * line correctly
15694           */
15695          SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "\n");
15696       }
15697    }
15698 
15699    return SCIP_OKAY;
15700 }
15701 
15702 
15703 /** constraint deactivation notification method of constraint handler */
15704 static
SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)15705 SCIP_DECL_CONSDEACTIVE(consDeactiveLinear)
15706 {  /*lint --e{715}*/
15707    assert( cons != NULL );
15708 
15709    if( SCIPconsIsDeleted(cons) )
15710    {
15711       SCIP_CONSHDLRDATA* conshdlrdata;
15712       SCIP_CONSDATA* consdata;
15713 
15714       assert(scip != NULL);
15715       assert(conshdlr != NULL);
15716       assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15717 
15718       /* get constraint data */
15719       consdata = SCIPconsGetData(cons);
15720       assert(consdata != NULL);
15721 
15722       /* check for event handler */
15723       conshdlrdata = SCIPconshdlrGetData(conshdlr);
15724       assert(conshdlrdata != NULL);
15725       assert(conshdlrdata->eventhdlr != NULL);
15726 
15727       /* free event data */
15728       if( consdata->eventdata != NULL )
15729       {
15730          /* drop bound change events of variables */
15731          SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15732       }
15733       assert(consdata->eventdata == NULL);
15734    }
15735 
15736    return SCIP_OKAY;
15737 }
15738 
15739 
15740 /** frees specific constraint data */
15741 static
SCIP_DECL_CONSDELETE(consDeleteLinear)15742 SCIP_DECL_CONSDELETE(consDeleteLinear)
15743 {  /*lint --e{715}*/
15744    assert(scip != NULL);
15745    assert(conshdlr != NULL);
15746    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15747 
15748    if( (*consdata)->eventdata != NULL )
15749    {
15750       SCIP_CONSHDLRDATA* conshdlrdata;
15751 
15752       conshdlrdata = SCIPconshdlrGetData(conshdlr);
15753       assert(conshdlrdata != NULL);
15754 
15755       /* drop all events */
15756       SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15757       assert((*consdata)->eventdata == NULL);
15758    }
15759 
15760    /* free linear constraint */
15761    SCIP_CALL( consdataFree(scip, consdata) );
15762 
15763    return SCIP_OKAY;
15764 }
15765 
15766 
15767 /** transforms constraint data into data belonging to the transformed problem */
15768 static
SCIP_DECL_CONSTRANS(consTransLinear)15769 SCIP_DECL_CONSTRANS(consTransLinear)
15770 {  /*lint --e{715}*/
15771    SCIP_CONSDATA* sourcedata;
15772    SCIP_CONSDATA* targetdata;
15773 
15774    /*debugMsg(scip, "Trans method of linear constraints\n");*/
15775 
15776    assert(scip != NULL);
15777    assert(conshdlr != NULL);
15778    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15779    assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
15780    assert(sourcecons != NULL);
15781    assert(targetcons != NULL);
15782 
15783    sourcedata = SCIPconsGetData(sourcecons);
15784    assert(sourcedata != NULL);
15785    assert(sourcedata->row == NULL);  /* in original problem, there cannot be LP rows */
15786 
15787    /* create linear constraint data for target constraint */
15788    SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15789 
15790 #ifndef NDEBUG
15791    /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
15792    if( SCIPconsIsEnforced(sourcecons) || SCIPconsIsChecked(sourcecons) )
15793    {
15794       int n;
15795       for(n = targetdata->nvars - 1; n >= 0; --n )
15796          assert(!SCIPvarIsRelaxationOnly(targetdata->vars[n]));
15797    }
15798 #endif
15799 
15800    /* create target constraint */
15801    SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15802          SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15803          SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15804          SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15805          SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15806 
15807    return SCIP_OKAY;
15808 }
15809 
15810 
15811 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15812 static
SCIP_DECL_CONSINITLP(consInitlpLinear)15813 SCIP_DECL_CONSINITLP(consInitlpLinear)
15814 {  /*lint --e{715}*/
15815    int c;
15816 
15817    assert(scip != NULL);
15818    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15819 
15820    *infeasible = FALSE;
15821 
15822    for( c = 0; c < nconss && !(*infeasible); ++c )
15823    {
15824       assert(SCIPconsIsInitial(conss[c]));
15825       SCIP_CALL( addRelaxation(scip, conss[c], infeasible) );
15826    }
15827 
15828    return SCIP_OKAY;
15829 }
15830 
15831 
15832 /** separation method of constraint handler for LP solutions */
15833 static
SCIP_DECL_CONSSEPALP(consSepalpLinear)15834 SCIP_DECL_CONSSEPALP(consSepalpLinear)
15835 {  /*lint --e{715}*/
15836    SCIP_CONSHDLRDATA* conshdlrdata;
15837    SCIP_Real loclowerbound;
15838    SCIP_Real glblowerbound;
15839    SCIP_Real cutoffbound;
15840    SCIP_Real maxbound;
15841    SCIP_Bool separatecards;
15842    SCIP_Bool cutoff;
15843    int c;
15844    int depth;
15845    int nrounds;
15846    int maxsepacuts;
15847    int ncuts;
15848 
15849    assert(scip != NULL);
15850    assert(conshdlr != NULL);
15851    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15852    assert(result != NULL);
15853 
15854    conshdlrdata = SCIPconshdlrGetData(conshdlr);
15855    assert(conshdlrdata != NULL);
15856    depth = SCIPgetDepth(scip);
15857    nrounds = SCIPgetNSepaRounds(scip);
15858 
15859    /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15860 
15861    *result = SCIP_DIDNOTRUN;
15862 
15863    /* only call the separator a given number of times at each node */
15864    if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15865       || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15866       return SCIP_OKAY;
15867 
15868    /* get the maximal number of cuts allowed in a separation round */
15869    maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15870 
15871    /* check if we want to produce knapsack cardinality cuts at this node */
15872    loclowerbound = SCIPgetLocalLowerbound(scip);
15873    glblowerbound = SCIPgetLowerbound(scip);
15874    cutoffbound = SCIPgetCutoffbound(scip);
15875    maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
15876    separatecards = SCIPisLE(scip, loclowerbound, maxbound);
15877    separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
15878 
15879    *result = SCIP_DIDNOTFIND;
15880    ncuts = 0;
15881    cutoff = FALSE;
15882 
15883    /* check all useful linear constraints for feasibility */
15884    for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15885    {
15886       /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15887       SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
15888    }
15889 
15890    /* adjust return value */
15891    if( cutoff )
15892       *result = SCIP_CUTOFF;
15893    else if( ncuts > 0 )
15894       *result = SCIP_SEPARATED;
15895 
15896    /* combine linear constraints to get more cuts */
15897    /**@todo further cuts of linear constraints */
15898 
15899    return SCIP_OKAY;
15900 }
15901 
15902 
15903 /** separation method of constraint handler for arbitrary primal solutions */
15904 static
SCIP_DECL_CONSSEPASOL(consSepasolLinear)15905 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
15906 {  /*lint --e{715}*/
15907    SCIP_CONSHDLRDATA* conshdlrdata;
15908    int c;
15909    int depth;
15910    int nrounds;
15911    int maxsepacuts;
15912    int ncuts;
15913    SCIP_Bool cutoff;
15914 
15915    assert(scip != NULL);
15916    assert(conshdlr != NULL);
15917    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15918    assert(result != NULL);
15919 
15920    conshdlrdata = SCIPconshdlrGetData(conshdlr);
15921    assert(conshdlrdata != NULL);
15922    depth = SCIPgetDepth(scip);
15923    nrounds = SCIPgetNSepaRounds(scip);
15924 
15925    /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15926 
15927    *result = SCIP_DIDNOTRUN;
15928 
15929    /* only call the separator a given number of times at each node */
15930    if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15931       || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15932       return SCIP_OKAY;
15933 
15934    /* get the maximal number of cuts allowed in a separation round */
15935    maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15936 
15937    *result = SCIP_DIDNOTFIND;
15938    ncuts = 0;
15939    cutoff = FALSE;
15940 
15941    /* check all useful linear constraints for feasibility */
15942    for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15943    {
15944       /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15945       SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
15946    }
15947 
15948    /* adjust return value */
15949    if( cutoff )
15950       *result = SCIP_CUTOFF;
15951    else if( ncuts > 0 )
15952       *result = SCIP_SEPARATED;
15953 
15954    /* combine linear constraints to get more cuts */
15955    /**@todo further cuts of linear constraints */
15956 
15957    return SCIP_OKAY;
15958 }
15959 
15960 
15961 /** constraint enforcing method of constraint handler for LP solutions */
15962 static
SCIP_DECL_CONSENFOLP(consEnfolpLinear)15963 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
15964 {  /*lint --e{715}*/
15965    SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
15966 
15967    return SCIP_OKAY;
15968 }
15969 
15970 /** constraint enforcing method of constraint handler for relaxation solutions */
15971 static
SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)15972 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
15973 {  /*lint --e{715}*/
15974    SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
15975 
15976    return SCIP_OKAY;
15977 }
15978 
15979 /** constraint enforcing method of constraint handler for pseudo solutions */
15980 static
SCIP_DECL_CONSENFOPS(consEnfopsLinear)15981 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
15982 {  /*lint --e{715}*/
15983    SCIP_CONSHDLRDATA* conshdlrdata;
15984    SCIP_Bool checkrelmaxabs;
15985    SCIP_Bool violated;
15986    int c;
15987 
15988    assert(scip != NULL);
15989    assert(conshdlr != NULL);
15990    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15991    assert(result != NULL);
15992 
15993    conshdlrdata = SCIPconshdlrGetData(conshdlr);
15994    assert(conshdlrdata != NULL);
15995 
15996    checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15997 
15998    SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
15999 
16000    /* if the solution is infeasible anyway due to objective value, skip the enforcement */
16001    if( objinfeasible )
16002    {
16003       SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
16004 
16005       *result = SCIP_DIDNOTRUN;
16006       return SCIP_OKAY;
16007    }
16008 
16009    /* check all linear constraints for feasibility */
16010    violated = FALSE;
16011    for( c = 0; c < nconss && !violated; ++c )
16012    {
16013       SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
16014    }
16015 
16016    if( violated )
16017       *result = SCIP_INFEASIBLE;
16018    else
16019       *result = SCIP_FEASIBLE;
16020 
16021    SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
16022 
16023    return SCIP_OKAY;
16024 }
16025 
16026 
16027 /** feasibility check method of constraint handler for integral solutions */
16028 static
SCIP_DECL_CONSCHECK(consCheckLinear)16029 SCIP_DECL_CONSCHECK(consCheckLinear)
16030 {  /*lint --e{715}*/
16031    SCIP_CONSHDLRDATA* conshdlrdata;
16032    SCIP_Bool checkrelmaxabs;
16033    int c;
16034 
16035    assert(scip != NULL);
16036    assert(conshdlr != NULL);
16037    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16038    assert(result != NULL);
16039 
16040    *result = SCIP_FEASIBLE;
16041 
16042    conshdlrdata = SCIPconshdlrGetData(conshdlr);
16043    assert(conshdlrdata != NULL);
16044 
16045    checkrelmaxabs = conshdlrdata->checkrelmaxabs;
16046 
16047    /*debugMsg(scip, "Check method of linear constraints\n");*/
16048 
16049    /* check all linear constraints for feasibility */
16050    for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
16051    {
16052       SCIP_Bool violated = FALSE;
16053       SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
16054 
16055       if( violated )
16056       {
16057          *result = SCIP_INFEASIBLE;
16058 
16059          if( printreason )
16060          {
16061             SCIP_CONSDATA* consdata;
16062             SCIP_Real activity;
16063 
16064             consdata = SCIPconsGetData(conss[c]);
16065             assert( consdata != NULL);
16066 
16067             activity = consdataGetActivity(scip, consdata, sol);
16068 
16069             SCIP_CALL( consPrintConsSol(scip, conss[c], sol, NULL ) );
16070             SCIPinfoMessage(scip, NULL, ";\n");
16071 
16072             if( activity == SCIP_INVALID ) /*lint !e777*/
16073                SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
16074             else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
16075                SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
16076             else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
16077                SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
16078          }
16079       }
16080    }
16081 
16082    return SCIP_OKAY;
16083 }
16084 
16085 
16086 /** domain propagation method of constraint handler */
16087 static
SCIP_DECL_CONSPROP(consPropLinear)16088 SCIP_DECL_CONSPROP(consPropLinear)
16089 {  /*lint --e{715}*/
16090    SCIP_CONSHDLRDATA* conshdlrdata;
16091    SCIP_Bool rangedrowpropagation = FALSE;
16092    SCIP_Bool tightenbounds;
16093    SCIP_Bool cutoff;
16094 
16095    int nchgbds;
16096    int i;
16097 
16098    assert(scip != NULL);
16099    assert(conshdlr != NULL);
16100    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16101    assert(result != NULL);
16102 
16103    conshdlrdata = SCIPconshdlrGetData(conshdlr);
16104    assert(conshdlrdata != NULL);
16105 
16106    /*debugMsg(scip, "Prop method of linear constraints\n");*/
16107 
16108    /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
16109    if( SCIPinProbing(scip) )
16110       tightenbounds = TRUE;
16111    else
16112    {
16113       int depth;
16114       int propfreq;
16115       int tightenboundsfreq;
16116       int rangedrowfreq;
16117 
16118       depth = SCIPgetDepth(scip);
16119       propfreq = SCIPconshdlrGetPropFreq(conshdlr);
16120       tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
16121       tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
16122          && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
16123 
16124       /* check if we want to do ranged row propagation */
16125       rangedrowpropagation = conshdlrdata->rangedrowpropagation;
16126       rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
16127       rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
16128       rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
16129       rangedrowpropagation = rangedrowpropagation && (conshdlrdata->rangedrowfreq >= 0)
16130          && ((rangedrowfreq == 0 && depth == 0) || (rangedrowfreq >= 1 && (depth % rangedrowfreq == 0)));
16131    }
16132 
16133    cutoff = FALSE;
16134    nchgbds = 0;
16135 
16136    /* process constraints marked for propagation */
16137    for( i = 0; i < nmarkedconss && !cutoff; i++ )
16138    {
16139       SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
16140       SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
16141             conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
16142    }
16143 
16144    /* adjust result code */
16145    if( cutoff )
16146       *result = SCIP_CUTOFF;
16147    else if( nchgbds > 0 )
16148       *result = SCIP_REDUCEDDOM;
16149    else
16150       *result = SCIP_DIDNOTFIND;
16151 
16152    return SCIP_OKAY;
16153 }
16154 
16155 
16156 #define MAXCONSPRESOLROUNDS 10
16157 /** presolving method of constraint handler */
16158 static
SCIP_DECL_CONSPRESOL(consPresolLinear)16159 SCIP_DECL_CONSPRESOL(consPresolLinear)
16160 {  /*lint --e{715}*/
16161    SCIP_CONSHDLRDATA* conshdlrdata;
16162    SCIP_CONS* cons;
16163    SCIP_CONSDATA* consdata;
16164    SCIP_Real minactivity;
16165    SCIP_Real maxactivity;
16166    SCIP_Bool minactisrelax;
16167    SCIP_Bool maxactisrelax;
16168    SCIP_Bool isminsettoinfinity;
16169    SCIP_Bool ismaxsettoinfinity;
16170    SCIP_Bool cutoff;
16171    int oldnfixedvars;
16172    int oldnaggrvars;
16173    int oldnchgbds;
16174    int oldndelconss;
16175    int oldnupgdconss;
16176    int oldnchgcoefs;
16177    int oldnchgsides;
16178    int firstchange;
16179    int firstupgradetry;
16180    int c;
16181 
16182    assert(scip != NULL);
16183    assert(conshdlr != NULL);
16184    assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
16185    assert(result != NULL);
16186 
16187    /*debugMsg(scip, "Presol method of linear constraints\n");*/
16188 
16189    /* remember old preprocessing counters */
16190    cutoff = FALSE;
16191    oldnfixedvars = *nfixedvars;
16192    oldnaggrvars = *naggrvars;
16193    oldnchgbds = *nchgbds;
16194    oldndelconss = *ndelconss;
16195    oldnupgdconss = *nupgdconss;
16196    oldnchgcoefs = *nchgcoefs;
16197    oldnchgsides = *nchgsides;
16198 
16199    /* get constraint handler data */
16200    conshdlrdata = SCIPconshdlrGetData(conshdlr);
16201    assert(conshdlrdata != NULL);
16202 
16203    /* process single constraints */
16204    firstchange = INT_MAX;
16205    firstupgradetry = INT_MAX;
16206    for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
16207    {
16208       int npresolrounds;
16209       SCIP_Bool infeasible;
16210 
16211       infeasible = FALSE;
16212 
16213       cons = conss[c];
16214       assert(SCIPconsIsActive(cons));
16215       consdata = SCIPconsGetData(cons);
16216       assert(consdata != NULL);
16217 
16218       /* ensure that rhs >= lhs is satisfied without numerical tolerance */
16219       if( SCIPisEQ(scip, consdata->rhs, consdata->lhs) )
16220       {
16221          consdata->lhs = consdata->rhs;
16222          assert(consdata->row == NULL);
16223       }
16224 
16225       if( consdata->eventdata == NULL )
16226       {
16227          /* catch bound change events of variables */
16228          SCIP_CALL( consCatchAllEvents(scip, cons, conshdlrdata->eventhdlr) );
16229          assert(consdata->eventdata != NULL);
16230       }
16231 
16232       /* constraint should not be already presolved in the initial round */
16233       assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
16234       assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
16235       assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
16236       assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
16237 
16238       /* incorporate fixings and aggregations in constraint */
16239       SCIP_CALL( applyFixings(scip, cons, &infeasible) );
16240 
16241       if( infeasible )
16242       {
16243          SCIPdebugMsg(scip, " -> infeasible fixing\n");
16244          cutoff = TRUE;
16245          break;
16246       }
16247 
16248       assert(consdata->removedfixings);
16249 
16250       /* we can only presolve linear constraints, that are not modifiable */
16251       if( SCIPconsIsModifiable(cons) )
16252          continue;
16253 
16254       /* remember the first changed constraint to begin the next aggregation round with */
16255       if( firstchange == INT_MAX && consdata->changed )
16256          firstchange = c;
16257 
16258       /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16259       if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16260          firstupgradetry = c;
16261 
16262       /* check, if constraint is already preprocessed */
16263       if( consdata->presolved )
16264          continue;
16265 
16266       assert(SCIPconsIsActive(cons));
16267 
16268       SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
16269       SCIPdebugPrintCons(scip, cons, NULL);
16270 
16271       /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
16272        * to avoid nearly infinite cycling due to very small bound changes)
16273        */
16274       npresolrounds = 0;
16275       while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
16276       {
16277          assert(!cutoff);
16278          npresolrounds++;
16279 
16280          /* mark constraint being presolved and propagated */
16281          consdata->presolved = TRUE;
16282          SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
16283 
16284          /* normalize constraint */
16285          SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
16286 
16287          if( infeasible )
16288          {
16289             SCIPdebugMsg(scip, " -> infeasible normalization\n");
16290             cutoff = TRUE;
16291             break;
16292          }
16293 
16294          /* tighten left and right hand side due to integrality */
16295          SCIP_CALL( tightenSides(scip, cons, nchgsides, &infeasible) );
16296 
16297          if( infeasible )
16298          {
16299             SCIPdebugMsg(scip, " -> infeasibility detected during tightening sides\n");
16300             cutoff = TRUE;
16301             break;
16302          }
16303 
16304          /* check bounds */
16305          if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16306          {
16307             SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16308                SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16309             cutoff = TRUE;
16310             break;
16311          }
16312 
16313          /* tighten variable's bounds */
16314          SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
16315          if( cutoff )
16316             break;
16317 
16318          /* check for fixed variables */
16319          SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
16320          if( cutoff )
16321             break;
16322 
16323          /* check constraint for infeasibility and redundancy */
16324          consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax,
16325             &isminsettoinfinity, &ismaxsettoinfinity);
16326          if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
16327          {
16328             SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16329                SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16330             cutoff = TRUE;
16331             break;
16332          }
16333          else if( SCIPisFeasGE(scip, minactivity, consdata->lhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
16334          {
16335             SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16336                SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16337             SCIP_CALL( SCIPdelCons(scip, cons) );
16338             assert(!SCIPconsIsActive(cons));
16339 
16340             if( !consdata->upgraded )
16341                (*ndelconss)++;
16342             break;
16343          }
16344          else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasGE(scip, minactivity, consdata->lhs) )
16345          {
16346             SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16347                SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16348             SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
16349             if( !consdata->upgraded )
16350                (*nchgsides)++;
16351          }
16352          else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
16353          {
16354             SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
16355                SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
16356             SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
16357             if( !consdata->upgraded )
16358                (*nchgsides)++;
16359          }
16360          assert(consdata->nvars >= 1); /* otherwise, it should be redundant or infeasible */
16361 
16362          /* handle empty constraint */
16363          if( consdata->nvars == 0 )
16364          {
16365             if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16366             {
16367                SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16368                   SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16369                cutoff = TRUE;
16370             }
16371             else
16372             {
16373                SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16374                   SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16375                SCIP_CALL( SCIPdelCons(scip, cons) );
16376                assert(!SCIPconsIsActive(cons));
16377 
16378                if( !consdata->upgraded )
16379                   (*ndelconss)++;
16380             }
16381             break;
16382          }
16383 
16384          /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
16385          SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
16386 
16387          /* try to simplify inequalities */
16388          if( conshdlrdata->simplifyinequalities )
16389          {
16390             SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides, &cutoff) );
16391 
16392             if( cutoff )
16393                break;
16394          }
16395 
16396          /* aggregation variable in equations */
16397          if( conshdlrdata->aggregatevariables )
16398          {
16399             SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars) );
16400             if( cutoff )
16401                break;
16402          }
16403       }
16404 
16405       if( !cutoff && !SCIPisStopped(scip) )
16406       {
16407          /* perform ranged row propagation */
16408          if( conshdlrdata->rangedrowpropagation )
16409          {
16410             int lastnfixedvars;
16411 
16412             lastnfixedvars = *nfixedvars;
16413 
16414             SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
16415             if( !cutoff )
16416             {
16417                if( lastnfixedvars < *nfixedvars )
16418                {
16419                   SCIP_CALL( applyFixings(scip, cons, &cutoff) );
16420                }
16421             }
16422          }
16423 
16424          /* extract cliques from constraint */
16425          if( conshdlrdata->extractcliques && !cutoff && SCIPconsIsActive(cons) )
16426          {
16427             SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
16428                   nfixedvars, nchgbds, &cutoff) );
16429 
16430             /* check if the constraint got redundant or infeasible */
16431             if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
16432             {
16433                if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16434                {
16435                   SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16436                         SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16437                   cutoff = TRUE;
16438                }
16439                else
16440                {
16441                   SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16442                         SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16443                   SCIP_CALL( SCIPdelCons(scip, cons) );
16444                   assert(!SCIPconsIsActive(cons));
16445 
16446                   if( !consdata->upgraded )
16447                      (*ndelconss)++;
16448                }
16449             }
16450          }
16451 
16452          /* convert special equalities */
16453          if( !cutoff && SCIPconsIsActive(cons) )
16454          {
16455             SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
16456          }
16457 
16458          /* apply dual presolving for variables that appear in only one constraint */
16459          if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) )
16460          {
16461             SCIP_CALL( dualPresolve(scip, conshdlrdata, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
16462          }
16463 
16464          /* check if an inequality is parallel to the objective function */
16465          if( !cutoff && SCIPconsIsActive(cons) )
16466          {
16467             SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
16468          }
16469 
16470          /* remember the first changed constraint to begin the next aggregation round with */
16471          if( firstchange == INT_MAX && consdata->changed )
16472             firstchange = c;
16473 
16474          /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
16475          if( firstupgradetry == INT_MAX && !consdata->upgradetried )
16476             firstupgradetry = c;
16477       }
16478 
16479       /* singleton column stuffing */
16480       if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
16481          (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowStrongDualReds(scip) )
16482       {
16483          SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
16484                conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
16485 
16486          /* handle empty constraint */
16487          if( consdata->nvars == 0 )
16488          {
16489             if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
16490             {
16491                SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
16492                   SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16493                cutoff = TRUE;
16494             }
16495             else
16496             {
16497                SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
16498                   SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
16499                SCIP_CALL( SCIPdelCons(scip, cons) );
16500                assert(!SCIPconsIsActive(cons));
16501 
16502                if( !consdata->upgraded )
16503                   (*ndelconss)++;
16504             }
16505             break;
16506          }
16507       }
16508    }
16509 
16510    /* process pairs of constraints: check them for redundancy and try to aggregate them;
16511     * only apply this expensive procedure in exhaustive presolving timing
16512     */
16513    if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
16514    {
16515       assert(firstchange >= 0);
16516 
16517       if( firstchange < nconss && conshdlrdata->presolusehashing )
16518       {
16519          /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
16520          SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
16521                ndelconss, nchgsides) );
16522       }
16523 
16524       if( firstchange < nconss && conshdlrdata->presolpairwise )
16525       {
16526          SCIP_CONS** usefulconss;
16527          int nusefulconss;
16528          int firstchangenew;
16529          SCIP_Longint npaircomparisons;
16530 
16531          npaircomparisons = 0;
16532          oldndelconss = *ndelconss;
16533          oldnchgsides = *nchgsides;
16534          oldnchgcoefs = *nchgcoefs;
16535 
16536          /* allocate temporary memory */
16537          SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
16538 
16539          nusefulconss = 0;
16540          firstchangenew = -1;
16541          for( c = 0; c < nconss; ++c )
16542          {
16543             /* update firstchange */
16544             if( c == firstchange )
16545                firstchangenew = nusefulconss;
16546 
16547             /* ignore inactive and modifiable constraints */
16548             if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
16549                continue;
16550 
16551             usefulconss[nusefulconss] = conss[c];
16552             ++nusefulconss;
16553          }
16554          firstchange = firstchangenew;
16555          assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
16556 
16557          for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
16558          {
16559             /* constraint has become inactive or modifiable during pairwise presolving */
16560             if( usefulconss[c] == NULL )
16561                continue;
16562 
16563             npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
16564 
16565             assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
16566             SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
16567                   &cutoff, ndelconss, nchgsides, nchgcoefs) );
16568 
16569             if( npaircomparisons > conshdlrdata->nmincomparisons )
16570             {
16571                assert(npaircomparisons > 0);
16572                if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
16573                   break;
16574                oldndelconss = *ndelconss;
16575                oldnchgsides = *nchgsides;
16576                oldnchgcoefs = *nchgcoefs;
16577                npaircomparisons = 0;
16578             }
16579          }
16580          /* free temporary memory */
16581          SCIPfreeBufferArray(scip, &usefulconss);
16582       }
16583    }
16584 
16585    /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16586     * in linear constraints and we therefore have full information about it
16587     */
16588    if( !cutoff && firstupgradetry < nconss
16589       && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16590       && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16591       )
16592    {
16593       if( conshdlrdata->dualpresolving && SCIPallowStrongDualReds(scip) && !SCIPisStopped(scip) )
16594       {
16595          SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16596       }
16597    }
16598 
16599    /* try to upgrade constraints into a more specific constraint type;
16600     * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16601     * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16602     */
16603    if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16604    {
16605       for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16606       {
16607          cons = conss[c];
16608 
16609          /* don't upgrade modifiable constraints */
16610          if( SCIPconsIsModifiable(cons) )
16611             continue;
16612 
16613          consdata = SCIPconsGetData(cons);
16614          assert(consdata != NULL);
16615 
16616          /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16617          if( consdata->upgradetried )
16618             continue;
16619          /* @todo force that upgrade will be performed later? */
16620          if( !consdata->presolved )
16621             continue;
16622 
16623          consdata->upgradetried = TRUE;
16624          if( SCIPconsIsActive(cons) )
16625          {
16626             SCIP_CONS* upgdcons;
16627 
16628             SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16629             if( upgdcons != NULL )
16630             {
16631                /* add the upgraded constraint to the problem */
16632                SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16633                SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16634                (*nupgdconss)++;
16635 
16636                /* mark the linear constraint being upgraded and to be removed after presolving;
16637                 * don't delete it directly, because it may help to preprocess other linear constraints
16638                 */
16639                assert(!consdata->upgraded);
16640                consdata->upgraded = TRUE;
16641 
16642                /* delete upgraded inequalities immediately;
16643                 * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16644                 */
16645                if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16646                   || !conshdlrdata->presolpairwise
16647                   || (conshdlrdata->maxaggrnormscale == 0.0) )
16648                {
16649                   SCIP_CALL( SCIPdelCons(scip, cons) );
16650                }
16651             }
16652          }
16653       }
16654    }
16655 
16656    /* return the correct result code */
16657    if( cutoff )
16658       *result = SCIP_CUTOFF;
16659    else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16660       || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16661       *result = SCIP_SUCCESS;
16662    else
16663       *result = SCIP_DIDNOTFIND;
16664 
16665    return SCIP_OKAY;
16666 }
16667 
16668 
16669 /** propagation conflict resolving method of constraint handler */
16670 static
SCIP_DECL_CONSRESPROP(consRespropLinear)16671 SCIP_DECL_CONSRESPROP(consRespropLinear)
16672 {  /*lint --e{715}*/
16673    assert(scip != NULL);
16674    assert(cons != NULL);
16675    assert(result != NULL);
16676 
16677    SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16678 
16679    return SCIP_OKAY;
16680 }
16681 
16682 
16683 /** variable rounding lock method of constraint handler */
16684 static
SCIP_DECL_CONSLOCK(consLockLinear)16685 SCIP_DECL_CONSLOCK(consLockLinear)
16686 {  /*lint --e{715}*/
16687    SCIP_CONSDATA* consdata;
16688    SCIP_Bool haslhs;
16689    SCIP_Bool hasrhs;
16690    int i;
16691 
16692    assert(scip != NULL);
16693    assert(cons != NULL);
16694    consdata = SCIPconsGetData(cons);
16695    assert(consdata != NULL);
16696 
16697    haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16698    hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16699 
16700    /* update rounding locks of every single variable */
16701    for( i = 0; i < consdata->nvars; ++i )
16702    {
16703       if( SCIPisPositive(scip, consdata->vals[i]) )
16704       {
16705          if( haslhs )
16706          {
16707             SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16708          }
16709          if( hasrhs )
16710          {
16711             SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16712          }
16713       }
16714       else
16715       {
16716          if( haslhs )
16717          {
16718             SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlocksneg, nlockspos) );
16719          }
16720          if( hasrhs )
16721          {
16722             SCIP_CALL( SCIPaddVarLocksType(scip, consdata->vars[i], locktype, nlockspos, nlocksneg) );
16723          }
16724       }
16725    }
16726 
16727    return SCIP_OKAY;
16728 }
16729 
16730 
16731 /** variable deletion method of constraint handler */
16732 static
SCIP_DECL_CONSDELVARS(consDelvarsLinear)16733 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16734 {
16735    assert(scip != NULL);
16736    assert(conshdlr != NULL);
16737    assert(conss != NULL || nconss == 0);
16738 
16739    if( nconss > 0 )
16740    {
16741       SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16742    }
16743 
16744    return SCIP_OKAY;
16745 }
16746 
16747 /** constraint display method of constraint handler */
16748 static
SCIP_DECL_CONSPRINT(consPrintLinear)16749 SCIP_DECL_CONSPRINT(consPrintLinear)
16750 {  /*lint --e{715}*/
16751    assert(scip != NULL);
16752    assert(conshdlr != NULL);
16753    assert(cons != NULL);
16754 
16755    SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16756 
16757    return SCIP_OKAY;
16758 }
16759 
16760 /** constraint copying method of constraint handler */
16761 static
SCIP_DECL_CONSCOPY(consCopyLinear)16762 SCIP_DECL_CONSCOPY(consCopyLinear)
16763 {  /*lint --e{715}*/
16764    SCIP_VAR** sourcevars;
16765    SCIP_Real* sourcecoefs;
16766    const char* consname;
16767    int nvars;
16768 
16769    assert(scip != NULL);
16770    assert(sourcescip != NULL);
16771    assert(sourcecons != NULL);
16772 
16773    /* get variables and coefficients of the source constraint */
16774    sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16775    sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16776    nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16777 
16778    if( name != NULL )
16779       consname = name;
16780    else
16781       consname = SCIPconsGetName(sourcecons);
16782 
16783    SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16784          SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16785          initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16786    assert(cons != NULL || *valid == FALSE);
16787 
16788    /* @todo should also the checkabsolute flag of the constraint be copied? */
16789 
16790    return SCIP_OKAY;
16791 }
16792 
16793 /** find operators '<=', '==', '>=', [free] in input string and return those places
16794  *
16795  *  There should only be one operator, except for ranged rows for which exactly two operators '<=' must be present.
16796  */
16797 static
findOperators(const char * str,char ** firstoperator,char ** secondoperator,SCIP_Bool * success)16798 void findOperators(
16799    const char*           str,                /**< null terminated input string */
16800    char**                firstoperator,      /**< pointer to store the string starting at the first operator */
16801    char**                secondoperator,     /**< pointer to store the string starting at the second operator */
16802    SCIP_Bool*            success             /**< pointer to store if the line contains a valid operator order */
16803    )
16804 {
16805    char* curr;
16806 
16807    assert(str != NULL);
16808    assert(firstoperator != NULL);
16809    assert(secondoperator != NULL);
16810 
16811    *firstoperator = NULL;
16812    *secondoperator = NULL;
16813 
16814    curr = (char*)str;
16815    *success = TRUE;
16816 
16817    /* loop over the input string to find all operators */
16818    while( *curr && *success )
16819    {
16820       SCIP_Bool found = FALSE;
16821       int increment = 1;
16822 
16823       /* try if we found a possible operator */
16824       switch( *curr )
16825       {
16826       case '<':
16827       case '=':
16828       case '>':
16829 
16830          /* check if the two characters curr[0,1] form an operator together */
16831          if( curr[1] == '=' )
16832          {
16833             found = TRUE;
16834 
16835             /* update increment to continue after this operator */
16836             increment = 2;
16837          }
16838          break;
16839       case '[':
16840          if( strncmp(curr, "[free]", 6) == 0 )
16841          {
16842             found = TRUE;
16843 
16844             /* update increment to continue after this operator */
16845             increment = 6;
16846          }
16847          break;
16848       default:
16849          break;
16850       }
16851 
16852       /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16853       if( found )
16854       {
16855          if( *firstoperator == NULL )
16856          {
16857             *firstoperator = curr;
16858          }
16859          else
16860          {
16861             if( *secondoperator != NULL )
16862             {
16863                SCIPerrorMessage("Found more than two operators in line %s\n", str);
16864                *success = FALSE;
16865             }
16866             else if( strncmp(*firstoperator, "<=", 2) != 0 )
16867             {
16868                SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16869                *success = FALSE;
16870             }
16871             else if( strncmp(curr, "<=", 2) != 0 )
16872             {
16873                SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
16874                *success = FALSE;
16875             }
16876 
16877             *secondoperator = curr;
16878          }
16879       }
16880 
16881       curr += increment;
16882    }
16883 
16884    /* check if we did find at least one operator */
16885    if( *success )
16886    {
16887       if( *firstoperator == NULL )
16888       {
16889          SCIPerrorMessage("Could not find any operator in line %s\n", str);
16890          *success = FALSE;
16891       }
16892    }
16893 }
16894 
16895 /** constraint parsing method of constraint handler */
16896 static
SCIP_DECL_CONSPARSE(consParseLinear)16897 SCIP_DECL_CONSPARSE(consParseLinear)
16898 {  /*lint --e{715}*/
16899    SCIP_VAR** vars;
16900    SCIP_Real* coefs;
16901    int        nvars;
16902    int        coefssize;
16903    int        requsize;
16904    SCIP_Real  lhs;
16905    SCIP_Real  rhs;
16906    char*      endptr;
16907    char*      firstop;
16908    char*      secondop;
16909    SCIP_Bool  operatorsuccess;
16910    char*      lhsstrptr;
16911    char*      rhsstrptr;
16912    char*      varstrptr;
16913 
16914    assert(scip != NULL);
16915    assert(success != NULL);
16916    assert(str != NULL);
16917    assert(name != NULL);
16918    assert(cons != NULL);
16919 
16920    /* set left and right hand side to their default values */
16921    lhs = -SCIPinfinity(scip);
16922    rhs =  SCIPinfinity(scip);
16923 
16924    (*success) = FALSE;
16925 
16926    /* return of string empty */
16927    if( !*str )
16928       return SCIP_OKAY;
16929 
16930    /* ignore whitespace */
16931    while( isspace((unsigned char)*str) )
16932       ++str;
16933 
16934    /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
16935     * and the special word [free]
16936     */
16937    findOperators(str, &firstop, &secondop, &operatorsuccess);
16938 
16939    /* if the grammar is not valid for parsing a linear constraint, return */
16940    if( ! operatorsuccess )
16941       return SCIP_OKAY;
16942 
16943    varstrptr = (char *)str;
16944    lhsstrptr = rhsstrptr = NULL;
16945    assert(firstop != NULL);
16946 
16947    /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
16948    switch( *firstop )
16949    {
16950       case '<':
16951          assert(firstop[1] == '=');
16952          /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
16953          if( secondop != NULL )
16954          {
16955             assert(secondop[0] == '<' && secondop[1] == '=');
16956             lhsstrptr = (char *)str;
16957             varstrptr = firstop + 2;
16958             rhsstrptr = secondop + 2;
16959          }
16960          else
16961          {
16962             /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
16963             lhsstrptr = NULL;
16964             varstrptr = (char *)str;
16965             rhsstrptr = firstop + 2;
16966          }
16967          break;
16968       case '>':
16969          assert(firstop[1] == '=');
16970          assert(secondop == NULL);
16971          /* we have a_1 x_1 + ... + a_n x_n >= lhs */
16972          lhsstrptr = firstop + 2;
16973          break;
16974       case '=':
16975          assert(firstop[1] == '=');
16976          assert(secondop == NULL);
16977          /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
16978          rhsstrptr = firstop + 2;
16979          lhsstrptr = firstop + 2;
16980          break;
16981       case '[':
16982          assert(strncmp(firstop, "[free]", 6) == 0);
16983          assert(secondop == NULL);
16984          /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
16985          break;
16986       default:
16987          /* it should not be possible that a different character appears in that position */
16988          SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
16989          return SCIP_READERROR;
16990    }
16991 
16992    /* parse left hand side, if necessary */
16993    if( lhsstrptr != NULL )
16994    {
16995       if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
16996       {
16997          SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
16998          return SCIP_OKAY;
16999       }
17000 
17001       /* in case of an equation, assign the left also to the right hand side */
17002       if( rhsstrptr == lhsstrptr )
17003          rhs = lhs;
17004    }
17005 
17006    /* parse right hand side, if different from left hand side */
17007    if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
17008    {
17009       if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
17010       {
17011          SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
17012          return SCIP_OKAY;
17013       }
17014    }
17015 
17016    /* initialize buffers for storing the variables and coefficients */
17017    coefssize = 100;
17018    SCIP_CALL( SCIPallocBufferArray(scip, &vars,  coefssize) );
17019    SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
17020 
17021    assert(varstrptr != NULL);
17022 
17023    /* parse linear sum to get variables and coefficients */
17024    SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17025 
17026    if( *success && requsize > coefssize )
17027    {
17028       /* realloc buffers and try again */
17029       coefssize = requsize;
17030       SCIP_CALL( SCIPreallocBufferArray(scip, &vars,  coefssize) );
17031       SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
17032 
17033       SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
17034       assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
17035    }
17036 
17037    if( !*success )
17038    {
17039       SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
17040    }
17041    else
17042    {
17043       SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17044             initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17045    }
17046 
17047    SCIPfreeBufferArray(scip, &coefs);
17048    SCIPfreeBufferArray(scip, &vars);
17049 
17050    return SCIP_OKAY;
17051 }
17052 
17053 
17054 /** constraint method of constraint handler which returns the variables (if possible) */
17055 static
SCIP_DECL_CONSGETVARS(consGetVarsLinear)17056 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
17057 {  /*lint --e{715}*/
17058    SCIP_CONSDATA* consdata;
17059 
17060    consdata = SCIPconsGetData(cons);
17061    assert(consdata != NULL);
17062 
17063    if( varssize < consdata->nvars )
17064       (*success) = FALSE;
17065    else
17066    {
17067       assert(vars != NULL);
17068 
17069       BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
17070       (*success) = TRUE;
17071    }
17072 
17073    return SCIP_OKAY;
17074 }
17075 
17076 /**! [Callback for the number of variables]*/
17077 /** constraint method of constraint handler which returns the number of variables (if possible) */
17078 static
SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)17079 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
17080 {  /*lint --e{715}*/
17081    SCIP_CONSDATA* consdata;
17082 
17083    consdata = SCIPconsGetData(cons);
17084    assert(consdata != NULL);
17085 
17086    (*nvars) = consdata->nvars;
17087    (*success) = TRUE;
17088 
17089    return SCIP_OKAY;
17090 }
17091 /**! [Callback for the number of variables]*/
17092 
17093 /*
17094  * Callback methods of event handler
17095  */
17096 
17097 /** execution method of event handler */
17098 static
SCIP_DECL_EVENTEXEC(eventExecLinear)17099 SCIP_DECL_EVENTEXEC(eventExecLinear)
17100 {  /*lint --e{715}*/
17101    SCIP_CONS* cons;
17102    SCIP_CONSDATA* consdata;
17103    SCIP_VAR* var;
17104    SCIP_EVENTTYPE eventtype;
17105 
17106    assert(scip != NULL);
17107    assert(eventhdlr != NULL);
17108    assert(eventdata != NULL);
17109    assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
17110    assert(event != NULL);
17111 
17112    cons = eventdata->cons;
17113    assert(cons != NULL);
17114    consdata = SCIPconsGetData(cons);
17115    assert(consdata != NULL);
17116 
17117    /* we can skip events droped for deleted constraints */
17118    if( SCIPconsIsDeleted(cons) )
17119       return SCIP_OKAY;
17120 
17121    eventtype = SCIPeventGetType(event);
17122    var = SCIPeventGetVar(event);
17123 
17124    if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
17125    {
17126       SCIP_Real oldbound;
17127       SCIP_Real newbound;
17128       SCIP_Real val;
17129       int varpos;
17130 
17131       varpos = eventdata->varpos;
17132       assert(0 <= varpos && varpos < consdata->nvars);
17133       oldbound = SCIPeventGetOldbound(event);
17134       newbound = SCIPeventGetNewbound(event);
17135       assert(var != NULL);
17136       assert(consdata->vars[varpos] == var);
17137       val = consdata->vals[varpos];
17138 
17139       /* we only need to update the activities if the constraint is active,
17140        * otherwise we mark them to be invalid
17141        */
17142       if( SCIPconsIsActive(cons) )
17143       {
17144          /* update the activity values */
17145          if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
17146             consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
17147          else
17148          {
17149             assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
17150             consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
17151          }
17152       }
17153       else
17154          consdataInvalidateActivities(consdata);
17155 
17156       consdata->presolved = FALSE;
17157       consdata->rangedrowpropagated = 0;
17158 
17159       /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
17160       if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
17161       {
17162          SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
17163 
17164          /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17165          if( consdata->maxactdeltavar == var )
17166          {
17167             consdata->maxactdelta = SCIP_INVALID;
17168             consdata->maxactdeltavar = NULL;
17169          }
17170 
17171          /* check whether bound tightening might now be successful */
17172          if( consdata->boundstightened > 0)
17173          {
17174             switch( eventtype )
17175             {
17176             case SCIP_EVENTTYPE_LBTIGHTENED:
17177                if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
17178                   consdata->boundstightened = 0;
17179                break;
17180             case SCIP_EVENTTYPE_UBTIGHTENED:
17181                if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
17182                   consdata->boundstightened = 0;
17183                break;
17184             default:
17185                SCIPerrorMessage("invalid event type %ld\n", eventtype);
17186                return SCIP_INVALIDDATA;
17187             }
17188          }
17189       }
17190       /* update maximal activity delta if a bound was relaxed */
17191       else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
17192       {
17193          SCIP_Real lb;
17194          SCIP_Real ub;
17195          SCIP_Real domain;
17196          SCIP_Real delta;
17197 
17198          assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
17199 
17200          lb = SCIPvarGetLbLocal(var);
17201          ub = SCIPvarGetUbLocal(var);
17202 
17203          domain = ub - lb;
17204          delta = REALABS(val) * domain;
17205 
17206          if( delta > consdata->maxactdelta )
17207          {
17208             consdata->maxactdelta = delta;
17209             consdata->maxactdeltavar = var;
17210          }
17211       }
17212    }
17213    else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
17214    {
17215       /* we want to remove the fixed variable */
17216       consdata->presolved = FALSE;
17217       consdata->removedfixings = FALSE;
17218       consdata->rangedrowpropagated = 0;
17219 
17220       /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
17221       if( consdata->maxactdeltavar == var )
17222       {
17223          consdata->maxactdelta = SCIP_INVALID;
17224          consdata->maxactdeltavar = NULL;
17225       }
17226    }
17227    else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
17228    {
17229       /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
17230       assert(SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17231       assert(SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) <= 1);
17232       consdata->presolved = FALSE;
17233    }
17234    else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
17235    {
17236       SCIP_Real oldbound;
17237       SCIP_Real newbound;
17238       SCIP_Real val;
17239       int varpos;
17240 
17241       varpos = eventdata->varpos;
17242       assert(0 <= varpos && varpos < consdata->nvars);
17243       oldbound = SCIPeventGetOldbound(event);
17244       newbound = SCIPeventGetNewbound(event);
17245       assert(var != NULL);
17246       assert(consdata->vars[varpos] == var);
17247       val = consdata->vals[varpos];
17248 
17249       consdata->rangedrowpropagated = 0;
17250 
17251       /* update the activity values */
17252       if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
17253          consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
17254       else
17255       {
17256          assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
17257          consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
17258       }
17259 
17260       /* if the variable is binary but not fixed it had to become binary due to this global change */
17261       if( SCIPvarIsBinary(var) && SCIPisGT(scip, SCIPvarGetUbGlobal(var), SCIPvarGetLbGlobal(var)) )
17262       {
17263          if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE )
17264             consdata->indexsorted = FALSE;
17265          else
17266             consdata->coefsorted = FALSE;
17267       }
17268    }
17269    else if( (eventtype & SCIP_EVENTTYPE_TYPECHANGED) != 0 )
17270    {
17271       assert(SCIPgetStage(scip) < SCIP_STAGE_PRESOLVED);
17272 
17273       /* for presolving it only matters if a variable type changed from continuous to some kind of integer */
17274       consdata->presolved = (consdata->presolved && SCIPeventGetOldtype(event) < SCIP_VARTYPE_CONTINUOUS);
17275 
17276       /* the ordering is preserved if the type changes from something different to binary to binary but SCIPvarIsBinary() is true */
17277       consdata->indexsorted = (consdata->indexsorted && SCIPeventGetNewtype(event) == SCIP_VARTYPE_BINARY && SCIPvarIsBinary(var));
17278    }
17279    else
17280    {
17281       assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
17282       consdata->varsdeleted = TRUE;
17283    }
17284 
17285    return SCIP_OKAY;
17286 }
17287 
17288 
17289 /*
17290  * Callback methods of conflict handler
17291  */
17292 
17293 /** conflict processing method of conflict handler (called when conflict was found) */
17294 static
SCIP_DECL_CONFLICTEXEC(conflictExecLinear)17295 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
17296 {  /*lint --e{715}*/
17297    SCIP_VAR** vars;
17298    SCIP_Real* vals;
17299    SCIP_Real lhs;
17300    int i;
17301 
17302    assert(scip != NULL);
17303    assert(conflicthdlr != NULL);
17304    assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
17305    assert(bdchginfos != NULL || nbdchginfos == 0);
17306    assert(result != NULL);
17307 
17308    /* don't process already resolved conflicts */
17309    if( resolved )
17310    {
17311       *result = SCIP_DIDNOTRUN;
17312       return SCIP_OKAY;
17313    }
17314 
17315    *result = SCIP_DIDNOTFIND;
17316 
17317    /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
17318    SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
17319    SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
17320    lhs = 1.0;
17321    for( i = 0; i < nbdchginfos; ++i )
17322    {
17323       assert(bdchginfos != NULL);
17324 
17325       vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
17326 
17327       /* we can only treat binary variables */
17328       /**@todo extend linear conflict constraints to some non-binary cases */
17329       if( !SCIPvarIsBinary(vars[i]) )
17330          break;
17331 
17332       /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
17333       if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
17334          vals[i] = 1.0;
17335       else
17336       {
17337          vals[i] = -1.0;
17338          lhs -= 1.0;
17339       }
17340    }
17341 
17342    if( i == nbdchginfos )
17343    {
17344       SCIP_CONS* cons;
17345       SCIP_CONS* upgdcons;
17346       char consname[SCIP_MAXSTRLEN];
17347 
17348       /* create a constraint out of the conflict set */
17349       (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
17350       SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
17351             FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
17352 
17353       /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
17354       SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
17355       if( upgdcons != NULL )
17356       {
17357          SCIP_CALL( SCIPreleaseCons(scip, &cons) );
17358          cons = upgdcons;
17359       }
17360 
17361       /* add conflict to SCIP */
17362       SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
17363 
17364       *result = SCIP_CONSADDED;
17365    }
17366 
17367    /* free temporary memory */
17368    SCIPfreeBufferArray(scip, &vals);
17369    SCIPfreeBufferArray(scip, &vars);
17370 
17371    return SCIP_OKAY;
17372 }
17373 
17374 
17375 /*
17376  * Quadratic constraint upgrading
17377  */
17378 
17379 
17380 /** upgrades quadratic constraints with only and at least one linear variables into a linear constraint
17381  */
17382 static
SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)17383 SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
17384 {  /*lint --e{715}*/
17385    SCIP_CONSDATA* upgdconsdata;
17386 
17387    assert(scip != NULL);
17388    assert(cons != NULL);
17389    assert(nupgdconss != NULL);
17390    assert(upgdconss  != NULL);
17391 
17392    *nupgdconss = 0;
17393 
17394    SCIPdebugMsg(scip, "upgradeConsQuadratic called for constraint <%s>\n", SCIPconsGetName(cons));
17395    SCIPdebugPrintCons(scip, cons, NULL);
17396 
17397    if( SCIPgetNQuadVarTermsQuadratic(scip, cons) > 0 )
17398       return SCIP_OKAY;
17399    if( SCIPgetNLinearVarsQuadratic(scip, cons) == 0 )
17400       return SCIP_OKAY;
17401 
17402    if( upgdconsssize < 1 )
17403    {
17404       /* signal that we need more memory */
17405       *nupgdconss = -1;
17406       return SCIP_OKAY;
17407    }
17408 
17409    *nupgdconss = 1;
17410    SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17411          SCIPgetNLinearVarsQuadratic(scip, cons),
17412          SCIPgetLinearVarsQuadratic(scip, cons),
17413          SCIPgetCoefsLinearVarsQuadratic(scip, cons),
17414          SCIPgetLhsQuadratic(scip, cons), SCIPgetRhsQuadratic(scip, cons),
17415          SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
17416          SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons),  SCIPconsIsLocal(cons),
17417          SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons),
17418          SCIPconsIsStickingAtNode(cons)) );
17419 
17420    upgdconsdata = SCIPconsGetData(upgdconss[0]);
17421    assert(upgdconsdata != NULL);
17422 
17423    /* check violation of this linear constraint with absolute tolerances, to be consistent with the original quadratic constraint */
17424    upgdconsdata->checkabsolute = TRUE;
17425 
17426    SCIPdebugMsg(scip, "created linear constraint:\n");
17427    SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17428 
17429    return SCIP_OKAY;
17430 }
17431 
17432 /** tries to upgrade a nonlinear constraint into a linear constraint */
17433 static
SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)17434 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
17435 {
17436    SCIP_CONSDATA* upgdconsdata;
17437 
17438    assert(nupgdconss != NULL);
17439    assert(upgdconss != NULL);
17440 
17441    *nupgdconss = 0;
17442 
17443    /* no interest in nonlinear constraints */
17444    if( SCIPgetExprgraphNodeNonlinear(scip, cons) != NULL )
17445       return SCIP_OKAY;
17446 
17447    /* no interest in constant constraints */
17448    if( SCIPgetNLinearVarsNonlinear(scip, cons) == 0 )
17449       return SCIP_OKAY;
17450 
17451    if( upgdconsssize < 1 )
17452    {
17453       /* request larger upgdconss array */
17454       *nupgdconss = -1;
17455       return SCIP_OKAY;
17456    }
17457 
17458    *nupgdconss = 1;
17459    SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
17460          SCIPgetNLinearVarsNonlinear(scip, cons), SCIPgetLinearVarsNonlinear(scip, cons), SCIPgetLinearCoefsNonlinear(scip, cons),
17461          SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons),
17462          SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons),
17463          SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
17464          SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons),
17465          SCIPconsIsStickingAtNode(cons)) );
17466 
17467    upgdconsdata = SCIPconsGetData(upgdconss[0]);
17468    assert(upgdconsdata != NULL);
17469 
17470    /* check violation of this linear constraint with absolute tolerances, to be consistent with the original nonlinear constraint */
17471    upgdconsdata->checkabsolute = TRUE;
17472 
17473    SCIPdebugMsg(scip, "created linear constraint:\n");
17474    SCIPdebugPrintCons(scip, upgdconss[0], NULL);
17475 
17476    return SCIP_OKAY;
17477 }
17478 
17479 /*
17480  * constraint specific interface methods
17481  */
17482 
17483 /** creates the handler for linear constraints and includes it in SCIP */
SCIPincludeConshdlrLinear(SCIP * scip)17484 SCIP_RETCODE SCIPincludeConshdlrLinear(
17485    SCIP*                 scip                /**< SCIP data structure */
17486    )
17487 {
17488    SCIP_CONSHDLRDATA* conshdlrdata;
17489    SCIP_CONSHDLR* conshdlr;
17490    SCIP_EVENTHDLR* eventhdlr;
17491    SCIP_CONFLICTHDLR* conflicthdlr;
17492 
17493    assert(scip != NULL);
17494 
17495    /* create event handler for bound change events */
17496    SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC,
17497          eventExecLinear, NULL) );
17498 
17499    /* create conflict handler for linear constraints */
17500    SCIP_CALL( SCIPincludeConflicthdlrBasic(scip, &conflicthdlr, CONFLICTHDLR_NAME, CONFLICTHDLR_DESC, CONFLICTHDLR_PRIORITY,
17501          conflictExecLinear, NULL) );
17502 
17503    /* create constraint handler data */
17504    SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
17505 
17506    /* include constraint handler */
17507    SCIP_CALL( SCIPincludeConshdlrBasic(scip, &conshdlr, CONSHDLR_NAME, CONSHDLR_DESC,
17508          CONSHDLR_ENFOPRIORITY, CONSHDLR_CHECKPRIORITY, CONSHDLR_EAGERFREQ, CONSHDLR_NEEDSCONS,
17509          consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
17510          conshdlrdata) );
17511 
17512    assert(conshdlr != NULL);
17513 
17514    /* set non-fundamental callbacks via specific setter functions */
17515    SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
17516    SCIP_CALL( SCIPsetConshdlrDeactive(scip, conshdlr, consDeactiveLinear) );
17517    SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
17518    SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
17519    SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
17520    SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
17521    SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
17522    SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
17523    SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
17524    SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
17525    SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
17526    SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
17527    SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
17528    SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
17529    SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
17530    SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
17531          CONSHDLR_PROP_TIMING) );
17532    SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
17533    SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
17534          CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
17535    SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
17536    SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
17537 
17538    if( SCIPfindConshdlr(scip, "quadratic") != NULL )
17539    {
17540       /* include function that upgrades quadratic constraint to linear constraints */
17541       SCIP_CALL( SCIPincludeQuadconsUpgrade(scip, upgradeConsQuadratic, QUADCONSUPGD_PRIORITY, TRUE, CONSHDLR_NAME) );
17542    }
17543 
17544    if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
17545    {
17546       /* include the linear constraint upgrade in the nonlinear constraint handler */
17547       SCIP_CALL( SCIPincludeNonlinconsUpgrade(scip, upgradeConsNonlinear, NULL, NONLINCONSUPGD_PRIORITY, TRUE, CONSHDLR_NAME) );
17548    }
17549 
17550    /* add linear constraint handler parameters */
17551    SCIP_CALL( SCIPaddIntParam(scip,
17552          "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
17553          "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
17554          &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17555    SCIP_CALL( SCIPaddIntParam(scip,
17556          "constraints/" CONSHDLR_NAME "/maxrounds",
17557          "maximal number of separation rounds per node (-1: unlimited)",
17558          &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
17559    SCIP_CALL( SCIPaddIntParam(scip,
17560          "constraints/" CONSHDLR_NAME "/maxroundsroot",
17561          "maximal number of separation rounds per node in the root node (-1: unlimited)",
17562          &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
17563    SCIP_CALL( SCIPaddIntParam(scip,
17564          "constraints/" CONSHDLR_NAME "/maxsepacuts",
17565          "maximal number of cuts separated per separation round",
17566          &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
17567    SCIP_CALL( SCIPaddIntParam(scip,
17568          "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
17569          "maximal number of cuts separated per separation round in the root node",
17570          &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
17571    SCIP_CALL( SCIPaddBoolParam(scip,
17572          "constraints/" CONSHDLR_NAME "/presolpairwise",
17573          "should pairwise constraint comparison be performed in presolving?",
17574          &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
17575    SCIP_CALL( SCIPaddBoolParam(scip,
17576          "constraints/" CONSHDLR_NAME "/presolusehashing",
17577          "should hash table be used for detecting redundant constraints in advance",
17578          &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
17579    SCIP_CALL( SCIPaddIntParam(scip,
17580          "constraints/" CONSHDLR_NAME "/nmincomparisons",
17581          "number for minimal pairwise presolve comparisons",
17582          &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
17583    SCIP_CALL( SCIPaddRealParam(scip,
17584          "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
17585          "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
17586          &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
17587    SCIP_CALL( SCIPaddRealParam(scip,
17588          "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
17589          "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
17590          &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17591    SCIP_CALL( SCIPaddRealParam(scip,
17592          "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
17593          "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
17594          &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
17595    SCIP_CALL( SCIPaddRealParam(scip,
17596          "constraints/" CONSHDLR_NAME "/maxcardbounddist",
17597          "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
17598          &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
17599    SCIP_CALL( SCIPaddBoolParam(scip,
17600          "constraints/" CONSHDLR_NAME "/separateall",
17601          "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
17602          &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
17603    SCIP_CALL( SCIPaddBoolParam(scip,
17604          "constraints/" CONSHDLR_NAME "/aggregatevariables",
17605          "should presolving search for aggregations in equations",
17606          &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
17607    SCIP_CALL( SCIPaddBoolParam(scip,
17608          "constraints/" CONSHDLR_NAME "/simplifyinequalities",
17609          "should presolving try to simplify inequalities",
17610          &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
17611    SCIP_CALL( SCIPaddBoolParam(scip,
17612          "constraints/" CONSHDLR_NAME "/dualpresolving",
17613          "should dual presolving steps be performed?",
17614          &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
17615    SCIP_CALL( SCIPaddBoolParam(scip,
17616          "constraints/" CONSHDLR_NAME "/singletonstuffing",
17617          "should stuffing of singleton continuous variables be performed?",
17618          &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17619    SCIP_CALL( SCIPaddBoolParam(scip,
17620          "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17621          "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17622          &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17623    SCIP_CALL( SCIPaddBoolParam(scip,
17624          "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17625          &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17626    SCIP_CALL( SCIPaddBoolParam(scip,
17627          "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17628          "should the violation for a constraint with side 0.0 be checked relative to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)?",
17629          &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17630    SCIP_CALL( SCIPaddBoolParam(scip,
17631          "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17632          "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17633          &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17634    SCIP_CALL( SCIPaddBoolParam(scip,
17635          "constraints/" CONSHDLR_NAME "/detectlowerbound",
17636          "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17637          &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17638    SCIP_CALL( SCIPaddBoolParam(scip,
17639          "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17640          "should presolving try to detect subsets of constraints parallel to the objective function?",
17641          &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17642    SCIP_CALL( SCIPaddBoolParam(scip,
17643          "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17644          "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17645          &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17646    SCIP_CALL( SCIPaddBoolParam(scip,
17647          "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17648          "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17649          &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17650    SCIP_CALL( SCIPaddIntParam(scip,
17651          "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17652          "maximum depth to apply ranged row propagation",
17653          &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17654    SCIP_CALL( SCIPaddIntParam(scip,
17655          "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17656          "frequency for applying ranged row propagation",
17657          &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17658    SCIP_CALL( SCIPaddBoolParam(scip,
17659          "constraints/" CONSHDLR_NAME "/multaggrremove",
17660          "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17661          &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17662    SCIP_CALL( SCIPaddRealParam(scip,
17663          "constraints/" CONSHDLR_NAME "/maxmultaggrquot",
17664          "maximum coefficient dynamism (ie. maxabsval / minabsval) for primal multiaggregation",
17665          &conshdlrdata->maxmultaggrquot, TRUE, DEFAULT_MAXMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17666    SCIP_CALL( SCIPaddRealParam(scip,
17667          "constraints/" CONSHDLR_NAME "/maxdualmultaggrquot",
17668          "maximum coefficient dynamism (ie. maxabsval / minabsval) for dual multiaggregation",
17669          &conshdlrdata->maxdualmultaggrquot, TRUE, DEFAULT_MAXDUALMULTAGGRQUOT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
17670    SCIP_CALL( SCIPaddBoolParam(scip,
17671          "constraints/" CONSHDLR_NAME "/extractcliques",
17672          "should Cliques be extracted?",
17673          &conshdlrdata->extractcliques, TRUE, DEFAULT_EXTRACTCLIQUES, NULL, NULL) );
17674 
17675    return SCIP_OKAY;
17676 }
17677 
17678 /** includes a linear constraint update method into the linear constraint handler */
SCIPincludeLinconsUpgrade(SCIP * scip,SCIP_DECL_LINCONSUPGD ((* linconsupgd)),int priority,const char * conshdlrname)17679 SCIP_RETCODE SCIPincludeLinconsUpgrade(
17680    SCIP*                 scip,               /**< SCIP data structure */
17681    SCIP_DECL_LINCONSUPGD((*linconsupgd)),    /**< method to call for upgrading linear constraint */
17682    int                   priority,           /**< priority of upgrading method */
17683    const char*           conshdlrname        /**< name of the constraint handler */
17684    )
17685 {
17686    SCIP_CONSHDLR* conshdlr;
17687    SCIP_CONSHDLRDATA* conshdlrdata;
17688    SCIP_LINCONSUPGRADE* linconsupgrade;
17689    char paramname[SCIP_MAXSTRLEN];
17690    char paramdesc[SCIP_MAXSTRLEN];
17691 
17692    assert(scip != NULL);
17693    assert(linconsupgd != NULL);
17694    assert(conshdlrname != NULL );
17695 
17696    /* find the linear constraint handler */
17697    conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17698    if( conshdlr == NULL )
17699    {
17700       SCIPerrorMessage("linear constraint handler not found\n");
17701       return SCIP_PLUGINNOTFOUND;
17702    }
17703 
17704    conshdlrdata = SCIPconshdlrGetData(conshdlr);
17705    assert(conshdlrdata != NULL);
17706 
17707    /* check if linear constraint update method already exists in constraint handler data */
17708    if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17709    {
17710       /* create a linear constraint upgrade data object */
17711       SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17712 
17713       /* insert linear constraint update method into constraint handler data */
17714       SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17715 
17716       /* adds parameter to turn on and off the upgrading step */
17717       (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17718       (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17719       SCIP_CALL( SCIPaddBoolParam(scip,
17720             paramname, paramdesc,
17721             &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17722    }
17723 
17724    return SCIP_OKAY;
17725 }
17726 
17727 /** creates and captures a linear constraint
17728  *
17729  *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17730  */
SCIPcreateConsLinear(SCIP * scip,SCIP_CONS ** cons,const char * name,int nvars,SCIP_VAR ** vars,SCIP_Real * vals,SCIP_Real lhs,SCIP_Real rhs,SCIP_Bool initial,SCIP_Bool separate,SCIP_Bool enforce,SCIP_Bool check,SCIP_Bool propagate,SCIP_Bool local,SCIP_Bool modifiable,SCIP_Bool dynamic,SCIP_Bool removable,SCIP_Bool stickingatnode)17731 SCIP_RETCODE SCIPcreateConsLinear(
17732    SCIP*                 scip,               /**< SCIP data structure */
17733    SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
17734    const char*           name,               /**< name of constraint */
17735    int                   nvars,              /**< number of nonzeros in the constraint */
17736    SCIP_VAR**            vars,               /**< array with variables of constraint entries */
17737    SCIP_Real*            vals,               /**< array with coefficients of constraint entries */
17738    SCIP_Real             lhs,                /**< left hand side of constraint */
17739    SCIP_Real             rhs,                /**< right hand side of constraint */
17740    SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP?
17741                                               *   Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17742    SCIP_Bool             separate,           /**< should the constraint be separated during LP processing?
17743                                               *   Usually set to TRUE. */
17744    SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing?
17745                                               *   TRUE for model constraints, FALSE for additional, redundant constraints. */
17746    SCIP_Bool             check,              /**< should the constraint be checked for feasibility?
17747                                               *   TRUE for model constraints, FALSE for additional, redundant constraints. */
17748    SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing?
17749                                               *   Usually set to TRUE. */
17750    SCIP_Bool             local,              /**< is constraint only valid locally?
17751                                               *   Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17752    SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)?
17753                                               *   Usually set to FALSE. In column generation applications, set to TRUE if pricing
17754                                               *   adds coefficients to this constraint. */
17755    SCIP_Bool             dynamic,            /**< is constraint subject to aging?
17756                                               *   Usually set to FALSE. Set to TRUE for own cuts which
17757                                               *   are separated as constraints. */
17758    SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup?
17759                                               *   Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17760    SCIP_Bool             stickingatnode      /**< should the constraint always be kept at the node where it was added, even
17761                                               *   if it may be moved to a more global node?
17762                                               *   Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17763    )
17764 {
17765    SCIP_CONSHDLR* conshdlr;
17766    SCIP_CONSDATA* consdata;
17767 
17768    assert(scip != NULL);
17769    assert(cons != NULL);
17770 
17771    /* find the linear constraint handler */
17772    conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17773    if( conshdlr == NULL )
17774    {
17775       SCIPerrorMessage("linear constraint handler not found\n");
17776       return SCIP_PLUGINNOTFOUND;
17777    }
17778 
17779    /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17780     * constraint after presolving we have to ensure that it holds active variables
17781     */
17782    if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17783    {
17784       SCIP_VAR** consvars;
17785       SCIP_Real* consvals;
17786       SCIP_Real constant = 0.0;
17787       int nconsvars;
17788       int requiredsize;
17789 
17790       nconsvars = nvars;
17791       SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17792       SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17793 
17794       /* get active variables for new constraint */
17795       SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17796 
17797       /* if space was not enough we need to resize the buffers */
17798       if( requiredsize > nconsvars )
17799       {
17800          SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17801          SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17802 
17803          SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17804          assert(requiredsize <= nconsvars);
17805       }
17806 
17807       /* adjust sides and check that we do not subtract infinity values */
17808       if( SCIPisInfinity(scip, REALABS(constant)) )
17809       {
17810          if( constant < 0.0 )
17811          {
17812             if( SCIPisInfinity(scip, lhs) )
17813             {
17814                SCIPfreeBufferArray(scip, &consvals);
17815                SCIPfreeBufferArray(scip, &consvars);
17816 
17817                SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", name);
17818 
17819                SCIPABORT();
17820                return SCIP_INVALIDDATA; /*lint !e527*/
17821             }
17822             if( SCIPisInfinity(scip, rhs) )
17823             {
17824                SCIPfreeBufferArray(scip, &consvals);
17825                SCIPfreeBufferArray(scip, &consvars);
17826 
17827                SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", name);
17828 
17829                SCIPABORT();
17830                return SCIP_INVALIDDATA; /*lint !e527*/
17831             }
17832 
17833             lhs = -SCIPinfinity(scip);
17834             rhs = -SCIPinfinity(scip);
17835          }
17836          else
17837          {
17838             if( SCIPisInfinity(scip, -lhs) )
17839             {
17840                SCIPfreeBufferArray(scip, &consvals);
17841                SCIPfreeBufferArray(scip, &consvars);
17842 
17843                SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", name);
17844 
17845                SCIPABORT();
17846                return SCIP_INVALIDDATA; /*lint !e527*/
17847             }
17848             if( SCIPisInfinity(scip, -rhs) )
17849             {
17850                SCIPfreeBufferArray(scip, &consvals);
17851                SCIPfreeBufferArray(scip, &consvars);
17852 
17853                SCIPerrorMessage("try to generate inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", name);
17854 
17855                SCIPABORT();
17856                return SCIP_INVALIDDATA; /*lint !e527*/
17857             }
17858 
17859             lhs = SCIPinfinity(scip);
17860             rhs = SCIPinfinity(scip);
17861          }
17862       }
17863       else
17864       {
17865          if( !SCIPisInfinity(scip, REALABS(lhs)) )
17866             lhs -= constant;
17867          if( !SCIPisInfinity(scip, REALABS(rhs)) )
17868             rhs -= constant;
17869 
17870          if( SCIPisInfinity(scip, -lhs) )
17871             lhs = -SCIPinfinity(scip);
17872          else if( SCIPisInfinity(scip, lhs) )
17873             lhs = SCIPinfinity(scip);
17874 
17875          if( SCIPisInfinity(scip, rhs) )
17876             rhs = SCIPinfinity(scip);
17877          else if( SCIPisInfinity(scip, -rhs) )
17878             rhs = -SCIPinfinity(scip);
17879       }
17880 
17881       /* create constraint data */
17882       SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17883       assert(consdata != NULL);
17884 
17885       SCIPfreeBufferArray(scip, &consvals);
17886       SCIPfreeBufferArray(scip, &consvars);
17887    }
17888    else
17889    {
17890       /* create constraint data */
17891       SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
17892       assert(consdata != NULL);
17893    }
17894 
17895 #ifndef NDEBUG
17896    /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
17897    if( check || enforce )
17898    {
17899       int n;
17900       for(n = consdata->nvars - 1; n >= 0; --n )
17901          assert(!SCIPvarIsRelaxationOnly(consdata->vars[n]));
17902    }
17903 #endif
17904 
17905    /* create constraint */
17906    SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
17907          local, modifiable, dynamic, removable, stickingatnode) );
17908 
17909    return SCIP_OKAY;
17910 }
17911 
17912 /** creates and captures a linear constraint
17913  *  in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
17914  *  method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
17915  *
17916  *  @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
17917  *
17918  *  @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17919  */
SCIPcreateConsBasicLinear(SCIP * scip,SCIP_CONS ** cons,const char * name,int nvars,SCIP_VAR ** vars,SCIP_Real * vals,SCIP_Real lhs,SCIP_Real rhs)17920 SCIP_RETCODE SCIPcreateConsBasicLinear(
17921    SCIP*                 scip,               /**< SCIP data structure */
17922    SCIP_CONS**           cons,               /**< pointer to hold the created constraint */
17923    const char*           name,               /**< name of constraint */
17924    int                   nvars,              /**< number of nonzeros in the constraint */
17925    SCIP_VAR**            vars,               /**< array with variables of constraint entries */
17926    SCIP_Real*            vals,               /**< array with coefficients of constraint entries */
17927    SCIP_Real             lhs,                /**< left hand side of constraint */
17928    SCIP_Real             rhs                 /**< right hand side of constraint */
17929    )
17930 {
17931    assert(scip != NULL);
17932 
17933    SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
17934          TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
17935 
17936    return SCIP_OKAY;
17937 }
17938 
17939 /** creates by copying and captures a linear constraint */
SCIPcopyConsLinear(SCIP * scip,SCIP_CONS ** cons,SCIP * sourcescip,const char * name,int nvars,SCIP_VAR ** sourcevars,SCIP_Real * sourcecoefs,SCIP_Real lhs,SCIP_Real rhs,SCIP_HASHMAP * varmap,SCIP_HASHMAP * consmap,SCIP_Bool initial,SCIP_Bool separate,SCIP_Bool enforce,SCIP_Bool check,SCIP_Bool propagate,SCIP_Bool local,SCIP_Bool modifiable,SCIP_Bool dynamic,SCIP_Bool removable,SCIP_Bool stickingatnode,SCIP_Bool global,SCIP_Bool * valid)17940 SCIP_RETCODE SCIPcopyConsLinear(
17941    SCIP*                 scip,               /**< target SCIP data structure */
17942    SCIP_CONS**           cons,               /**< pointer to store the created target constraint */
17943    SCIP*                 sourcescip,         /**< source SCIP data structure */
17944    const char*           name,               /**< name of constraint */
17945    int                   nvars,              /**< number of variables in source variable array */
17946    SCIP_VAR**            sourcevars,         /**< source variables of the linear constraints */
17947    SCIP_Real*            sourcecoefs,        /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
17948    SCIP_Real             lhs,                /**< left hand side of the linear constraint */
17949    SCIP_Real             rhs,                /**< right hand side of the linear constraint */
17950    SCIP_HASHMAP*         varmap,             /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
17951                                               *   variables of the target SCIP */
17952    SCIP_HASHMAP*         consmap,            /**< a hashmap to store the mapping of source constraints to the corresponding
17953                                               *   target constraints */
17954    SCIP_Bool             initial,            /**< should the LP relaxation of constraint be in the initial LP? */
17955    SCIP_Bool             separate,           /**< should the constraint be separated during LP processing? */
17956    SCIP_Bool             enforce,            /**< should the constraint be enforced during node processing? */
17957    SCIP_Bool             check,              /**< should the constraint be checked for feasibility? */
17958    SCIP_Bool             propagate,          /**< should the constraint be propagated during node processing? */
17959    SCIP_Bool             local,              /**< is constraint only valid locally? */
17960    SCIP_Bool             modifiable,         /**< is constraint modifiable (subject to column generation)? */
17961    SCIP_Bool             dynamic,            /**< is constraint subject to aging? */
17962    SCIP_Bool             removable,          /**< should the relaxation be removed from the LP due to aging or cleanup? */
17963    SCIP_Bool             stickingatnode,     /**< should the constraint always be kept at the node where it was added, even
17964                                               *   if it may be moved to a more global node? */
17965    SCIP_Bool             global,             /**< create a global or a local copy? */
17966    SCIP_Bool*            valid               /**< pointer to store if the copying was valid */
17967    )
17968 {
17969    SCIP_VAR** vars;
17970    SCIP_Real* coefs;
17971 
17972    SCIP_Real constant;
17973    int requiredsize;
17974    int v;
17975    SCIP_Bool success;
17976 
17977    if( SCIPisGT(scip, lhs, rhs) )
17978    {
17979       *valid = FALSE;
17980       return SCIP_OKAY;
17981    }
17982 
17983    (*valid) = TRUE;
17984 
17985    if( nvars == 0 )
17986    {
17987       SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
17988             initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17989       return SCIP_OKAY;
17990    }
17991 
17992    /* duplicate variable array */
17993    SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
17994 
17995    /* duplicate coefficient array */
17996    if( sourcecoefs != NULL )
17997    {
17998       SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
17999    }
18000    else
18001    {
18002       SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
18003       for( v = 0; v < nvars; ++v )
18004          coefs[v] = 1.0;
18005    }
18006 
18007    constant = 0.0;
18008 
18009    /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
18010     * the target SCIP
18011     */
18012    if( !SCIPvarIsOriginal(vars[0]) )
18013    {
18014       SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
18015 
18016       if( requiredsize > nvars )
18017       {
18018          SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
18019          SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
18020 
18021          SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
18022          assert(requiredsize <= nvars);
18023       }
18024    }
18025    else
18026    {
18027       for( v = 0; v < nvars; ++v )
18028       {
18029          assert(SCIPvarIsOriginal(vars[v]));
18030          SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
18031          assert(vars[v] != NULL);
18032       }
18033    }
18034 
18035    success = TRUE;
18036    /* map variables of the source constraint to variables of the target SCIP */
18037    for( v = 0; v < nvars && success; ++v )
18038    {
18039       SCIP_VAR* var;
18040       var = vars[v];
18041 
18042       /* if this is a checked or enforced constraints, then there must be no relaxation-only variables */
18043       assert(!SCIPvarIsRelaxationOnly(var) || (!check && !enforce));
18044 
18045       SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
18046       assert(!(success) || vars[v] != NULL);
18047    }
18048 
18049    /* only create the target constraint, if all variables could be copied */
18050    if( success )
18051    {
18052       if( !SCIPisInfinity(scip, -lhs) )
18053          lhs -= constant;
18054 
18055       if( !SCIPisInfinity(scip, rhs) )
18056          rhs -= constant;
18057 
18058       SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
18059             initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
18060    }
18061    else
18062       *valid = FALSE;
18063 
18064    /* free buffer array */
18065    SCIPfreeBufferArray(scip, &coefs);
18066    SCIPfreeBufferArray(scip, &vars);
18067 
18068    return SCIP_OKAY;
18069 }
18070 
18071 /** adds coefficient to linear constraint (if it is not zero) */
SCIPaddCoefLinear(SCIP * scip,SCIP_CONS * cons,SCIP_VAR * var,SCIP_Real val)18072 SCIP_RETCODE SCIPaddCoefLinear(
18073    SCIP*                 scip,               /**< SCIP data structure */
18074    SCIP_CONS*            cons,               /**< constraint data */
18075    SCIP_VAR*             var,                /**< variable of constraint entry */
18076    SCIP_Real             val                 /**< coefficient of constraint entry */
18077    )
18078 {
18079    assert(scip != NULL);
18080    assert(cons != NULL);
18081    assert(var != NULL);
18082 
18083    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18084    {
18085       SCIPerrorMessage("constraint is not linear\n");
18086       return SCIP_INVALIDDATA;
18087    }
18088 
18089    /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
18090     * constraint after presolving we have to ensure that it holds active variables
18091     */
18092    if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
18093    {
18094       SCIP_CONSDATA* consdata;
18095       SCIP_VAR** consvars;
18096       SCIP_Real* consvals;
18097       SCIP_Real constant = 0.0;
18098       SCIP_Real rhs;
18099       SCIP_Real lhs;
18100       int nconsvars;
18101       int requiredsize;
18102       int v;
18103 
18104       nconsvars = 1;
18105       SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
18106       SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
18107       consvars[0] = var;
18108       consvals[0] = val;
18109 
18110       /* get active variables for new constraint */
18111       SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
18112 
18113       /* if space was not enough we need to resize the buffers */
18114       if( requiredsize > nconsvars )
18115       {
18116          SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
18117          SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
18118 
18119          SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
18120          assert(requiredsize <= nconsvars);
18121       }
18122 
18123       consdata = SCIPconsGetData(cons);
18124       assert(consdata != NULL);
18125 
18126       lhs = consdata->lhs;
18127       rhs = consdata->rhs;
18128 
18129       /* adjust sides and check that we do not subtract infinity values */
18130       /* constant is infinite */
18131       if( SCIPisInfinity(scip, REALABS(constant)) )
18132       {
18133 	 if( constant < 0.0 )
18134 	 {
18135 	    if( SCIPisInfinity(scip, lhs) )
18136 	    {
18137 	       SCIPfreeBufferArray(scip, &consvals);
18138 	       SCIPfreeBufferArray(scip, &consvars);
18139 
18140 	       SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons));
18141 
18142 	       SCIPABORT();
18143 	       return SCIP_INVALIDDATA; /*lint !e527*/
18144 	    }
18145 	    if( SCIPisInfinity(scip, rhs) )
18146 	    {
18147 	       SCIPfreeBufferArray(scip, &consvals);
18148 	       SCIPfreeBufferArray(scip, &consvars);
18149 
18150 	       SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons));
18151 
18152 	       SCIPABORT();
18153 	       return SCIP_INVALIDDATA; /*lint !e527*/
18154 	    }
18155 
18156 	    lhs = -SCIPinfinity(scip);
18157 	    rhs = -SCIPinfinity(scip);
18158 	 }
18159 	 else
18160 	 {
18161 	    if( SCIPisInfinity(scip, -lhs) )
18162 	    {
18163 	       SCIPfreeBufferArray(scip, &consvals);
18164 	       SCIPfreeBufferArray(scip, &consvars);
18165 
18166 	       SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite left hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons));
18167 
18168 	       SCIPABORT();
18169 	       return SCIP_INVALIDDATA; /*lint !e527*/
18170 	    }
18171 	    if( SCIPisInfinity(scip, -rhs) )
18172 	    {
18173 	       SCIPfreeBufferArray(scip, &consvals);
18174 	       SCIPfreeBufferArray(scip, &consvars);
18175 
18176 	       SCIPerrorMessage("adding variable <%s> leads to inconsistent constraint <%s>, active variables leads to a infinite constant constradict the infinite right hand side of the constraint\n", SCIPvarGetName(var), SCIPconsGetName(cons));
18177 
18178 	       SCIPABORT();
18179 	       return SCIP_INVALIDDATA; /*lint !e527*/
18180 	    }
18181 
18182 	    lhs = SCIPinfinity(scip);
18183 	    rhs = SCIPinfinity(scip);
18184 	 }
18185       }
18186       /* constant is not infinite */
18187       else
18188       {
18189 	 if( !SCIPisInfinity(scip, REALABS(lhs)) )
18190 	    lhs -= constant;
18191 	 if( !SCIPisInfinity(scip, REALABS(rhs)) )
18192 	    rhs -= constant;
18193 
18194 	 if( SCIPisInfinity(scip, -lhs) )
18195 	    lhs = -SCIPinfinity(scip);
18196 	 else if( SCIPisInfinity(scip, lhs) )
18197 	    lhs = SCIPinfinity(scip);
18198 
18199 	 if( SCIPisInfinity(scip, rhs) )
18200 	    rhs = SCIPinfinity(scip);
18201 	 else if( SCIPisInfinity(scip, -rhs) )
18202 	    rhs = -SCIPinfinity(scip);
18203       }
18204 
18205       /* add all active variables to constraint */
18206       for( v = nconsvars - 1; v >= 0; --v )
18207       {
18208 	 SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
18209       }
18210 
18211       /* update left and right hand sides */
18212       SCIP_CALL( chgLhs(scip, cons, lhs));
18213       SCIP_CALL( chgRhs(scip, cons, rhs));
18214 
18215       SCIPfreeBufferArray(scip, &consvals);
18216       SCIPfreeBufferArray(scip, &consvars);
18217    }
18218    else
18219    {
18220       SCIP_CALL( addCoef(scip, cons, var, val) );
18221    }
18222 
18223    return SCIP_OKAY;
18224 }
18225 
18226 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
18227  *  not yet contained in the constraint
18228  *
18229  *  @note This method may only be called during problem creation stage for an original constraint and variable.
18230  *
18231  *  @note This method requires linear time to search for occurences of the variable in the constraint data.
18232  */
SCIPchgCoefLinear(SCIP * scip,SCIP_CONS * cons,SCIP_VAR * var,SCIP_Real val)18233 SCIP_RETCODE SCIPchgCoefLinear(
18234    SCIP*                 scip,               /**< SCIP data structure */
18235    SCIP_CONS*            cons,               /**< constraint data */
18236    SCIP_VAR*             var,                /**< variable of constraint entry */
18237    SCIP_Real             val                 /**< new coefficient of constraint entry */
18238    )
18239 {
18240    SCIP_CONSDATA* consdata;
18241    SCIP_VAR** vars;
18242    SCIP_Bool found;
18243    int i;
18244 
18245    assert(scip != NULL);
18246    assert(cons != NULL);
18247    assert(var != NULL);
18248 
18249    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18250    {
18251       SCIPerrorMessage("constraint is not linear\n");
18252       return SCIP_INVALIDDATA;
18253    }
18254 
18255    if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
18256    {
18257       SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
18258       return SCIP_INVALIDDATA;
18259    }
18260 
18261    consdata = SCIPconsGetData(cons);
18262    assert(consdata != NULL);
18263 
18264    vars = consdata->vars;
18265    found = FALSE;
18266    i = 0;
18267    while( i < consdata->nvars )
18268    {
18269       if( vars[i] == var )
18270       {
18271          if( found || SCIPisZero(scip, val) )
18272          {
18273             SCIP_CALL( delCoefPos(scip, cons, i) );
18274 
18275             /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
18276             i--;
18277          }
18278          else
18279          {
18280             SCIP_CALL( chgCoefPos(scip, cons, i, val) );
18281          }
18282          found = TRUE;
18283       }
18284       i++;
18285    }
18286 
18287    if( !found && !SCIPisZero(scip, val) )
18288    {
18289       SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
18290    }
18291 
18292    return SCIP_OKAY;
18293 }
18294 
18295 /** deletes variable from linear constraint
18296  *
18297  *  @note This method may only be called during problem creation stage for an original constraint and variable.
18298  *
18299  *  @note This method requires linear time to search for occurences of the variable in the constraint data.
18300  */
SCIPdelCoefLinear(SCIP * scip,SCIP_CONS * cons,SCIP_VAR * var)18301 SCIP_RETCODE SCIPdelCoefLinear(
18302    SCIP*                 scip,               /**< SCIP data structure */
18303    SCIP_CONS*            cons,               /**< constraint data */
18304    SCIP_VAR*             var                 /**< variable of constraint entry */
18305    )
18306 {
18307    assert(scip != NULL);
18308    assert(cons != NULL);
18309    assert(var != NULL);
18310 
18311    SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
18312 
18313    return SCIP_OKAY;
18314 }
18315 
18316 /** gets left hand side of linear constraint */
SCIPgetLhsLinear(SCIP * scip,SCIP_CONS * cons)18317 SCIP_Real SCIPgetLhsLinear(
18318    SCIP*                 scip,               /**< SCIP data structure */
18319    SCIP_CONS*            cons                /**< constraint data */
18320    )
18321 {
18322    SCIP_CONSDATA* consdata;
18323 
18324    assert(scip != NULL);
18325    assert(cons != NULL);
18326 
18327    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18328    {
18329       SCIPerrorMessage("constraint is not linear\n");
18330       SCIPABORT();
18331       return SCIP_INVALID;  /*lint !e527*/
18332    }
18333 
18334    consdata = SCIPconsGetData(cons);
18335    assert(consdata != NULL);
18336 
18337    return consdata->lhs;
18338 }
18339 
18340 /** gets right hand side of linear constraint */
SCIPgetRhsLinear(SCIP * scip,SCIP_CONS * cons)18341 SCIP_Real SCIPgetRhsLinear(
18342    SCIP*                 scip,               /**< SCIP data structure */
18343    SCIP_CONS*            cons                /**< constraint data */
18344    )
18345 {
18346    SCIP_CONSDATA* consdata;
18347 
18348    assert(scip != NULL);
18349    assert(cons != NULL);
18350 
18351    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18352    {
18353       SCIPerrorMessage("constraint is not linear\n");
18354       SCIPABORT();
18355       return SCIP_INVALID;  /*lint !e527*/
18356    }
18357 
18358    consdata = SCIPconsGetData(cons);
18359    assert(consdata != NULL);
18360 
18361    return consdata->rhs;
18362 }
18363 
18364 /** changes left hand side of linear constraint */
SCIPchgLhsLinear(SCIP * scip,SCIP_CONS * cons,SCIP_Real lhs)18365 SCIP_RETCODE SCIPchgLhsLinear(
18366    SCIP*                 scip,               /**< SCIP data structure */
18367    SCIP_CONS*            cons,               /**< constraint data */
18368    SCIP_Real             lhs                 /**< new left hand side */
18369    )
18370 {
18371    assert(scip != NULL);
18372    assert(cons != NULL);
18373 
18374    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18375    {
18376       SCIPerrorMessage("constraint is not linear\n");
18377       return SCIP_INVALIDDATA;
18378    }
18379 
18380    SCIP_CALL( chgLhs(scip, cons, lhs) );
18381 
18382    return SCIP_OKAY;
18383 }
18384 
18385 /** changes right hand side of linear constraint */
SCIPchgRhsLinear(SCIP * scip,SCIP_CONS * cons,SCIP_Real rhs)18386 SCIP_RETCODE SCIPchgRhsLinear(
18387    SCIP*                 scip,               /**< SCIP data structure */
18388    SCIP_CONS*            cons,               /**< constraint data */
18389    SCIP_Real             rhs                 /**< new right hand side */
18390    )
18391 {
18392    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18393    {
18394       SCIPerrorMessage("constraint is not linear\n");
18395       return SCIP_INVALIDDATA;
18396    }
18397 
18398    SCIP_CALL( chgRhs(scip, cons, rhs) );
18399 
18400    return SCIP_OKAY;
18401 }
18402 
18403 /** gets the number of variables in the linear constraint */
SCIPgetNVarsLinear(SCIP * scip,SCIP_CONS * cons)18404 int SCIPgetNVarsLinear(
18405    SCIP*                 scip,               /**< SCIP data structure */
18406    SCIP_CONS*            cons                /**< constraint data */
18407    )
18408 {
18409    SCIP_CONSDATA* consdata;
18410 
18411    assert(scip != NULL);
18412    assert(cons != NULL);
18413 
18414    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18415    {
18416       SCIPerrorMessage("constraint is not linear\n");
18417       SCIPABORT();
18418       return -1;  /*lint !e527*/
18419    }
18420 
18421    consdata = SCIPconsGetData(cons);
18422    assert(consdata != NULL);
18423 
18424    return consdata->nvars;
18425 }
18426 
18427 /** gets the array of variables in the linear constraint; the user must not modify this array! */
SCIPgetVarsLinear(SCIP * scip,SCIP_CONS * cons)18428 SCIP_VAR** SCIPgetVarsLinear(
18429    SCIP*                 scip,               /**< SCIP data structure */
18430    SCIP_CONS*            cons                /**< constraint data */
18431    )
18432 {
18433    SCIP_CONSDATA* consdata;
18434 
18435    assert(scip != NULL);
18436    assert(cons != NULL);
18437 
18438    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18439    {
18440       SCIPerrorMessage("constraint is not linear\n");
18441       SCIPABORT();
18442       return NULL;  /*lint !e527*/
18443    }
18444 
18445    consdata = SCIPconsGetData(cons);
18446    assert(consdata != NULL);
18447 
18448    return consdata->vars;
18449 }
18450 
18451 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
SCIPgetValsLinear(SCIP * scip,SCIP_CONS * cons)18452 SCIP_Real* SCIPgetValsLinear(
18453    SCIP*                 scip,               /**< SCIP data structure */
18454    SCIP_CONS*            cons                /**< constraint data */
18455    )
18456 {
18457    SCIP_CONSDATA* consdata;
18458 
18459    assert(scip != NULL);
18460    assert(cons != NULL);
18461 
18462    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18463    {
18464       SCIPerrorMessage("constraint is not linear\n");
18465       SCIPABORT();
18466       return NULL;  /*lint !e527*/
18467    }
18468 
18469    consdata = SCIPconsGetData(cons);
18470    assert(consdata != NULL);
18471 
18472    return consdata->vals;
18473 }
18474 
18475 /** gets the activity of the linear constraint in the given solution
18476  *
18477  *  @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
18478  *        comprises positive and negative infinity contributions
18479  */
SCIPgetActivityLinear(SCIP * scip,SCIP_CONS * cons,SCIP_SOL * sol)18480 SCIP_Real SCIPgetActivityLinear(
18481    SCIP*                 scip,               /**< SCIP data structure */
18482    SCIP_CONS*            cons,               /**< constraint data */
18483    SCIP_SOL*             sol                 /**< solution, or NULL to use current node's solution */
18484    )
18485 {
18486    SCIP_CONSDATA* consdata;
18487 
18488    assert(scip != NULL);
18489    assert(cons != NULL);
18490 
18491    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18492    {
18493       SCIPerrorMessage("constraint is not linear\n");
18494       SCIPABORT();
18495       return SCIP_INVALID;  /*lint !e527*/
18496    }
18497 
18498    consdata = SCIPconsGetData(cons);
18499    assert(consdata != NULL);
18500 
18501    if( consdata->row != NULL )
18502       return SCIPgetRowSolActivity(scip, consdata->row, sol);
18503    else
18504       return consdataGetActivity(scip, consdata, sol);
18505 }
18506 
18507 /** gets the feasibility of the linear constraint in the given solution */
SCIPgetFeasibilityLinear(SCIP * scip,SCIP_CONS * cons,SCIP_SOL * sol)18508 SCIP_Real SCIPgetFeasibilityLinear(
18509    SCIP*                 scip,               /**< SCIP data structure */
18510    SCIP_CONS*            cons,               /**< constraint data */
18511    SCIP_SOL*             sol                 /**< solution, or NULL to use current node's solution */
18512    )
18513 {
18514    SCIP_CONSDATA* consdata;
18515 
18516    assert(scip != NULL);
18517    assert(cons != NULL);
18518 
18519    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18520    {
18521       SCIPerrorMessage("constraint is not linear\n");
18522       SCIPABORT();
18523       return SCIP_INVALID;  /*lint !e527*/
18524    }
18525 
18526    consdata = SCIPconsGetData(cons);
18527    assert(consdata != NULL);
18528 
18529    if( consdata->row != NULL )
18530       return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
18531    else
18532       return consdataGetFeasibility(scip, consdata, sol);
18533 }
18534 
18535 /** gets the dual solution of the linear constraint in the current LP */
SCIPgetDualsolLinear(SCIP * scip,SCIP_CONS * cons)18536 SCIP_Real SCIPgetDualsolLinear(
18537    SCIP*                 scip,               /**< SCIP data structure */
18538    SCIP_CONS*            cons                /**< constraint data */
18539    )
18540 {
18541    SCIP_CONSDATA* consdata;
18542 
18543    assert(scip != NULL);
18544    assert(cons != NULL);
18545    assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18546 
18547    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18548    {
18549       SCIPerrorMessage("constraint is not linear\n");
18550       SCIPABORT();
18551       return SCIP_INVALID;  /*lint !e527*/
18552    }
18553 
18554    consdata = SCIPconsGetData(cons);
18555    assert(consdata != NULL);
18556 
18557    if( consdata->row != NULL )
18558       return SCIProwGetDualsol(consdata->row);
18559    else
18560       return 0.0;
18561 }
18562 
18563 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
SCIPgetDualfarkasLinear(SCIP * scip,SCIP_CONS * cons)18564 SCIP_Real SCIPgetDualfarkasLinear(
18565    SCIP*                 scip,               /**< SCIP data structure */
18566    SCIP_CONS*            cons                /**< constraint data */
18567    )
18568 {
18569    SCIP_CONSDATA* consdata;
18570 
18571    assert(scip != NULL);
18572    assert(cons != NULL);
18573    assert(!SCIPconsIsOriginal(cons)); /* original constraints would always return 0 */
18574 
18575    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18576    {
18577       SCIPerrorMessage("constraint is not linear\n");
18578       SCIPABORT();
18579       return SCIP_INVALID;  /*lint !e527*/
18580    }
18581 
18582    consdata = SCIPconsGetData(cons);
18583    assert(consdata != NULL);
18584 
18585    if( consdata->row != NULL )
18586       return SCIProwGetDualfarkas(consdata->row);
18587    else
18588       return 0.0;
18589 }
18590 
18591 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
18592  *  the user must not modify the row!
18593  */
SCIPgetRowLinear(SCIP * scip,SCIP_CONS * cons)18594 SCIP_ROW* SCIPgetRowLinear(
18595    SCIP*                 scip,               /**< SCIP data structure */
18596    SCIP_CONS*            cons                /**< constraint data */
18597    )
18598 {
18599    SCIP_CONSDATA* consdata;
18600 
18601    assert(scip != NULL);
18602    assert(cons != NULL);
18603 
18604    if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
18605    {
18606       SCIPerrorMessage("constraint is not linear\n");
18607       SCIPABORT();
18608       return NULL;  /*lint !e527*/
18609    }
18610 
18611    consdata = SCIPconsGetData(cons);
18612    assert(consdata != NULL);
18613 
18614    return consdata->row;
18615 }
18616 
18617 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
SCIPupgradeConsLinear(SCIP * scip,SCIP_CONS * cons,SCIP_CONS ** upgdcons)18618 SCIP_RETCODE SCIPupgradeConsLinear(
18619    SCIP*                 scip,               /**< SCIP data structure */
18620    SCIP_CONS*            cons,               /**< source constraint to try to convert */
18621    SCIP_CONS**           upgdcons            /**< pointer to store upgraded constraint, or NULL if not successful */
18622    )
18623 {
18624    SCIP_CONSHDLR* conshdlr;
18625    SCIP_CONSHDLRDATA* conshdlrdata;
18626    SCIP_CONSDATA* consdata;
18627    SCIP_VAR* var;
18628    SCIP_Real val;
18629    SCIP_Real lb;
18630    SCIP_Real ub;
18631    SCIP_Real poscoeffsum;
18632    SCIP_Real negcoeffsum;
18633    SCIP_Bool infeasible;
18634    SCIP_Bool integral;
18635    int nchgsides = 0;
18636    int nposbin;
18637    int nnegbin;
18638    int nposint;
18639    int nnegint;
18640    int nposimpl;
18641    int nnegimpl;
18642    int nposimplbin;
18643    int nnegimplbin;
18644    int nposcont;
18645    int nnegcont;
18646    int ncoeffspone;
18647    int ncoeffsnone;
18648    int ncoeffspint;
18649    int ncoeffsnint;
18650    int ncoeffspfrac;
18651    int ncoeffsnfrac;
18652    int i;
18653 
18654    assert(scip != NULL);
18655    assert(cons != NULL);
18656    assert(upgdcons != NULL);
18657 
18658    *upgdcons = NULL;
18659 
18660    /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18661    if( SCIPconsIsModifiable(cons) )
18662       return SCIP_OKAY;
18663 
18664    /* check for upgradability */
18665    if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18666       return SCIP_OKAY;
18667 
18668    /* get the constraint handler and check, if it's really a linear constraint */
18669    conshdlr = SCIPconsGetHdlr(cons);
18670    if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18671    {
18672       SCIPerrorMessage("constraint is not linear\n");
18673       return SCIP_INVALIDDATA;
18674    }
18675 
18676    /* get constraint handler data and constraint data */
18677    conshdlrdata = SCIPconshdlrGetData(conshdlr);
18678    assert(conshdlrdata != NULL);
18679    consdata = SCIPconsGetData(cons);
18680    assert(consdata != NULL);
18681 
18682    /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18683    if( consdata->upgraded )
18684       return SCIP_OKAY;
18685 
18686    /* check, if the constraint is already stored as LP row */
18687    if( consdata->row != NULL )
18688    {
18689       if( SCIProwIsInLP(consdata->row) )
18690       {
18691          SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18692          return SCIP_INVALIDDATA;
18693       }
18694       else
18695       {
18696          SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18697       }
18698    }
18699 
18700    /* normalize constraint */
18701    SCIP_CALL( normalizeCons(scip, cons, &infeasible) );
18702 
18703    /* normalizeCons() can only detect infeasibility when scaling with the gcd. in that case, the scaling was
18704     * skipped and we hope that the infeasibility gets detected later again.
18705     *
18706     * TODO: do we want to try to upgrade the constraint anyway?
18707     *
18708     * TODO: this needs to be fixed on master by changing the API and passing a pointer to whether the constraint is
18709     *       proven to be infeasible.
18710     */
18711    if( infeasible )   /*lint !e774*/
18712       return SCIP_OKAY;
18713 
18714    /* tighten sides */
18715    SCIP_CALL( tightenSides(scip, cons, &nchgsides, &infeasible) );
18716 
18717    if( infeasible )   /*lint !e774*/
18718       return SCIP_OKAY;
18719 
18720    /*
18721     * calculate some statistics on linear constraint
18722     */
18723 
18724    nposbin = 0;
18725    nnegbin = 0;
18726    nposint = 0;
18727    nnegint = 0;
18728    nposimpl = 0;
18729    nnegimpl = 0;
18730    nposimplbin = 0;
18731    nnegimplbin = 0;
18732    nposcont = 0;
18733    nnegcont = 0;
18734    ncoeffspone = 0;
18735    ncoeffsnone = 0;
18736    ncoeffspint = 0;
18737    ncoeffsnint = 0;
18738    ncoeffspfrac = 0;
18739    ncoeffsnfrac = 0;
18740    integral = TRUE;
18741    poscoeffsum = 0.0;
18742    negcoeffsum = 0.0;
18743 
18744    for( i = 0; i < consdata->nvars; ++i )
18745    {
18746       var = consdata->vars[i];
18747       val = consdata->vals[i];
18748       lb = SCIPvarGetLbLocal(var);
18749       ub = SCIPvarGetUbLocal(var);
18750       assert(!SCIPisZero(scip, val));
18751 
18752       switch( SCIPvarGetType(var) )
18753       {
18754       case SCIP_VARTYPE_BINARY:
18755          if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18756             integral = integral && SCIPisIntegral(scip, val);
18757          if( val >= 0.0 )
18758             nposbin++;
18759          else
18760             nnegbin++;
18761          break;
18762       case SCIP_VARTYPE_INTEGER:
18763          if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18764             integral = integral && SCIPisIntegral(scip, val);
18765          if( val >= 0.0 )
18766             nposint++;
18767          else
18768             nnegint++;
18769          break;
18770       case SCIP_VARTYPE_IMPLINT:
18771          if( SCIPvarIsBinary(var) )
18772          {
18773             if( val >= 0.0 )
18774                nposimplbin++;
18775             else
18776                nnegimplbin++;
18777          }
18778          if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18779             integral = integral && SCIPisIntegral(scip, val);
18780          if( val >= 0.0 )
18781             nposimpl++;
18782          else
18783             nnegimpl++;
18784          break;
18785       case SCIP_VARTYPE_CONTINUOUS:
18786          integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18787          if( val >= 0.0 )
18788             nposcont++;
18789          else
18790             nnegcont++;
18791          break;
18792       default:
18793          SCIPerrorMessage("unknown variable type\n");
18794          return SCIP_INVALIDDATA;
18795       }
18796       if( SCIPisEQ(scip, val, 1.0) )
18797          ncoeffspone++;
18798       else if( SCIPisEQ(scip, val, -1.0) )
18799          ncoeffsnone++;
18800       else if( SCIPisIntegral(scip, val) )
18801       {
18802          if( SCIPisPositive(scip, val) )
18803             ncoeffspint++;
18804          else
18805             ncoeffsnint++;
18806       }
18807       else
18808       {
18809          if( SCIPisPositive(scip, val) )
18810             ncoeffspfrac++;
18811          else
18812             ncoeffsnfrac++;
18813       }
18814       if( SCIPisPositive(scip, val) )
18815          poscoeffsum += val;
18816       else
18817          negcoeffsum += val;
18818    }
18819 
18820    /*
18821     * call the upgrading methods
18822     */
18823 
18824    SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18825       SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18826    SCIPdebugMsg(scip, " +bin=%d -bin=%d +int=%d -int=%d +impl=%d -impl=%d +cont=%d -cont=%d +1=%d -1=%d +I=%d -I=%d +F=%d -F=%d possum=%.15g negsum=%.15g integral=%u\n",
18827       nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18828       ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18829       poscoeffsum, negcoeffsum, integral);
18830 
18831    /* try all upgrading methods in priority order in case the upgrading step is enable  */
18832    for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18833    {
18834       if( conshdlrdata->linconsupgrades[i]->active )
18835       {
18836          SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18837                consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18838                nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18839                ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18840                poscoeffsum, negcoeffsum, integral,
18841                upgdcons) );
18842       }
18843    }
18844 
18845 #ifdef SCIP_DEBUG
18846    if( *upgdcons != NULL )
18847    {
18848       SCIPdebugPrintCons(scip, cons, NULL);
18849       SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18850       SCIPdebugPrintCons(scip, *upgdcons, NULL);
18851    }
18852 #endif
18853 
18854    return SCIP_OKAY; /*lint !e438*/
18855 }
18856 
18857 /** cleans up (multi-)aggregations and fixings from linear constraints */
SCIPcleanupConssLinear(SCIP * scip,SCIP_Bool onlychecked,SCIP_Bool * infeasible)18858 SCIP_RETCODE SCIPcleanupConssLinear(
18859    SCIP*                 scip,               /**< SCIP data structure */
18860    SCIP_Bool             onlychecked,        /**< should only checked constraints be cleaned up? */
18861    SCIP_Bool*            infeasible          /**< pointer to return whether the problem was detected to be infeasible */
18862    )
18863 {
18864    SCIP_CONSHDLR* conshdlr;
18865    SCIP_CONS** conss;
18866    int nconss;
18867    int i;
18868 
18869    conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
18870    if( conshdlr == NULL )
18871       return SCIP_OKAY;
18872 
18873    assert(infeasible != NULL);
18874    *infeasible = FALSE;
18875 
18876    nconss = onlychecked ? SCIPconshdlrGetNCheckConss(conshdlr) : SCIPconshdlrGetNActiveConss(conshdlr);
18877    conss = onlychecked ? SCIPconshdlrGetCheckConss(conshdlr) : SCIPconshdlrGetConss(conshdlr);
18878 
18879    for( i = 0; i < nconss; ++i )
18880    {
18881       SCIP_CALL( applyFixings(scip, conss[i], infeasible) );
18882 
18883       if( *infeasible )
18884          break;
18885    }
18886 
18887    return SCIP_OKAY;
18888 }
18889