Scippy

SCIP

Solving Constraint Integer Programs

cons_linear.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2017 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_linear.c
17  * @brief Constraint handler for linear constraints in their most general form, \f$lhs <= a^T x <= rhs\f$.
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Marc Pfetsch
21  * @author Kati Wolter
22  * @author Michael Winkler
23  * @author Gerald Gamrath
24  * @author Domenico Salvagnin
25  *
26  * Linear constraints are separated with a high priority, because they are easy
27  * to separate. Instead of using the global cut pool, the same effect can be
28  * implemented by adding linear constraints to the root node, such that they are
29  * separated each time, the linear constraints are separated. A constraint
30  * handler, which generates linear constraints in this way should have a lower
31  * separation priority than the linear constraint handler, and it should have a
32  * separation frequency that is a multiple of the frequency of the linear
33  * constraint handler. In this way, it can be avoided to separate the same cut
34  * twice, because if a separation run of the handler is always preceded by a
35  * separation of the linear constraints, the priorily added constraints are
36  * always satisfied.
37  *
38  * Linear constraints are enforced and checked with a very low priority. Checking
39  * of (many) linear constraints is much more involved than checking the solution
40  * values for integrality. Because we are separating the linear constraints quite
41  * often, it is only necessary to enforce them for integral solutions. A constraint
42  * handler which generates pool cuts in its enforcing method should have an
43  * enforcing priority smaller than that of the linear constraint handler to avoid
44  * regenerating constraints which already exist.
45  */
46 
47 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
48 
49 #include <assert.h>
50 #include <string.h>
51 #include <limits.h>
52 #include <ctype.h>
53 
54 #include "scip/cons_linear.h"
55 #include "scip/cons_knapsack.h"
56 #include "scip/cons_quadratic.h"
57 #include "scip/cons_nonlinear.h"
58 #include "scip/pub_misc.h"
59 #include "scip/debug.h"
60 
61 #define CONSHDLR_NAME "linear"
62 #define CONSHDLR_DESC "linear constraints of the form lhs <= a^T x <= rhs"
63 #define CONSHDLR_SEPAPRIORITY +100000 /**< priority of the constraint handler for separation */
64 #define CONSHDLR_ENFOPRIORITY -1000000 /**< priority of the constraint handler for constraint enforcing */
65 #define CONSHDLR_CHECKPRIORITY -1000000 /**< priority of the constraint handler for checking feasibility */
66 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
67 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
68 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
69  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
70 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
71 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
72 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
73 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
74 
75 #define CONSHDLR_PRESOLTIMING (SCIP_PRESOLTIMING_FAST | SCIP_PRESOLTIMING_EXHAUSTIVE) /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
76 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
77 
78 #define EVENTHDLR_NAME "linear"
79 #define EVENTHDLR_DESC "bound change event handler for linear constraints"
80 
81 #define CONFLICTHDLR_NAME "linear"
82 #define CONFLICTHDLR_DESC "conflict handler creating linear constraints"
83 #define CONFLICTHDLR_PRIORITY -1000000
84 
85 #define DEFAULT_TIGHTENBOUNDSFREQ 1 /**< multiplier on propagation frequency, how often the bounds are tightened */
86 #define DEFAULT_MAXROUNDS 5 /**< maximal number of separation rounds per node (-1: unlimited) */
87 #define DEFAULT_MAXROUNDSROOT -1 /**< maximal number of separation rounds in the root node (-1: unlimited) */
88 #define DEFAULT_MAXSEPACUTS 50 /**< maximal number of cuts separated per separation round */
89 #define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of cuts separated per separation round in root node */
90 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
91 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
92 #define DEFAULT_NMINCOMPARISONS 200000 /**< number for minimal pairwise presolving comparisons */
93 #define DEFAULT_MINGAINPERNMINCOMP 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise
94  * comparison round */
95 #define DEFAULT_SORTVARS TRUE /**< should variables be sorted after presolve w.r.t their coefficient absolute for faster
96  * propagation? */
97 #define DEFAULT_CHECKRELMAXABS FALSE /**< should the violation for a constraint with side 0.0 be checked relative
98  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
99 #define DEFAULT_MAXAGGRNORMSCALE 0.0 /**< maximal allowed relative gain in maximum norm for constraint aggregation
100  * (0.0: disable constraint aggregation) */
101 #define DEFAULT_MAXEASYACTIVITYDELTA 1e6 /**< maximum activity delta to run easy propagation on linear constraint
102  * (faster, but numerically less stable) */
103 #define DEFAULT_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
104  * to best node's dual bound for separating knapsack cardinality cuts */
105 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
106  * the ones with non-zero dual value? */
107 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
108 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
109 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
110 #define DEFAULT_SINGLETONSTUFFING TRUE /**< should stuffing of singleton continuous variables be performed? */
111 #define DEFAULT_SINGLEVARSTUFFING FALSE /**< should single variable stuffing be performed, which tries to fulfill
112  * constraints using the cheapest variable? */
113 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
114  * function defining an upper bound and prevent these constraints from
115  * entering the LP */
116 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
117  * function defining a lower bound and prevent these constraints from
118  * entering the LP */
119 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
120  * objective function */
121 #define DEFAULT_RANGEDROWPROPAGATION TRUE /**< should we perform ranged row propagation */
122 #define DEFAULT_RANGEDROWARTCONS TRUE /**< should presolving and propagation extract sub-constraints from ranged rows and equations? */
123 #define DEFAULT_RANGEDROWMAXDEPTH INT_MAX /**< maximum depth to apply ranged row propagation */
124 #define DEFAULT_RANGEDROWFREQ 1 /**< frequency for applying ranged row propagation */
125 
126 #define DEFAULT_MULTAGGRREMOVE FALSE /**< should multi-aggregations only be performed if the constraint can be
127  * removed afterwards? */
128 
129 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
130 #define MAXSCALEDCOEF 1e+03 /**< maximal coefficient value after scaling */
131 #define MAXSCALEDCOEFINTEGER 1e+05 /**< maximal coefficient value after scaling if all variables are of integral
132  * type
133  */
134 
135 #define HASHSIZE_LINEARCONS 500 /**< minimal size of hash table in linear constraint tables */
136 #define MAXVALRECOMP 1e+06 /**< maximal abolsute value we trust without recomputing the activity */
137 #define MINVALRECOMP 1e-05 /**< minimal abolsute value we trust without recomputing the activity */
139 
140 #define QUADCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of quadratic constraints */
141 #define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of nonlinear constraints */
142 
143 #ifdef WITH_PRINTORIGCONSTYPES
144 /** constraint type */
145 enum SCIP_Constype
146 {
147  SCIP_CONSTYPE_EMPTY = 0, /**< */
148  SCIP_CONSTYPE_FREE = 1, /**< */
149  SCIP_CONSTYPE_SINGLETON = 2, /**< */
150  SCIP_CONSTYPE_AGGREGATION = 3, /**< */
151  SCIP_CONSTYPE_VARBOUND = 4, /**< */
152  SCIP_CONSTYPE_SETPARTITION = 5, /**< */
153  SCIP_CONSTYPE_SETPACKING = 6, /**< */
154  SCIP_CONSTYPE_SETCOVERING = 7, /**< */
155  SCIP_CONSTYPE_CARDINALITY = 8, /**< */
156  SCIP_CONSTYPE_INVKNAPSACK = 9, /**< */
157  SCIP_CONSTYPE_EQKNAPSACK = 10, /**< */
158  SCIP_CONSTYPE_BINPACKING = 11, /**< */
159  SCIP_CONSTYPE_KNAPSACK = 12, /**< */
160  SCIP_CONSTYPE_INTKNAPSACK = 13, /**< */
161  SCIP_CONSTYPE_MIXEDBINARY = 14, /**< */
162  SCIP_CONSTYPE_GENERAL = 15 /**< */
163 };
164 typedef enum SCIP_Constype SCIP_CONSTYPE;
165 #endif
166 
167 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
168  * maybe in fullDualPresolve(), see convertLongEquality()
169  */
170 
171 
172 /** constraint data for linear constraints */
173 struct SCIP_ConsData
174 {
175  SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
176  SCIP_Real rhs; /**< right hand side of row */
177  SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
178  SCIP_Real minabsval; /**< minimal absolute value of all coefficients */
179  SCIP_Real minactivity; /**< minimal value w.r.t. the variable's local bounds for the constraint's
180  * activity, ignoring the coefficients contributing with infinite value */
181  SCIP_Real maxactivity; /**< maximal value w.r.t. the variable's local bounds for the constraint's
182  * activity, ignoring the coefficients contributing with infinite value */
183  SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
184  * over all contributing values */
185  SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
186  * over all contributing values */
187  SCIP_Real glbminactivity; /**< minimal value w.r.t. the variable's global bounds for the constraint's
188  * activity, ignoring the coefficients contributing with infinite value */
189  SCIP_Real glbmaxactivity; /**< maximal value w.r.t. the variable's global bounds for the constraint's
190  * activity, ignoring the coefficients contributing with infinite value */
191  SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
192  * over all contributing values */
193  SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
194  * over all contributing values */
195  SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
196  SCIP_VAR* maxactdeltavar; /**< variable with maximal activity contribution, or NULL if invalid */
197  uint64_t possignature; /**< bit signature of coefficients that may take a positive value */
198  uint64_t negsignature; /**< bit signature of coefficients that may take a negative value */
199  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
200  SCIP_VAR** vars; /**< variables of constraint entries */
201  SCIP_Real* vals; /**< coefficients of constraint entries */
202  SCIP_EVENTDATA** eventdata; /**< event data for bound change events of the variables */
203  int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
204  int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
205  int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
206  int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
207  int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
208  int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
209  int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
210  int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
211  int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
212  int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
213  int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
214  int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
215  int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
216  int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
217  int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
218  int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
219  int varssize; /**< size of the vars- and vals-arrays */
220  int nvars; /**< number of nonzeros in constraint */
221  int nbinvars; /**< the number of binary variables in the constraint, only valid after
222  * sorting in stage >= SCIP_STAGE_INITSOLVE
223  */
224  unsigned int boundstightened:2; /**< is constraint already propagated with bound tightening? */
225  unsigned int rangedrowpropagated:2; /**< did we perform ranged row propagation on this constraint?
226  * (0: no, 1: yes, 2: with potentially adding artificial constraint */
227  unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
228  unsigned int validminabsval:1; /**< is the minimum absolute value valid? */
229  unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
230  unsigned int validminact:1; /**< is the local minactivity valid? */
231  unsigned int validmaxact:1; /**< is the local maxactivity valid? */
232  unsigned int validglbminact:1; /**< is the global minactivity valid? */
233  unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
234  unsigned int presolved:1; /**< is constraint already presolved? */
235  unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
236  unsigned int validsignature:1; /**< is the bit signature valid? */
237  unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
238  unsigned int normalized:1; /**< is the constraint in normalized form? */
239  unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
240  unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
241  unsigned int sorted:1; /**< are the constraint's variables sorted? */
242  unsigned int merged:1; /**< are the constraint's equal variables already merged? */
243  unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
244  unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
245  unsigned int binvarssorted:1; /**< are binary variables sorted w.r.t. the absolute of their coefficient? */
246  unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
247  unsigned int hascontvar:1; /**< does the constraint contain at least one continuous variable? */
248  unsigned int hasnonbinvar:1; /**< does the constraint contain at least one non-binary variable? */
249  unsigned int hasnonbinvalid:1; /**< is the information stored in hasnonbinvar and hascontvar valid? */
250 };
251 
252 /** event data for bound change event */
253 struct SCIP_EventData
254 {
255  SCIP_CONS* cons; /**< linear constraint to process the bound change for */
256  int varpos; /**< position of variable in vars array */
257  int filterpos; /**< position of event in variable's event filter */
258 };
259 
260 /** constraint handler data */
261 struct SCIP_ConshdlrData
262 {
263  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
264  SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
265  SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
266  * (0.0: disable constraint aggregation) */
267  SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
268  * to best node's dual bound for separating knapsack cardinality cuts */
269  SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
270  SCIP_Real maxeasyactivitydelta;/**< maximum activity delta to run easy propagation on linear constraint
271  * (faster, but numerically less stable) */
272  int linconsupgradessize;/**< size of linconsupgrade array */
273  int nlinconsupgrades; /**< number of linear constraint upgrade methods */
274  int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
275  int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
276  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
277  int maxsepacuts; /**< maximal number of cuts separated per separation round */
278  int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
279  int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
280  int naddconss; /**< number of added constraints */
281  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
282  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
283  SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
284  * the ones with non-zero dual value? */
285  SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
286  SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
287  SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
288  SCIP_Bool singletonstuffing; /**< should stuffing of singleton continuous variables be performed? */
289  SCIP_Bool singlevarstuffing; /**< should single variable stuffing be performed, which tries to fulfill
290  * constraints using the cheapest variable? */
291  SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
292  SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
293  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
294  SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
295  * function defining an upper bound and prevent these constraints from
296  * entering the LP */
297  SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
298  * function defining a lower bound and prevent these constraints from
299  * entering the LP */
300  SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
301  * the objective function */
302  SCIP_Bool rangedrowpropagation;/**< should presolving and propagation try to improve bounds, detect
303  * infeasibility, and extract sub-constraints from ranged rows and
304  * equations */
305  SCIP_Bool rangedrowartcons; /**< should presolving and propagation extract sub-constraints from ranged rows and equations?*/
306  int rangedrowmaxdepth; /**< maximum depth to apply ranged row propagation */
307  int rangedrowfreq; /**< frequency for applying ranged row propagation */
308  SCIP_Bool multaggrremove; /**< should multi-aggregations only be performed if the constraint can be
309  * removed afterwards? */
310 };
311 
312 /** linear constraint update method */
313 struct SCIP_LinConsUpgrade
314 {
315  SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
316  int priority; /**< priority of upgrading method */
317  SCIP_Bool active; /**< is upgrading enabled */
318 };
319 
320 
321 /*
322  * Propagation rules
323  */
324 
325 enum Proprule
326 {
327  PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
328  * variable due to the right hand side of the inequality */
329  PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
330  * variable due to the left hand side of the inequality */
331  PROPRULE_1_RANGEDROW = 3, /**< fixed variables and gcd of all left variables tighten bounds of a
332  * single variable in this reanged row */
333  PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
334 };
335 typedef enum Proprule PROPRULE;
336 
337 /** inference information */
338 struct InferInfo
339 {
340  union
341  {
342  struct
343  {
344  unsigned int proprule:8; /**< propagation rule that was applied */
345  unsigned int pos:24; /**< variable position, the propagation rule was applied at */
346  } asbits;
347  int asint; /**< inference information as a single int value */
348  } val;
349 };
350 typedef struct InferInfo INFERINFO;
351 
352 /** converts an integer into an inference information */
353 static
355  int i /**< integer to convert */
356  )
357 {
358  INFERINFO inferinfo;
359 
360  inferinfo.val.asint = i;
361 
362  return inferinfo;
363 }
364 
365 /** converts an inference information into an int */
366 static
368  INFERINFO inferinfo /**< inference information to convert */
369  )
370 {
371  return inferinfo.val.asint;
372 }
373 
374 /** returns the propagation rule stored in the inference information */
375 static
377  INFERINFO inferinfo /**< inference information to convert */
378  )
379 {
380  return (int) inferinfo.val.asbits.proprule;
381 }
382 
383 /** returns the position stored in the inference information */
384 static
385 int inferInfoGetPos(
386  INFERINFO inferinfo /**< inference information to convert */
387  )
388 {
389  return (int) inferinfo.val.asbits.pos;
390 }
391 
392 /** constructs an inference information out of a propagation rule and a position number */
393 static
395  PROPRULE proprule, /**< propagation rule that deduced the value */
396  int pos /**< variable position, the propagation rule was applied at */
397  )
398 {
399  INFERINFO inferinfo;
400 
401  assert(pos >= 0);
402  /* in the inferinfo struct only 24 bits for 'pos' are reserved */
403  assert(pos < (1<<24));
404 
405  inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
406  inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
407 
408  return inferinfo;
409 }
410 
411 /** constructs an inference information out of a propagation rule and a position number, returns info as int */
412 static
413 int getInferInt(
414  PROPRULE proprule, /**< propagation rule that deduced the value */
415  int pos /**< variable position, the propagation rule was applied at */
416  )
417 {
418  return inferInfoToInt(getInferInfo(proprule, pos));
419 }
420 
421 
422 /*
423  * memory growing methods for dynamically allocated arrays
424  */
425 
426 /** ensures, that linconsupgrades array can store at least num entries */
427 static
429  SCIP* scip, /**< SCIP data structure */
430  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
431  int num /**< minimum number of entries to store */
432  )
433 {
434  assert(scip != NULL);
435  assert(conshdlrdata != NULL);
436  assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
437 
438  if( num > conshdlrdata->linconsupgradessize )
439  {
440  int newsize;
441 
442  newsize = SCIPcalcMemGrowSize(scip, num);
443  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &conshdlrdata->linconsupgrades, conshdlrdata->linconsupgradessize, newsize) );
444  conshdlrdata->linconsupgradessize = newsize;
445  }
446  assert(num <= conshdlrdata->linconsupgradessize);
447 
448  return SCIP_OKAY;
449 }
450 
451 /** ensures, that vars and vals arrays can store at least num entries */
452 static
454  SCIP* scip, /**< SCIP data structure */
455  SCIP_CONSDATA* consdata, /**< linear constraint data */
456  int num /**< minimum number of entries to store */
457  )
458 {
459  assert(scip != NULL);
460  assert(consdata != NULL);
461  assert(consdata->nvars <= consdata->varssize);
462 
463  if( num > consdata->varssize )
464  {
465  int newsize;
466 
467  newsize = SCIPcalcMemGrowSize(scip, num);
468  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
469  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
470  if( consdata->eventdata != NULL )
471  {
472  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize, newsize) );
473  }
474  consdata->varssize = newsize;
475  }
476  assert(num <= consdata->varssize);
477 
478  return SCIP_OKAY;
479 }
480 
481 
482 /*
483  * local methods for managing linear constraint update methods
484  */
485 
486 /** creates a linear constraint upgrade data object */
487 static
489  SCIP* scip, /**< SCIP data structure */
490  SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
491  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
492  int priority /**< priority of upgrading method */
493  )
494 {
495  assert(scip != NULL);
496  assert(linconsupgrade != NULL);
497  assert(linconsupgd != NULL);
498 
499  SCIP_CALL( SCIPallocBlockMemory(scip, linconsupgrade) );
500  (*linconsupgrade)->linconsupgd = linconsupgd;
501  (*linconsupgrade)->priority = priority;
502  (*linconsupgrade)->active = TRUE;
503 
504  return SCIP_OKAY;
505 }
506 
507 /** frees a linear constraint upgrade data object */
508 static
509 void linconsupgradeFree(
510  SCIP* scip, /**< SCIP data structure */
511  SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
512  )
513 {
514  assert(scip != NULL);
515  assert(linconsupgrade != NULL);
516  assert(*linconsupgrade != NULL);
517 
518  SCIPfreeBlockMemory(scip, linconsupgrade);
519 }
520 
521 /** creates constraint handler data for linear constraint handler */
522 static
524  SCIP* scip, /**< SCIP data structure */
525  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
526  SCIP_EVENTHDLR* eventhdlr /**< event handler */
527  )
528 {
529  assert(scip != NULL);
530  assert(conshdlrdata != NULL);
531  assert(eventhdlr != NULL);
532 
533  SCIP_CALL( SCIPallocBlockMemory(scip, conshdlrdata) );
534  (*conshdlrdata)->linconsupgrades = NULL;
535  (*conshdlrdata)->linconsupgradessize = 0;
536  (*conshdlrdata)->nlinconsupgrades = 0;
537  (*conshdlrdata)->naddconss = 0;
538 
539  /* set event handler for updating linear constraint activity bounds */
540  (*conshdlrdata)->eventhdlr = eventhdlr;
541 
542  return SCIP_OKAY;
543 }
544 
545 /** frees constraint handler data for linear constraint handler */
546 static
547 void conshdlrdataFree(
548  SCIP* scip, /**< SCIP data structure */
549  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
550  )
551 {
552  int i;
553 
554  assert(scip != NULL);
555  assert(conshdlrdata != NULL);
556  assert(*conshdlrdata != NULL);
557 
558  for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
559  {
560  linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
561  }
562  SCIPfreeBlockMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades, (*conshdlrdata)->linconsupgradessize);
563 
564  SCIPfreeBlockMemory(scip, conshdlrdata);
565 }
566 
567 /** creates a linear constraint upgrade data object */
568 static
570  SCIP* scip, /**< SCIP data structure */
571  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
572  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
573  const char* conshdlrname /**< name of the constraint handler */
574  )
575 {
576  int i;
577 
578  assert(scip != NULL);
579  assert(conshdlrdata != NULL);
580  assert(linconsupgd != NULL);
581  assert(conshdlrname != NULL);
582 
583  for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
584  {
585  if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
586  {
587 #ifdef SCIP_DEBUG
588  SCIPwarningMessage(scip, "Try to add already known upgrade message %p for constraint handler %s.\n", linconsupgd, conshdlrname);
589 #endif
590  return TRUE;
591  }
592  }
593 
594  return FALSE;
595 }
596 
597 /** adds a linear constraint update method to the constraint handler's data */
598 static
600  SCIP* scip, /**< SCIP data structure */
601  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
602  SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
603  )
604 {
605  int i;
606 
607  assert(scip != NULL);
608  assert(conshdlrdata != NULL);
609  assert(linconsupgrade != NULL);
610 
611  SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
612 
613  for( i = conshdlrdata->nlinconsupgrades;
614  i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
615  {
616  conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
617  }
618  assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
619  conshdlrdata->linconsupgrades[i] = linconsupgrade;
620  conshdlrdata->nlinconsupgrades++;
621 
622  return SCIP_OKAY;
623 }
624 
625 /*
626  * local methods
627  */
628 
629 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
630 static
632  SCIP* scip, /**< SCIP data structure */
633  SCIP_CONS* cons, /**< linear constraint */
634  SCIP_VAR* var, /**< variable of constraint entry */
635  SCIP_Real val /**< coefficient of constraint entry */
636  )
637 {
638  SCIP_CONSDATA* consdata;
639 
640  assert(scip != NULL);
641  assert(cons != NULL);
642  assert(var != NULL);
643 
644  consdata = SCIPconsGetData(cons);
645  assert(consdata != NULL);
646  assert(!SCIPisZero(scip, val));
647 
648  if( SCIPisPositive(scip, val) )
649  {
650  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
651  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
652  }
653  else
654  {
655  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
656  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
657  }
658 
659  return SCIP_OKAY;
660 }
661 
662 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
663 static
665  SCIP* scip, /**< SCIP data structure */
666  SCIP_CONS* cons, /**< linear constraint */
667  SCIP_VAR* var, /**< variable of constraint entry */
668  SCIP_Real val /**< coefficient of constraint entry */
669  )
670 {
671  SCIP_CONSDATA* consdata;
672 
673  assert(scip != NULL);
674  assert(cons != NULL);
675  assert(var != NULL);
676 
677  consdata = SCIPconsGetData(cons);
678  assert(consdata != NULL);
679  assert(!SCIPisZero(scip, val));
680 
681  if( SCIPisPositive(scip, val) )
682  {
683  SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
684  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
685  }
686  else
687  {
688  SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
689  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
690  }
691 
692  return SCIP_OKAY;
693 }
694 
695 /** creates event data for variable at given position, and catches events */
696 /**! [SnippetDebugAssertions] */
697 static
699  SCIP* scip, /**< SCIP data structure */
700  SCIP_CONS* cons, /**< linear constraint */
701  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
702  int pos /**< array position of variable to catch bound change events for */
703  )
704 {
705  SCIP_CONSDATA* consdata;
706  assert(scip != NULL);
707  assert(cons != NULL);
708  assert(eventhdlr != NULL);
709 
710  consdata = SCIPconsGetData(cons);
711  assert(consdata != NULL);
712 
713  assert(0 <= pos && pos < consdata->nvars);
714  assert(consdata->vars != NULL);
715  assert(consdata->vars[pos] != NULL);
716  assert(SCIPvarIsTransformed(consdata->vars[pos]));
717  assert(consdata->eventdata != NULL);
718  assert(consdata->eventdata[pos] == NULL);
719 
720  SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdata[pos])) ); /*lint !e866*/
721  consdata->eventdata[pos]->cons = cons;
722  consdata->eventdata[pos]->varpos = pos;
723 
724  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
727  eventhdlr, consdata->eventdata[pos], &consdata->eventdata[pos]->filterpos) );
728 
729  return SCIP_OKAY;
730 }
731 /**! [SnippetDebugAssertions] */
732 
733 /** deletes event data for variable at given position, and drops events */
734 static
736  SCIP* scip, /**< SCIP data structure */
737  SCIP_CONS* cons, /**< linear constraint */
738  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
739  int pos /**< array position of variable to catch bound change events for */
740  )
741 {
742  SCIP_CONSDATA* consdata;
743  assert(scip != NULL);
744  assert(cons != NULL);
745  assert(eventhdlr != NULL);
746 
747  consdata = SCIPconsGetData(cons);
748  assert(consdata != NULL);
749 
750  assert(0 <= pos && pos < consdata->nvars);
751  assert(consdata->vars[pos] != NULL);
752  assert(consdata->eventdata != NULL);
753  assert(consdata->eventdata[pos] != NULL);
754  assert(consdata->eventdata[pos]->cons == cons);
755  assert(consdata->eventdata[pos]->varpos == pos);
756 
757  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
760  eventhdlr, consdata->eventdata[pos], consdata->eventdata[pos]->filterpos) );
761 
762  SCIPfreeBlockMemory(scip, &consdata->eventdata[pos]); /*lint !e866*/
763 
764  return SCIP_OKAY;
765 }
766 
767 /** catches bound change events for all variables in transformed linear constraint */
768 static
770  SCIP* scip, /**< SCIP data structure */
771  SCIP_CONS* cons, /**< linear constraint */
772  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
773  )
774 {
775  SCIP_CONSDATA* consdata;
776  int i;
777 
778  assert(scip != NULL);
779  assert(cons != NULL);
780 
781  consdata = SCIPconsGetData(cons);
782  assert(consdata != NULL);
783  assert(consdata->eventdata == NULL);
784 
785  /* allocate eventdata array */
786  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize) );
787  assert(consdata->eventdata != NULL);
788  BMSclearMemoryArray(consdata->eventdata, consdata->nvars);
789 
790  /* catch event for every single variable */
791  for( i = 0; i < consdata->nvars; ++i )
792  {
793  SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
794  }
795 
796  return SCIP_OKAY;
797 }
798 
799 /** drops bound change events for all variables in transformed linear constraint */
800 static
802  SCIP* scip, /**< SCIP data structure */
803  SCIP_CONS* cons, /**< linear constraint */
804  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
805  )
806 {
807  SCIP_CONSDATA* consdata;
808  int i;
809 
810  assert(scip != NULL);
811  assert(cons != NULL);
812 
813  consdata = SCIPconsGetData(cons);
814  assert(consdata != NULL);
815  assert(consdata->eventdata != NULL);
816 
817  /* drop event of every single variable */
818  for( i = consdata->nvars - 1; i >= 0; --i )
819  {
820  SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
821  }
822 
823  /* free eventdata array */
824  SCIPfreeBlockMemoryArray(scip, &consdata->eventdata, consdata->varssize);
825  assert(consdata->eventdata == NULL);
826 
827  return SCIP_OKAY;
828 }
829 
830 /** returns whether we are in a stage, where the variable events should be caught */
831 static
833  SCIP* scip /**< SCIP data structure */
834  )
835 {
836  assert(scip != NULL);
837 
839 }
840 
841 /** creates a linear constraint data */
842 static
844  SCIP* scip, /**< SCIP data structure */
845  SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
846  int nvars, /**< number of nonzeros in the constraint */
847  SCIP_VAR** vars, /**< array with variables of constraint entries */
848  SCIP_Real* vals, /**< array with coefficients of constraint entries */
849  SCIP_Real lhs, /**< left hand side of row */
850  SCIP_Real rhs /**< right hand side of row */
851  )
852 {
853  int v;
854  SCIP_Real constant;
855 
856  assert(scip != NULL);
857  assert(consdata != NULL);
858  assert(nvars == 0 || vars != NULL);
859  assert(nvars == 0 || vals != NULL);
861  if( SCIPisInfinity(scip, rhs) )
862  rhs = SCIPinfinity(scip);
863  else if( SCIPisInfinity(scip, -rhs) )
864  rhs = -SCIPinfinity(scip);
865 
866  if( SCIPisInfinity(scip, -lhs) )
867  lhs = -SCIPinfinity(scip);
868  else if( SCIPisInfinity(scip, lhs) )
869  lhs = SCIPinfinity(scip);
870 
871  if( SCIPisGT(scip, lhs, rhs) )
872  {
873  SCIPwarningMessage(scip, "left hand side of linear constraint greater than right hand side\n");
874  SCIPwarningMessage(scip, " -> lhs=%g, rhs=%g\n", lhs, rhs);
875  }
876 
877  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
878 
879  (*consdata)->varssize = 0;
880  (*consdata)->nvars = nvars;
881  (*consdata)->hascontvar = FALSE;
882  (*consdata)->hasnonbinvar = FALSE;
883  (*consdata)->hasnonbinvalid = TRUE;
884  (*consdata)->vars = NULL;
885  (*consdata)->vals = NULL;
886 
887  constant = 0.0;
888  if( nvars > 0 )
889  {
890  int k;
891 
892  SCIP_VAR** varsbuffer;
893  SCIP_Real* valsbuffer;
894 
895  /* copy variables into temporary buffer */
896  SCIP_CALL( SCIPallocBufferArray(scip, &varsbuffer, nvars) );
897  SCIP_CALL( SCIPallocBufferArray(scip, &valsbuffer, nvars) );
898  k = 0;
899 
900  /* loop over variables and sort out fixed ones */
901  for( v = 0; v < nvars; ++v )
902  {
903  SCIP_VAR* var;
904  SCIP_Real val;
905 
906  var = vars[v];
907  val = vals[v];
908 
909  assert(var != NULL);
910  if( !SCIPisZero(scip, val) )
911  {
912  /* treat fixed variable as a constant if problem compression is enabled */
914  {
915  constant += SCIPvarGetLbGlobal(var) * val;
916  }
917  else
918  {
919  varsbuffer[k] = var;
920  valsbuffer[k] = val;
921  k++;
922 
923  /* update hascontvar and hasnonbinvar flags */
924  if( !(*consdata)->hascontvar )
925  {
926  SCIP_VARTYPE vartype = SCIPvarGetType(var);
927 
928  if( vartype != SCIP_VARTYPE_BINARY )
929  {
930  (*consdata)->hasnonbinvar = TRUE;
931 
932  if( vartype == SCIP_VARTYPE_CONTINUOUS )
933  (*consdata)->hascontvar = TRUE;
934  }
935  }
936  }
937  }
938  }
939  (*consdata)->nvars = k;
940 
941  if( k > 0 )
942  {
943  /* copy the possibly reduced buffer arrays into block */
944  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, varsbuffer, k) );
945  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, valsbuffer, k) );
946  (*consdata)->varssize = k;
947  }
948  /* free temporary buffer */
949  SCIPfreeBufferArray(scip, &valsbuffer);
950  SCIPfreeBufferArray(scip, &varsbuffer);
951  }
952 
953  (*consdata)->eventdata = NULL;
954 
955  /* due to compressed copying, we may have fixed variables contributing to the left and right hand side */
956  if( !SCIPisZero(scip, constant) )
957  {
958  if( !SCIPisInfinity(scip, REALABS(lhs)) )
959  lhs -= constant;
960 
961  if( !SCIPisInfinity(scip, REALABS(rhs)) )
962  rhs -= constant;
963  }
964 
965  (*consdata)->row = NULL;
966  (*consdata)->lhs = lhs;
967  (*consdata)->rhs = rhs;
968  (*consdata)->maxabsval = SCIP_INVALID;
969  (*consdata)->minabsval = SCIP_INVALID;
970  (*consdata)->minactivity = SCIP_INVALID;
971  (*consdata)->maxactivity = SCIP_INVALID;
972  (*consdata)->lastminactivity = SCIP_INVALID;
973  (*consdata)->lastmaxactivity = SCIP_INVALID;
974  (*consdata)->maxactdelta = SCIP_INVALID;
975  (*consdata)->maxactdeltavar = NULL;
976  (*consdata)->minactivityneginf = -1;
977  (*consdata)->minactivityposinf = -1;
978  (*consdata)->maxactivityneginf = -1;
979  (*consdata)->maxactivityposinf = -1;
980  (*consdata)->minactivityneghuge = -1;
981  (*consdata)->minactivityposhuge = -1;
982  (*consdata)->maxactivityneghuge = -1;
983  (*consdata)->maxactivityposhuge = -1;
984  (*consdata)->glbminactivity = SCIP_INVALID;
985  (*consdata)->glbmaxactivity = SCIP_INVALID;
986  (*consdata)->lastglbminactivity = SCIP_INVALID;
987  (*consdata)->lastglbmaxactivity = SCIP_INVALID;
988  (*consdata)->glbminactivityneginf = -1;
989  (*consdata)->glbminactivityposinf = -1;
990  (*consdata)->glbmaxactivityneginf = -1;
991  (*consdata)->glbmaxactivityposinf = -1;
992  (*consdata)->glbminactivityneghuge = -1;
993  (*consdata)->glbminactivityposhuge = -1;
994  (*consdata)->glbmaxactivityneghuge = -1;
995  (*consdata)->glbmaxactivityposhuge = -1;
996  (*consdata)->possignature = 0;
997  (*consdata)->negsignature = 0;
998  (*consdata)->validmaxabsval = FALSE;
999  (*consdata)->validminabsval = FALSE;
1000  (*consdata)->validactivities = FALSE;
1001  (*consdata)->validminact = FALSE;
1002  (*consdata)->validmaxact = FALSE;
1003  (*consdata)->validglbminact = FALSE;
1004  (*consdata)->validglbmaxact = FALSE;
1005  (*consdata)->boundstightened = 0;
1006  (*consdata)->presolved = FALSE;
1007  (*consdata)->removedfixings = FALSE;
1008  (*consdata)->validsignature = FALSE;
1009  (*consdata)->changed = TRUE;
1010  (*consdata)->normalized = FALSE;
1011  (*consdata)->upgradetried = FALSE;
1012  (*consdata)->upgraded = FALSE;
1013  (*consdata)->sorted = (nvars <= 1);
1014  (*consdata)->merged = (nvars <= 1);
1015  (*consdata)->cliquesadded = FALSE;
1016  (*consdata)->implsadded = FALSE;
1017  (*consdata)->binvarssorted = FALSE;
1018  (*consdata)->nbinvars = -1;
1019  (*consdata)->varsdeleted = FALSE;
1020  (*consdata)->rangedrowpropagated = 0;
1021 
1022  if( SCIPisTransformed(scip) )
1023  {
1024  /* get transformed variables */
1025  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
1026  }
1027 
1028  /* capture variables */
1029  for( v = 0; v < (*consdata)->nvars; v++ )
1030  {
1031  assert((*consdata)->vars[v] != NULL);
1032  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1033  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
1034  }
1035 
1036  return SCIP_OKAY;
1037 }
1038 
1039 /** frees a linear constraint data */
1040 static
1042  SCIP* scip, /**< SCIP data structure */
1043  SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
1044  )
1045 {
1046  int v;
1047 
1048  assert(scip != NULL);
1049  assert(consdata != NULL);
1050  assert(*consdata != NULL);
1051  assert((*consdata)->varssize >= 0);
1052 
1053  /* release the row */
1054  if( (*consdata)->row != NULL )
1055  {
1056  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1057  }
1059  /* release variables */
1060  for( v = 0; v < (*consdata)->nvars; v++ )
1061  {
1062  assert((*consdata)->vars[v] != NULL);
1063  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
1064  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
1065  }
1066 
1067  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
1068  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
1069  SCIPfreeBlockMemory(scip, consdata);
1070 
1071  return SCIP_OKAY;
1072 }
1073 
1074 /** prints linear constraint in CIP format to file stream */
1075 static
1077  SCIP* scip, /**< SCIP data structure */
1078  SCIP_CONSDATA* consdata, /**< linear constraint data */
1079  FILE* file /**< output file (or NULL for standard output) */
1080  )
1081 {
1082  assert(scip != NULL);
1083  assert(consdata != NULL);
1084 
1085  /* print left hand side for ranged rows */
1086  if( !SCIPisInfinity(scip, -consdata->lhs)
1087  && !SCIPisInfinity(scip, consdata->rhs)
1088  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1089  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
1090 
1091  /* print coefficients and variables */
1092  if( consdata->nvars == 0 )
1093  SCIPinfoMessage(scip, file, "0");
1094  else
1095  {
1096  /* post linear sum of the linear constraint */
1097  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
1098  }
1099 
1100  /* print right hand side */
1101  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
1102  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
1103  else if( !SCIPisInfinity(scip, consdata->rhs) )
1104  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1105  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1106  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1107  else
1108  SCIPinfoMessage(scip, file, " [free]");
1109 
1110  return SCIP_OKAY;
1111 }
1112 
1113 /** invalidates activity bounds, such that they are recalculated in next get */
1114 static
1116  SCIP_CONSDATA* consdata /**< linear constraint */
1117  )
1118 {
1119  assert(consdata != NULL);
1120 
1121  consdata->validactivities = FALSE;
1122  consdata->validminact = FALSE;
1123  consdata->validmaxact = FALSE;
1124  consdata->validglbminact = FALSE;
1125  consdata->validglbmaxact = FALSE;
1126  consdata->validmaxabsval = FALSE;
1127  consdata->validminabsval = FALSE;
1128  consdata->hasnonbinvalid = FALSE;
1129  consdata->minactivity = SCIP_INVALID;
1130  consdata->maxactivity = SCIP_INVALID;
1131  consdata->lastminactivity = SCIP_INVALID;
1132  consdata->lastmaxactivity = SCIP_INVALID;
1133  consdata->maxabsval = SCIP_INVALID;
1134  consdata->minabsval = SCIP_INVALID;
1135  consdata->maxactdelta = SCIP_INVALID;
1136  consdata->maxactdeltavar = NULL;
1137  consdata->minactivityneginf = -1;
1138  consdata->minactivityposinf = -1;
1139  consdata->maxactivityneginf = -1;
1140  consdata->maxactivityposinf = -1;
1141  consdata->minactivityneghuge = -1;
1142  consdata->minactivityposhuge = -1;
1143  consdata->maxactivityneghuge = -1;
1144  consdata->maxactivityposhuge = -1;
1145  consdata->glbminactivity = SCIP_INVALID;
1146  consdata->glbmaxactivity = SCIP_INVALID;
1147  consdata->lastglbminactivity = SCIP_INVALID;
1148  consdata->lastglbmaxactivity = SCIP_INVALID;
1149  consdata->glbminactivityneginf = -1;
1150  consdata->glbminactivityposinf = -1;
1151  consdata->glbmaxactivityneginf = -1;
1152  consdata->glbmaxactivityposinf = -1;
1153  consdata->glbminactivityneghuge = -1;
1154  consdata->glbminactivityposhuge = -1;
1155  consdata->glbmaxactivityneghuge = -1;
1156  consdata->glbmaxactivityposhuge = -1;
1157 }
1158 
1159 /** compute the pseudo activity of a constraint */
1160 static
1162  SCIP* scip, /**< SCIP data structure */
1163  SCIP_CONSDATA* consdata /**< linear constraint data */
1164  )
1165 {
1166  int i;
1167  int pseudoactivityposinf;
1168  int pseudoactivityneginf;
1169  SCIP_Real pseudoactivity;
1170  SCIP_Real bound;
1171  SCIP_Real val;
1172 
1173  pseudoactivity = 0;
1174  pseudoactivityposinf = 0;
1175  pseudoactivityneginf = 0;
1176 
1177  for( i = consdata->nvars - 1; i >= 0; --i )
1178  {
1179  val = consdata->vals[i];
1180  bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1181  if( SCIPisInfinity(scip, bound) )
1182  {
1183  if( val > 0.0 )
1184  pseudoactivityposinf++;
1185  else
1186  pseudoactivityneginf++;
1187  }
1188  else
1189  {
1190  if( SCIPisInfinity(scip, -bound) )
1191  {
1192  if( val > 0.0 )
1193  pseudoactivityneginf++;
1194  else
1195  pseudoactivityposinf++;
1196  }
1197  else
1198  pseudoactivity += val * bound;
1199  }
1200  }
1201 
1202  if( pseudoactivityneginf > 0 && pseudoactivityposinf > 0 )
1203  return SCIP_INVALID;
1204  else if( pseudoactivityneginf > 0 )
1205  return -SCIPinfinity(scip);
1206  else if( pseudoactivityposinf > 0 )
1207  return SCIPinfinity(scip);
1208 
1209  return pseudoactivity;
1210 }
1211 
1212 /** recompute the minactivity of a constraint */
1213 static
1215  SCIP* scip, /**< SCIP data structure */
1216  SCIP_CONSDATA* consdata /**< linear constraint data */
1217  )
1218 {
1219  int i;
1220  SCIP_Real bound;
1221 
1222  consdata->minactivity = 0;
1223 
1224  for( i = consdata->nvars - 1; i >= 0; --i )
1225  {
1226  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1227  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1228  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1229  consdata->minactivity += consdata->vals[i] * bound;
1230  }
1232  /* the activity was just computed from scratch and is valid now */
1233  consdata->validminact = TRUE;
1234 
1235  /* the activity was just computed from scratch, mark it to be reliable */
1236  consdata->lastminactivity = consdata->minactivity;
1237 }
1238 
1239 /** recompute the maxactivity of a constraint */
1240 static
1242  SCIP* scip, /**< SCIP data structure */
1243  SCIP_CONSDATA* consdata /**< linear constraint data */
1244  )
1245 {
1246  int i;
1247  SCIP_Real bound;
1248 
1249  consdata->maxactivity = 0;
1250 
1251  for( i = consdata->nvars - 1; i >= 0; --i )
1252  {
1253  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1254  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1255  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1256  consdata->maxactivity += consdata->vals[i] * bound;
1257  }
1259  /* the activity was just computed from scratch and is valid now */
1260  consdata->validmaxact = TRUE;
1261 
1262  /* the activity was just computed from scratch, mark it to be reliable */
1263  consdata->lastmaxactivity = consdata->maxactivity;
1264 }
1265 
1266 /** recompute the global minactivity of a constraint */
1267 static
1269  SCIP* scip, /**< SCIP data structure */
1270  SCIP_CONSDATA* consdata /**< linear constraint data */
1271  )
1272 {
1273  int i;
1274  SCIP_Real bound;
1275 
1276  consdata->glbminactivity = 0;
1277 
1278  for( i = consdata->nvars - 1; i >= 0; --i )
1279  {
1280  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1281  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) )
1282  consdata->glbminactivity += consdata->vals[i] * bound;
1283  }
1284 
1285  /* the activity was just computed from scratch and is valid now */
1286  consdata->validglbminact = TRUE;
1287 
1288  /* the activity was just computed from scratch, mark it to be reliable */
1289  consdata->lastglbminactivity = consdata->glbminactivity;
1290 }
1291 
1292 /** recompute the global maxactivity of a constraint */
1293 static
1295  SCIP* scip, /**< SCIP data structure */
1296  SCIP_CONSDATA* consdata /**< linear constraint data */
1297  )
1298 {
1299  int i;
1300  SCIP_Real bound;
1301 
1302  consdata->glbmaxactivity = 0;
1303 
1304  for( i = consdata->nvars - 1; i >= 0; --i )
1305  {
1306  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1307  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) )
1308  consdata->glbmaxactivity += consdata->vals[i] * bound;
1309  }
1310 
1311  /* the activity was just computed from scratch and is valid now */
1312  consdata->validglbmaxact = TRUE;
1313 
1314  /* the activity was just computed from scratch, mark it to be reliable */
1315  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1316 }
1317 
1318 /** calculates maximum absolute value of coefficients */
1319 static
1321  SCIP_CONSDATA* consdata /**< linear constraint data */
1322  )
1323 {
1324  SCIP_Real absval;
1325  int i;
1326 
1327  assert(consdata != NULL);
1328  assert(!consdata->validmaxabsval);
1329  assert(consdata->maxabsval >= SCIP_INVALID);
1330 
1331  consdata->validmaxabsval = TRUE;
1332  consdata->maxabsval = 0.0;
1333  for( i = 0; i < consdata->nvars; ++i )
1334  {
1335  absval = consdata->vals[i];
1336  absval = REALABS(absval);
1337  if( absval > consdata->maxabsval )
1338  consdata->maxabsval = absval;
1339  }
1340 }
1341 
1342 /** calculates minimum absolute value of coefficients */
1343 static
1345  SCIP_CONSDATA* consdata /**< linear constraint data */
1346  )
1347 {
1348  SCIP_Real absval;
1349  int i;
1350 
1351  assert(consdata != NULL);
1352  assert(!consdata->validminabsval);
1353  assert(consdata->minabsval >= SCIP_INVALID);
1354 
1355  consdata->validminabsval = TRUE;
1356 
1357  if( consdata->nvars > 0 )
1358  consdata->minabsval = REALABS(consdata->vals[0]);
1359  else
1360  consdata->minabsval = 0.0;
1362  for( i = 1; i < consdata->nvars; ++i )
1363  {
1364  absval = consdata->vals[i];
1365  absval = REALABS(absval);
1366  if( absval < consdata->minabsval )
1367  consdata->minabsval = absval;
1368  }
1369 }
1370 
1371 /** checks the type of all variables of the constraint and sets hasnonbinvar and hascontvar flags accordingly */
1372 static
1374  SCIP_CONSDATA* consdata /**< linear constraint data */
1375  )
1376 {
1377  int v;
1378 
1379  assert(!consdata->hasnonbinvalid);
1380  consdata->hasnonbinvar = FALSE;
1381  consdata->hascontvar = FALSE;
1382 
1383  for( v = consdata->nvars - 1; v >= 0; --v )
1384  {
1385  SCIP_VARTYPE vartype = SCIPvarGetType(consdata->vars[v]);
1386 
1387  if( vartype != SCIP_VARTYPE_BINARY )
1388  {
1389  consdata->hasnonbinvar = TRUE;
1391  if( vartype == SCIP_VARTYPE_CONTINUOUS )
1392  {
1393  consdata->hascontvar = TRUE;
1394  break;
1395  }
1396  }
1397  }
1398  assert(consdata->hascontvar || v < 0);
1399 
1400  consdata->hasnonbinvalid = TRUE;
1401 }
1402 
1403 
1404 #ifdef CHECKMAXACTDELTA
1405 /* checks that the stored maximal activity delta (if not invalid) is correct */
1406 static
1408  SCIP* scip, /**< SCIP data structure */
1409  SCIP_CONSDATA* consdata /**< linear constraint data */
1410  )
1411 {
1412  if( consdata->maxactdelta != SCIP_INVALID )
1413  {
1414  SCIP_Real maxactdelta = 0.0;
1415  SCIP_Real domain;
1416  SCIP_Real delta;
1417  SCIP_Real lb;
1418  SCIP_Real ub;
1419  int v;
1420 
1421  for( v = consdata->nvars - 1; v >= 0; --v )
1422  {
1423  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1424  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1425 
1426  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1427  {
1428  maxactdelta = SCIPinfinity(scip);
1429  break;
1430  }
1431 
1432  domain = ub - lb;
1433  delta = REALABS(consdata->vals[v]) * domain;
1434 
1435  if( delta > maxactdelta )
1436  {
1437  maxactdelta = delta;
1438  }
1439  }
1440  assert(SCIPisFeasEQ(scip, maxactdelta, consdata->maxactdelta));
1441  }
1442 }
1443 #else
1444 #define checkMaxActivityDelta(scip, consdata) /**/
1445 #endif
1446 
1447 /** recompute maximal activity contribution for a single variable */
1448 static
1450  SCIP* scip, /**< SCIP data structure */
1451  SCIP_CONSDATA* consdata /**< linear constraint data */
1452  )
1453 {
1454  SCIP_Real delta;
1455  int v;
1456 
1457  consdata->maxactdelta = 0.0;
1458 
1459  if( !consdata->hasnonbinvalid )
1460  consdataCheckNonbinvar(consdata);
1462  /* easy case, the problem consists only of binary variables */
1463  if( !consdata->hasnonbinvar )
1464  {
1465  for( v = consdata->nvars - 1; v >= 0; --v )
1466  {
1467  if( SCIPvarGetLbLocal(consdata->vars[v]) < 0.5 && SCIPvarGetUbLocal(consdata->vars[v]) > 0.5 )
1468  {
1469  delta = REALABS(consdata->vals[v]);
1470 
1471  if( delta > consdata->maxactdelta )
1472  {
1473  consdata->maxactdelta = delta;
1474  consdata->maxactdeltavar = consdata->vars[v];
1475  }
1476  }
1477  }
1478  return;
1479  }
1480 
1481  for( v = consdata->nvars - 1; v >= 0; --v )
1482  {
1483  SCIP_Real domain;
1484  SCIP_Real lb;
1485  SCIP_Real ub;
1486 
1487  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1488  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1489 
1490  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1491  {
1492  consdata->maxactdelta = SCIPinfinity(scip);
1493  consdata->maxactdeltavar = consdata->vars[v];
1494  break;
1495  }
1496 
1497  domain = ub - lb;
1498  delta = REALABS(consdata->vals[v]) * domain;
1499 
1500  if( delta > consdata->maxactdelta )
1501  {
1502  consdata->maxactdelta = delta;
1503  consdata->maxactdeltavar = consdata->vars[v];
1504  }
1505  }
1506 }
1507 
1508 
1509 /** updates activities for a change in a bound */
1510 static
1512  SCIP* scip, /**< SCIP data structure */
1513  SCIP_CONSDATA* consdata, /**< linear constraint data */
1514  SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1515  SCIP_Real oldbound, /**< old bound of variable */
1516  SCIP_Real newbound, /**< new bound of variable */
1517  SCIP_Real val, /**< coefficient of constraint entry */
1518  SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1519  SCIP_Bool global, /**< is it a global or a local bound change? */
1520  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1521  )
1522 {
1523  SCIP_Real* activity;
1524  SCIP_Real* lastactivity;
1525  int* activityposinf;
1526  int* activityneginf;
1527  int* activityposhuge;
1528  int* activityneghuge;
1529  SCIP_Real oldcontribution;
1530  SCIP_Real newcontribution;
1531  SCIP_Real delta;
1532  SCIP_Bool validact;
1533  SCIP_Bool finitenewbound;
1534  SCIP_Bool hugevalnewcont;
1535 
1536  assert(scip != NULL);
1537  assert(consdata != NULL);
1538  assert(global || (var != NULL));
1539  assert(consdata->validactivities);
1540  assert(consdata->minactivity < SCIP_INVALID);
1541  assert(consdata->maxactivity < SCIP_INVALID);
1542  assert(consdata->lastminactivity < SCIP_INVALID);
1543  assert(consdata->lastmaxactivity < SCIP_INVALID);
1544  assert(consdata->minactivityneginf >= 0);
1545  assert(consdata->minactivityposinf >= 0);
1546  assert(consdata->maxactivityneginf >= 0);
1547  assert(consdata->maxactivityposinf >= 0);
1548  assert(consdata->minactivityneghuge >= 0);
1549  assert(consdata->minactivityposhuge >= 0);
1550  assert(consdata->maxactivityneghuge >= 0);
1551  assert(consdata->maxactivityposhuge >= 0);
1552  assert(consdata->glbminactivity < SCIP_INVALID);
1553  assert(consdata->glbmaxactivity < SCIP_INVALID);
1554  assert(consdata->lastglbminactivity < SCIP_INVALID);
1555  assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1556  assert(consdata->glbminactivityneginf >= 0);
1557  assert(consdata->glbminactivityposinf >= 0);
1558  assert(consdata->glbmaxactivityneginf >= 0);
1559  assert(consdata->glbmaxactivityposinf >= 0);
1560  assert(consdata->glbminactivityneghuge >= 0);
1561  assert(consdata->glbminactivityposhuge >= 0);
1562  assert(consdata->glbmaxactivityneghuge >= 0);
1563  assert(consdata->glbmaxactivityposhuge >= 0);
1564 
1565  delta = 0.0;
1566 
1567  /* we are updating global activities */
1568  if( global )
1569  {
1570  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1571  * lower bound + pos. coef: update minactivity
1572  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1573  * upper bound + pos. coef: update maxactivity
1574  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1575  */
1576  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1577  {
1578  if( val > 0.0 )
1579  {
1580  activity = &(consdata->glbminactivity);
1581  lastactivity = &(consdata->lastglbminactivity);
1582  activityposinf = &(consdata->glbminactivityposinf);
1583  activityneginf = &(consdata->glbminactivityneginf);
1584  activityposhuge = &(consdata->glbminactivityposhuge);
1585  activityneghuge = &(consdata->glbminactivityneghuge);
1586  validact = consdata->validglbminact;
1587  }
1588  else
1589  {
1590  activity = &(consdata->glbmaxactivity);
1591  lastactivity = &(consdata->lastglbmaxactivity);
1592  activityposinf = &(consdata->glbmaxactivityneginf);
1593  activityneginf = &(consdata->glbmaxactivityposinf);
1594  activityposhuge = &(consdata->glbmaxactivityposhuge);
1595  activityneghuge = &(consdata->glbmaxactivityneghuge);
1596  validact = consdata->validglbmaxact;
1597  }
1598  }
1599  else
1600  {
1601  if( val > 0.0 )
1602  {
1603  activity = &(consdata->glbmaxactivity);
1604  lastactivity = &(consdata->lastglbmaxactivity);
1605  activityposinf = &(consdata->glbmaxactivityposinf);
1606  activityneginf = &(consdata->glbmaxactivityneginf);
1607  activityposhuge = &(consdata->glbmaxactivityposhuge);
1608  activityneghuge = &(consdata->glbmaxactivityneghuge);
1609  validact = consdata->validglbmaxact;
1610  }
1611  else
1612  {
1613  activity = &(consdata->glbminactivity);
1614  lastactivity = &(consdata->lastglbminactivity);
1615  activityposinf = &(consdata->glbminactivityneginf);
1616  activityneginf = &(consdata->glbminactivityposinf);
1617  activityposhuge = &(consdata->glbminactivityposhuge);
1618  activityneghuge = &(consdata->glbminactivityneghuge);
1619  validact = consdata->validglbminact;
1620  }
1621  }
1622  }
1623  /* we are updating local activities */
1624  else
1625  {
1626  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1627  * lower bound + pos. coef: update minactivity
1628  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1629  * upper bound + pos. coef: update maxactivity
1630  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1631  */
1632  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1633  {
1634  if( val > 0.0 )
1635  {
1636  activity = &(consdata->minactivity);
1637  lastactivity = &(consdata->lastminactivity);
1638  activityposinf = &(consdata->minactivityposinf);
1639  activityneginf = &(consdata->minactivityneginf);
1640  activityposhuge = &(consdata->minactivityposhuge);
1641  activityneghuge = &(consdata->minactivityneghuge);
1642  validact = consdata->validminact;
1643  }
1644  else
1645  {
1646  activity = &(consdata->maxactivity);
1647  lastactivity = &(consdata->lastmaxactivity);
1648  activityposinf = &(consdata->maxactivityneginf);
1649  activityneginf = &(consdata->maxactivityposinf);
1650  activityposhuge = &(consdata->maxactivityposhuge);
1651  activityneghuge = &(consdata->maxactivityneghuge);
1652  validact = consdata->validmaxact;
1653  }
1654  }
1655  else
1656  {
1657  if( val > 0.0 )
1658  {
1659  activity = &(consdata->maxactivity);
1660  lastactivity = &(consdata->lastmaxactivity);
1661  activityposinf = &(consdata->maxactivityposinf);
1662  activityneginf = &(consdata->maxactivityneginf);
1663  activityposhuge = &(consdata->maxactivityposhuge);
1664  activityneghuge = &(consdata->maxactivityneghuge);
1665  validact = consdata->validmaxact;
1666  }
1667  else
1668  {
1669  activity = &(consdata->minactivity);
1670  lastactivity = &(consdata->lastminactivity);
1671  activityposinf = &(consdata->minactivityneginf);
1672  activityneginf = &(consdata->minactivityposinf);
1673  activityposhuge = &(consdata->minactivityposhuge);
1674  activityneghuge = &(consdata->minactivityneghuge);
1675  validact = consdata->validminact;
1676  }
1677  }
1678  }
1679 
1680  oldcontribution = val * oldbound;
1681  newcontribution = val * newbound;
1682  hugevalnewcont = SCIPisHugeValue(scip, REALABS(newcontribution));
1683  finitenewbound = !SCIPisInfinity(scip, REALABS(newbound));
1684 
1685  if( SCIPisInfinity(scip, REALABS(oldbound)) )
1686  {
1687  /* old bound was +infinity */
1688  if( oldbound > 0.0 )
1689  {
1690  assert((*activityposinf) >= 1);
1691 
1692  /* we only have to do something if the new bound is not again +infinity */
1693  if( finitenewbound || newbound < 0.0 )
1694  {
1695  /* decrease the counter for positive infinite contributions */
1696  (*activityposinf)--;
1697 
1698  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1699  if( !finitenewbound && newbound < 0.0 )
1700  (*activityneginf)++;
1701  else if( hugevalnewcont )
1702  {
1703  /* if the contribution of this variable is too large, increase the counter for huge values */
1704  if( newcontribution > 0.0 )
1705  (*activityposhuge)++;
1706  else
1707  (*activityneghuge)++;
1708  }
1709  /* "normal case": just add the contribution to the activity */
1710  else
1711  delta = newcontribution;
1712  }
1713  }
1714  /* old bound was -infinity */
1715  else
1716  {
1717  assert(oldbound < 0.0);
1718  assert((*activityneginf) >= 1);
1719 
1720  /* we only have to do something ig the new bound is not again -infinity */
1721  if( finitenewbound || newbound > 0.0 )
1722  {
1723  /* decrease the counter for negative infinite contributions */
1724  (*activityneginf)--;
1725 
1726  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1727  if( !finitenewbound && newbound > 0.0 )
1728  (*activityposinf)++;
1729  else if( hugevalnewcont )
1730  {
1731  /* if the contribution of this variable is too large, increase the counter for huge values */
1732  if( newcontribution > 0.0 )
1733  (*activityposhuge)++;
1734  else
1735  (*activityneghuge)++;
1736  }
1737  /* "normal case": just add the contribution to the activity */
1738  else
1739  delta = newcontribution;
1740  }
1741  }
1742  }
1743  else if( SCIPisHugeValue(scip, REALABS(oldcontribution)) )
1744  {
1745  /* old contribution was too large and positive */
1746  if( oldcontribution > 0.0 )
1747  {
1748  assert((*activityposhuge) >= 1);
1749 
1750  /* decrease the counter for huge positive contributions; it might be increased again later,
1751  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1752  */
1753  (*activityposhuge)--;
1754 
1755  if( !finitenewbound )
1756  {
1757  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1758  if( newbound > 0.0 )
1759  (*activityposinf)++;
1760  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1761  else
1762  (*activityneginf)++;
1763  }
1764  else if( hugevalnewcont )
1765  {
1766  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1767  if( newcontribution > 0.0 )
1768  (*activityposhuge)++;
1769  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1770  else
1771  (*activityneghuge)++;
1772  }
1773  /* "normal case": just add the contribution to the activity */
1774  else
1775  delta = newcontribution;
1776  }
1777  /* old contribution was too large and negative */
1778  else
1779  {
1780  assert(oldcontribution < 0.0);
1781  assert((*activityneghuge) >= 1);
1782 
1783  /* decrease the counter for huge negative contributions; it might be increased again later,
1784  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1785  */
1786  (*activityneghuge)--;
1787 
1788  if( !finitenewbound )
1789  {
1790  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1791  if( newbound > 0.0 )
1792  (*activityposinf)++;
1793  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1794  else
1795  (*activityneginf)++;
1796  }
1797  else if( hugevalnewcont )
1798  {
1799  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1800  if( newcontribution > 0.0 )
1801  (*activityposhuge)++;
1802  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1803  else
1804  (*activityneghuge)++;
1805  }
1806  /* "normal case": just add the contribution to the activity */
1807  else
1808  delta = newcontribution;
1809  }
1810  }
1811  /* old bound was finite and not too large */
1812  else
1813  {
1814  if( !finitenewbound )
1815  {
1816  /* if the new bound is +infinity, the old contribution has to be subtracted
1817  * and the counter for positive infinite contributions has to be increased
1818  */
1819  if( newbound > 0.0 )
1820  {
1821  (*activityposinf)++;
1822  delta = -oldcontribution;
1823  }
1824  /* if the new bound is -infinity, the old contribution has to be subtracted
1825  * and the counter for negative infinite contributions has to be increased
1826  */
1827  else
1828  {
1829  assert(newbound < 0.0 );
1830 
1831  (*activityneginf)++;
1832  delta = -oldcontribution;
1833  }
1834  }
1835  /* if the contribution of this variable is too large, increase the counter for huge values */
1836  else if( hugevalnewcont )
1837  {
1838  if( newcontribution > 0.0 )
1839  {
1840  (*activityposhuge)++;
1841  delta = -oldcontribution;
1842  }
1843  else
1844  {
1845  (*activityneghuge)++;
1846  delta = -oldcontribution;
1847  }
1848  }
1849  /* "normal case": just update the activity */
1850  else
1851  delta = newcontribution - oldcontribution;
1852  }
1853 
1854  /* update the activity, if the current value is valid and there was a change in the finite part */
1855  if( validact && (delta != 0.0) )
1856  {
1857  /* if the absolute value of the activity is increased, this is regarded as reliable,
1858  * otherwise, we check whether we can still trust the updated value
1859  */
1860  (*activity) = (*activity) + delta;
1861  assert(!SCIPisInfinity(scip, -(*activity)) && !SCIPisInfinity(scip, *activity));
1862 
1863  if( REALABS((*lastactivity)) < REALABS(*activity) )
1864  {
1865  (*lastactivity) = (*activity);
1866  }
1867  else
1868  {
1869  if( checkreliability && SCIPisUpdateUnreliable(scip, (*activity), (*lastactivity)) )
1870  {
1871  SCIPdebugMsg(scip, "%s activity of linear constraint unreliable after update: %16.9g\n",
1872  (global ? "global " : ""), (*activity));
1873 
1874  /* mark the activity that was just changed and is not reliable anymore to be invalid */
1875  if( global )
1876  {
1877  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1878  consdata->validglbminact = FALSE;
1879  else
1880  consdata->validglbmaxact = FALSE;
1881  }
1882  else
1883  {
1884  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1885  consdata->validminact = FALSE;
1886  else
1887  consdata->validmaxact = FALSE;
1888  }
1889  }
1890  }
1891  }
1892 }
1893 
1894 /** updates minimum and maximum activity for a change in lower bound */
1895 static
1897  SCIP* scip, /**< SCIP data structure */
1898  SCIP_CONSDATA* consdata, /**< linear constraint data */
1899  SCIP_VAR* var, /**< variable that has been changed */
1900  SCIP_Real oldlb, /**< old lower bound of variable */
1901  SCIP_Real newlb, /**< new lower bound of variable */
1902  SCIP_Real val, /**< coefficient of constraint entry */
1903  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1904  )
1905 {
1906  assert(scip != NULL);
1907  assert(consdata != NULL);
1908  assert(var != NULL);
1909 
1910  if( consdata->validactivities )
1911  {
1912  consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
1914  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1915  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1916  }
1917 }
1918 
1919 /** updates minimum and maximum activity for a change in upper bound */
1920 static
1922  SCIP* scip, /**< SCIP data structure */
1923  SCIP_CONSDATA* consdata, /**< linear constraint data */
1924  SCIP_VAR* var, /**< variable that has been changed */
1925  SCIP_Real oldub, /**< old upper bound of variable */
1926  SCIP_Real newub, /**< new upper bound of variable */
1927  SCIP_Real val, /**< coefficient of constraint entry */
1928  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1929  )
1930 {
1931  assert(scip != NULL);
1932  assert(consdata != NULL);
1933  assert(var != NULL);
1934 
1935  if( consdata->validactivities )
1936  {
1937  consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
1939  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1940  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1941  }
1942 }
1943 
1944 /** updates minimum and maximum global activity for a change in the global lower bound */
1945 static
1947  SCIP* scip, /**< SCIP data structure */
1948  SCIP_CONSDATA* consdata, /**< linear constraint data */
1949  SCIP_Real oldlb, /**< old lower bound of variable */
1950  SCIP_Real newlb, /**< new lower bound of variable */
1951  SCIP_Real val, /**< coefficient of constraint entry */
1952  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1953  )
1954 {
1955  assert(scip != NULL);
1956  assert(consdata != NULL);
1957 
1958  if( consdata->validactivities )
1959  {
1960  consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
1961 
1962  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
1963  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
1964  }
1965 }
1966 
1967 /** updates minimum and maximum global activity for a change in global upper bound */
1968 static
1970  SCIP* scip, /**< SCIP data structure */
1971  SCIP_CONSDATA* consdata, /**< linear constraint data */
1972  SCIP_Real oldub, /**< old upper bound of variable */
1973  SCIP_Real newub, /**< new upper bound of variable */
1974  SCIP_Real val, /**< coefficient of constraint entry */
1975  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1976  )
1977 {
1978  assert(scip != NULL);
1979  assert(consdata != NULL);
1980 
1981  if( consdata->validactivities )
1982  {
1983  consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
1984 
1985  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
1986  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
1987  }
1988 }
1989 
1990 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
1991 static
1993  SCIP* scip, /**< SCIP data structure */
1994  SCIP_CONSDATA* consdata, /**< linear constraint data */
1995  SCIP_VAR* var, /**< variable of constraint entry */
1996  SCIP_Real val, /**< coefficient of constraint entry */
1997  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1998  )
1999 {
2000  assert(scip != NULL);
2001  assert(consdata != NULL);
2002  assert(var != NULL);
2003 
2004  /* update maximum absolute value */
2005  if( consdata->validmaxabsval )
2006  {
2007  SCIP_Real absval;
2008 
2009  assert(consdata->maxabsval < SCIP_INVALID);
2010 
2011  absval = REALABS(val);
2012  consdata->maxabsval = MAX(consdata->maxabsval, absval);
2013  }
2014 
2015  if( consdata->validminabsval )
2016  {
2017  SCIP_Real absval;
2018 
2019  assert(consdata->minabsval < SCIP_INVALID);
2020 
2021  absval = REALABS(val);
2022  consdata->minabsval = MIN(consdata->minabsval, absval);
2023  }
2024 
2025  /* update minimal and maximal activity */
2026  if( consdata->validactivities )
2027  {
2028  assert(consdata->minactivity < SCIP_INVALID);
2029  assert(consdata->maxactivity < SCIP_INVALID);
2030  assert(consdata->glbminactivity < SCIP_INVALID);
2031  assert(consdata->glbmaxactivity < SCIP_INVALID);
2032 
2033  consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
2034  consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
2035  consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
2036  consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
2037  }
2038 }
2039 
2040 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
2041 static
2043  SCIP* scip, /**< SCIP data structure */
2044  SCIP_CONSDATA* consdata, /**< linear constraint data */
2045  SCIP_VAR* var, /**< variable of constraint entry */
2046  SCIP_Real val, /**< coefficient of constraint entry */
2047  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2048  )
2049 {
2050  assert(scip != NULL);
2051  assert(consdata != NULL);
2052  assert(var != NULL);
2053 
2054  /* invalidate maximum absolute value, if this coefficient was the maximum */
2055  if( consdata->validmaxabsval )
2056  {
2057  SCIP_Real absval;
2058 
2059  absval = REALABS(val);
2060 
2061  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2062  {
2063  consdata->validmaxabsval = FALSE;
2064  consdata->maxabsval = SCIP_INVALID;
2065  }
2066  }
2067 
2068  /* invalidate minimum absolute value, if this coefficient was the minimum */
2069  if( consdata->validminabsval )
2070  {
2071  SCIP_Real absval;
2072 
2073  absval = REALABS(val);
2074 
2075  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2076  {
2077  consdata->validminabsval = FALSE;
2078  consdata->minabsval = SCIP_INVALID;
2079  }
2080  }
2081 
2082  /* update minimal and maximal activity */
2083  if( consdata->validactivities )
2084  {
2085  assert(consdata->minactivity < SCIP_INVALID);
2086  assert(consdata->maxactivity < SCIP_INVALID);
2087  assert(consdata->glbminactivity < SCIP_INVALID);
2088  assert(consdata->glbmaxactivity < SCIP_INVALID);
2089 
2090  consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
2091  consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
2092  consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
2093  consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
2094  }
2095 }
2096 
2097 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
2098 static
2100  SCIP* scip, /**< SCIP data structure */
2101  SCIP_CONSDATA* consdata, /**< linear constraint data */
2102  SCIP_VAR* var, /**< variable of constraint entry */
2103  SCIP_Real oldval, /**< old coefficient of constraint entry */
2104  SCIP_Real newval, /**< new coefficient of constraint entry */
2105  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
2106  )
2107 {
2108  assert(scip != NULL);
2109  assert(consdata != NULL);
2110  assert(var != NULL);
2111 
2112  /* old zero coefficients should be handled by consdataUpdateAddCoef() */
2113  assert(!SCIPisZero(scip, oldval));
2114 
2115  /* new zero coefficients should be handled by consdataUpdateDelCoef() */
2116  assert(!SCIPisZero(scip, newval));
2117 
2118  /* update maximum absolute value */
2119  if( consdata->validmaxabsval )
2120  {
2121  SCIP_Real absval;
2122 
2123  absval = REALABS(newval);
2124 
2125  if( SCIPisGE(scip, absval, consdata->maxabsval) )
2126  {
2127  consdata->maxabsval = absval;
2128  }
2129  else
2130  {
2131  absval = REALABS(oldval);
2132 
2133  /* invalidate maximum absolute value */
2134  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
2135  {
2136  consdata->validmaxabsval = FALSE;
2137  consdata->maxabsval = SCIP_INVALID;
2138  }
2139  }
2140  }
2141 
2142  /* update minimum absolute value */
2143  if( consdata->validminabsval )
2144  {
2145  SCIP_Real absval;
2146 
2147  absval = REALABS(newval);
2148 
2149  if( SCIPisLE(scip, absval, consdata->minabsval) )
2150  {
2151  consdata->minabsval = absval;
2152  }
2153  else
2154  {
2155  absval = REALABS(oldval);
2156 
2157  /* invalidate minimum absolute value */
2158  if( SCIPisEQ(scip, absval, consdata->minabsval) )
2159  {
2160  consdata->validminabsval = FALSE;
2161  consdata->minabsval = SCIP_INVALID;
2162  }
2163  }
2164  }
2165 
2166 
2167  /* update maximum activity delta */
2168  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
2169  {
2170  SCIP_Real domain;
2171  SCIP_Real delta;
2172 
2173  assert(!SCIPisInfinity(scip, SCIPvarGetLbLocal(var)));
2174  assert(!SCIPisInfinity(scip, SCIPvarGetUbLocal(var)));
2175 
2176  domain = SCIPvarGetUbLocal(var) - SCIPvarGetLbLocal(var);
2177  delta = REALABS(newval) * domain;
2178 
2179  if( delta > consdata->maxactdelta )
2180  {
2181  consdata->maxactdelta = delta;
2182  consdata->maxactdeltavar = var;
2183  }
2184  else
2185  {
2186  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
2187  if( consdata->maxactdeltavar == var )
2188  consdata->maxactdelta = SCIP_INVALID;
2189  }
2190  }
2191 
2192  /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
2193  consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
2194  consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
2195 }
2196 
2197 /** returns the maximum absolute value of all coefficients in the constraint */
2198 static
2200  SCIP_CONSDATA* consdata /**< linear constraint data */
2201  )
2202 {
2203  assert(consdata != NULL);
2204 
2205  if( !consdata->validmaxabsval )
2206  consdataCalcMaxAbsval(consdata);
2207  assert(consdata->validmaxabsval);
2208  assert(consdata->maxabsval < SCIP_INVALID);
2209 
2210  return consdata->maxabsval;
2211 }
2212 
2213 /** returns the minimum absolute value of all coefficients in the constraint */
2214 static
2216  SCIP_CONSDATA* consdata /**< linear constraint data */
2217  )
2218 {
2219  assert(consdata != NULL);
2220 
2221  if( !consdata->validminabsval )
2222  consdataCalcMinAbsval(consdata);
2223  assert(consdata->validminabsval);
2224  assert(consdata->minabsval < SCIP_INVALID);
2225 
2226  return consdata->minabsval;
2227 }
2228 
2229 /** calculates minimum and maximum local and global activity for constraint from scratch;
2230  * additionally recalculates maximum absolute value of coefficients
2231  */
2232 static
2234  SCIP* scip, /**< SCIP data structure */
2235  SCIP_CONSDATA* consdata /**< linear constraint data */
2236  )
2237 {
2238  int i;
2239 
2240  assert(scip != NULL);
2241  assert(consdata != NULL);
2242  assert(!consdata->validactivities);
2243  assert(consdata->minactivity >= SCIP_INVALID || consdata->validminact);
2244  assert(consdata->maxactivity >= SCIP_INVALID || consdata->validmaxact);
2245  assert(consdata->glbminactivity >= SCIP_INVALID || consdata->validglbminact);
2246  assert(consdata->glbmaxactivity >= SCIP_INVALID || consdata->validglbmaxact);
2247 
2248  consdata->validmaxabsval = TRUE;
2249  consdata->validminabsval = TRUE;
2250  consdata->validactivities = TRUE;
2251  consdata->validminact = TRUE;
2252  consdata->validmaxact = TRUE;
2253  consdata->validglbminact = TRUE;
2254  consdata->validglbmaxact = TRUE;
2255  consdata->maxabsval = 0.0;
2256  consdata->minabsval = (consdata->nvars == 0 ? 0.0 : REALABS(consdata->vals[0]));
2257  consdata->minactivity = 0.0;
2258  consdata->maxactivity = 0.0;
2259  consdata->lastminactivity = 0.0;
2260  consdata->lastmaxactivity = 0.0;
2261  consdata->minactivityneginf = 0;
2262  consdata->minactivityposinf = 0;
2263  consdata->maxactivityneginf = 0;
2264  consdata->maxactivityposinf = 0;
2265  consdata->minactivityneghuge = 0;
2266  consdata->minactivityposhuge = 0;
2267  consdata->maxactivityneghuge = 0;
2268  consdata->maxactivityposhuge = 0;
2269  consdata->glbminactivity = 0.0;
2270  consdata->glbmaxactivity = 0.0;
2271  consdata->lastglbminactivity = 0.0;
2272  consdata->lastglbmaxactivity = 0.0;
2273  consdata->glbminactivityneginf = 0;
2274  consdata->glbminactivityposinf = 0;
2275  consdata->glbmaxactivityneginf = 0;
2276  consdata->glbmaxactivityposinf = 0;
2277  consdata->glbminactivityneghuge = 0;
2278  consdata->glbminactivityposhuge = 0;
2279  consdata->glbmaxactivityneghuge = 0;
2280  consdata->glbmaxactivityposhuge = 0;
2281 
2282  for( i = 0; i < consdata->nvars; ++i )
2283  consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
2284 
2285  consdata->lastminactivity = consdata->minactivity;
2286  consdata->lastmaxactivity = consdata->maxactivity;
2287  consdata->lastglbminactivity = consdata->glbminactivity;
2288  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
2289 }
2290 
2291 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
2292  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2293  */
2294 static
2295 void getMinActivity(
2296  SCIP* scip, /**< SCIP data structure */
2297  SCIP_CONSDATA* consdata, /**< linear constraint */
2298  int posinf, /**< number of coefficients contributing pos. infinite value */
2299  int neginf, /**< number of coefficients contributing neg. infinite value */
2300  int poshuge, /**< number of coefficients contributing huge pos. value */
2301  int neghuge, /**< number of coefficients contributing huge neg. value */
2302  SCIP_Real delta, /**< value to subtract from stored minactivity
2303  * (contribution of the variable set to zero when getting residual activity) */
2304  SCIP_Bool global, /**< should the global or local minimal activity be returned? */
2305  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2306  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2307  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2308  * i.e. is <= the exact minactivity (in case of huge contributing values) */
2309  SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
2310  )
2311 {
2312  assert(scip != NULL);
2313  assert(consdata != NULL);
2314  assert(posinf >= 0);
2315  assert(neginf >= 0);
2316  assert(poshuge >= 0);
2317  assert(neghuge >= 0);
2318  assert(minactivity != NULL);
2319  assert(isrelax != NULL);
2320  assert(issettoinfinity != NULL);
2321 
2322  /* if we have pos. infinite contributions, the minactivity is +infty */
2323  if( posinf > 0 )
2324  {
2325  *minactivity = SCIPinfinity(scip);
2326  *issettoinfinity = TRUE;
2327  *isrelax = FALSE;
2328  }
2329  /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
2330  else if( neginf > 0 )
2331  {
2332  *minactivity = -SCIPinfinity(scip);
2333  *issettoinfinity = TRUE;
2334  *isrelax = FALSE;
2335  }
2336  /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
2337  else if( neghuge > 0 )
2338  {
2339  *minactivity = -SCIPinfinity(scip);
2340  *issettoinfinity = TRUE;
2341  *isrelax = TRUE;
2342  }
2343  /* we do not need a good relaxation and we have positve huge contributions, so we just return -infty as activity */
2344  else if( !goodrelax && poshuge > 0 )
2345  {
2346  *minactivity = -SCIPinfinity(scip);
2347  *issettoinfinity = TRUE;
2348  *isrelax = TRUE;
2349  }
2350  else
2351  {
2352  SCIP_Real tmpactivity;
2353 
2354  /* recompute minactivity if it is not valid */
2355  if( global )
2356  {
2357  if( !consdata->validglbminact )
2358  consdataRecomputeGlbMinactivity(scip, consdata);
2359  assert(consdata->validglbminact);
2360 
2361  tmpactivity = consdata->glbminactivity;
2362  }
2363  else
2364  {
2365  if( !consdata->validminact )
2366  consdataRecomputeMinactivity(scip, consdata);
2367  assert(consdata->validminact);
2368 
2369  tmpactivity = consdata->minactivity;
2370  }
2371 
2372  /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2373  * a feasible relaxation of the minactivity is the number of positive huge contributions
2374  * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2375  */
2376  if( poshuge > 0 )
2377  {
2378  *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2379  *issettoinfinity = FALSE;
2380  *isrelax = TRUE;
2381  }
2382  /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2383  else
2384  {
2385  *minactivity = tmpactivity - delta;
2386  *issettoinfinity = FALSE;
2387  *isrelax = FALSE;
2388  }
2389  }
2390 }
2391 
2392 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2393  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2394  */
2395 static
2396 void getMaxActivity(
2397  SCIP* scip, /**< SCIP data structure */
2398  SCIP_CONSDATA* consdata, /**< linear constraint */
2399  int posinf, /**< number of coefficients contributing pos. infinite value */
2400  int neginf, /**< number of coefficients contributing neg. infinite value */
2401  int poshuge, /**< number of coefficients contributing huge pos. value */
2402  int neghuge, /**< number of coefficients contributing huge neg. value */
2403  SCIP_Real delta, /**< value to subtract from stored maxactivity
2404  * (contribution of the variable set to zero when getting residual activity) */
2405  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2406  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2407  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2408  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2409  * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2410  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2411  )
2412 {
2413  assert(scip != NULL);
2414  assert(consdata != NULL);
2415  assert(posinf >= 0);
2416  assert(neginf >= 0);
2417  assert(poshuge >= 0);
2418  assert(neghuge >= 0);
2419  assert(maxactivity != NULL);
2420  assert(isrelax != NULL);
2421  assert(issettoinfinity != NULL);
2422 
2423  /* if we have neg. infinite contributions, the maxactivity is -infty */
2424  if( neginf > 0 )
2425  {
2426  *maxactivity = -SCIPinfinity(scip);
2427  *issettoinfinity = TRUE;
2428  *isrelax = FALSE;
2429  }
2430  /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2431  else if( posinf > 0 )
2432  {
2433  *maxactivity = SCIPinfinity(scip);
2434  *issettoinfinity = TRUE;
2435  *isrelax = FALSE;
2436  }
2437  /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2438  else if( poshuge > 0 )
2439  {
2440  *maxactivity = SCIPinfinity(scip);
2441  *issettoinfinity = TRUE;
2442  *isrelax = TRUE;
2443  }
2444  /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2445  else if( !goodrelax && neghuge > 0 )
2446  {
2447  *maxactivity = SCIPinfinity(scip);
2448  *issettoinfinity = TRUE;
2449  *isrelax = TRUE;
2450  }
2451  else
2452  {
2453  SCIP_Real tmpactivity;
2454 
2455  /* recompute maxactivity if it is not valid */
2456  if( global )
2457  {
2458  if( !consdata->validglbmaxact )
2459  consdataRecomputeGlbMaxactivity(scip, consdata);
2460  assert(consdata->validglbmaxact);
2461 
2462  tmpactivity = consdata->glbmaxactivity;
2463  }
2464  else
2465  {
2466  if( !consdata->validmaxact )
2467  consdataRecomputeMaxactivity(scip, consdata);
2468  assert(consdata->validmaxact);
2469 
2470  tmpactivity = consdata->maxactivity;
2471  }
2472 
2473  /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2474  * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2475  * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2476  */
2477  if( neghuge > 0 )
2478  {
2479  *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2480  *issettoinfinity = FALSE;
2481  *isrelax = TRUE;
2482  }
2483  /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2484  else
2485  {
2486  *maxactivity = tmpactivity - delta;
2487  *issettoinfinity = FALSE;
2488  *isrelax = FALSE;
2489  }
2490  }
2491 }
2492 
2493 /** gets activity bounds for constraint */
2494 static
2496  SCIP* scip, /**< SCIP data structure */
2497  SCIP_CONSDATA* consdata, /**< linear constraint */
2498  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2499  * relaxed acticities ignored, anyway? */
2500  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2501  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2502  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2503  * i.e. <= the exact minactivity (in case of huge contributions),
2504  * or equal to the exact minimal activity */
2505  SCIP_Bool* maxisrelax /**< pointer to store whether the returned maxactivity is just a relaxation,
2506  * i.e. >= the exact maxactivity (in case of huge contributions),
2507  * or equal to the exact maximal activity */
2508  )
2509 {
2510  SCIP_Bool issettoinfinity;
2511 
2512  assert(scip != NULL);
2513  assert(consdata != NULL);
2514  assert(minactivity != NULL);
2515  assert(maxactivity != NULL);
2516 
2517  if( !consdata->validactivities )
2518  {
2519  consdataCalcActivities(scip, consdata);
2520  assert(consdata->validminact);
2521  assert(consdata->validmaxact);
2522  }
2523  assert(consdata->minactivity < SCIP_INVALID);
2524  assert(consdata->maxactivity < SCIP_INVALID);
2525  assert(consdata->minactivityneginf >= 0);
2526  assert(consdata->minactivityposinf >= 0);
2527  assert(consdata->maxactivityneginf >= 0);
2528  assert(consdata->maxactivityposinf >= 0);
2529 
2530  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2531  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2532  minactivity, minisrelax, &issettoinfinity);
2533 
2534  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2535  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2536  maxactivity, maxisrelax, &issettoinfinity);
2537 }
2538 
2539 /** calculates activity bounds for constraint after setting variable to zero */
2540 static
2542  SCIP* scip, /**< SCIP data structure */
2543  SCIP_CONSDATA* consdata, /**< linear constraint */
2544  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2545  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2546  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2547  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2548  )
2549 {
2550  SCIP_VAR* var;
2551  SCIP_Real val;
2552  SCIP_Real lb;
2553  SCIP_Real ub;
2554  int v;
2555 
2556  assert(scip != NULL);
2557  assert(consdata != NULL);
2558  assert(cancelvar != NULL);
2559  assert(resactivity != NULL);
2560 
2561  *resactivity = 0.0;
2562 
2563  for( v = 0; v < consdata->nvars; ++v )
2564  {
2565  var = consdata->vars[v];
2566  assert(var != NULL);
2567  if( var == cancelvar )
2568  continue;
2569 
2570  val = consdata->vals[v];
2571 
2572  if( useglobalbounds )
2573  {
2574  lb = SCIPvarGetLbGlobal(var);
2575  ub = SCIPvarGetUbGlobal(var);
2576  }
2577  else
2578  {
2579  lb = SCIPvarGetLbLocal(var);
2580  ub = SCIPvarGetUbLocal(var);
2581  }
2582 
2583  assert(!SCIPisZero(scip, val));
2584  assert(SCIPisLE(scip, lb, ub));
2585 
2586  if( val > 0.0 )
2587  {
2588  if( isminresact )
2589  {
2590  assert(!SCIPisInfinity(scip, -lb));
2591  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2592  *resactivity += val*lb;
2593  }
2594  else
2595  {
2596  assert(!SCIPisInfinity(scip, ub));
2597  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2598  *resactivity += val*ub;
2599  }
2600  }
2601  else
2602  {
2603  if( isminresact)
2604  {
2605  assert(!SCIPisInfinity(scip, ub));
2606  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2607  *resactivity += val*ub;
2608  }
2609  else
2610  {
2611  assert(!SCIPisInfinity(scip, -lb));
2612  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2613  *resactivity += val*lb;
2614  }
2615  }
2616  }
2617  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2618 }
2619 
2620 /** gets activity bounds for constraint after setting variable to zero */
2621 static
2623  SCIP* scip, /**< SCIP data structure */
2624  SCIP_CONSDATA* consdata, /**< linear constraint */
2625  SCIP_VAR* var, /**< variable to calculate activity residual for */
2626  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2627  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2628  * relaxed acticities ignored, anyway? */
2629  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2630  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2631  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2632  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2633  * contributions), or equal to the exact residual minactivity */
2634  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2635  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2636  * contributions), or equal to the exact residual minactivity */
2637  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2638  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2639  )
2640 {
2641  SCIP_Real minactbound;
2642  SCIP_Real maxactbound;
2643  SCIP_Real absval;
2644 
2645  assert(scip != NULL);
2646  assert(consdata != NULL);
2647  assert(var != NULL);
2648  assert(minresactivity != NULL);
2649  assert(maxresactivity != NULL);
2650  assert(minisrelax != NULL);
2651  assert(maxisrelax != NULL);
2652  assert(isminsettoinfinity != NULL);
2653  assert(ismaxsettoinfinity != NULL);
2654 
2655  /* get activity bounds of linear constraint */
2656  if( !consdata->validactivities )
2657  {
2658  consdataCalcActivities(scip, consdata);
2659  assert(consdata->validminact);
2660  assert(consdata->validmaxact);
2661  }
2662  assert(consdata->minactivity < SCIP_INVALID);
2663  assert(consdata->maxactivity < SCIP_INVALID);
2664  assert(consdata->minactivityneginf >= 0);
2665  assert(consdata->minactivityposinf >= 0);
2666  assert(consdata->maxactivityneginf >= 0);
2667  assert(consdata->maxactivityposinf >= 0);
2668  assert(consdata->minactivityneghuge >= 0);
2669  assert(consdata->minactivityposhuge >= 0);
2670  assert(consdata->maxactivityneghuge >= 0);
2671  assert(consdata->maxactivityposhuge >= 0);
2672 
2673  if( val > 0.0 )
2674  {
2675  minactbound = SCIPvarGetLbLocal(var);
2676  maxactbound = SCIPvarGetUbLocal(var);
2677  absval = val;
2678  }
2679  else
2680  {
2681  minactbound = -SCIPvarGetUbLocal(var);
2682  maxactbound = -SCIPvarGetLbLocal(var);
2683  absval = -val;
2684  }
2685 
2686  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2687  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2688  */
2689  if( SCIPisInfinity(scip, minactbound) )
2690  {
2691  assert(consdata->minactivityposinf >= 1);
2692 
2693  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2694  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2695  minresactivity, minisrelax, isminsettoinfinity);
2696  }
2697  else if( SCIPisInfinity(scip, -minactbound) )
2698  {
2699  assert(consdata->minactivityneginf >= 1);
2700 
2701  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2702  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2703  minresactivity, minisrelax, isminsettoinfinity);
2704  }
2705  else if( SCIPisHugeValue(scip, minactbound * absval) )
2706  {
2707  assert(consdata->minactivityposhuge >= 1);
2708 
2709  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2710  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2711  minresactivity, minisrelax, isminsettoinfinity);
2712  }
2713  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2714  {
2715  assert(consdata->minactivityneghuge >= 1);
2716 
2717  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2718  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2719  minresactivity, minisrelax, isminsettoinfinity);
2720  }
2721  else
2722  {
2723  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2724  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2725  minresactivity, minisrelax, isminsettoinfinity);
2726  }
2727 
2728  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2729  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2730  */
2731  if( SCIPisInfinity(scip, -maxactbound) )
2732  {
2733  assert(consdata->maxactivityneginf >= 1);
2734 
2735  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2736  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2737  maxresactivity, maxisrelax, ismaxsettoinfinity);
2738  }
2739  else if( SCIPisInfinity(scip, maxactbound) )
2740  {
2741  assert(consdata->maxactivityposinf >= 1);
2742 
2743  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2744  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2745  maxresactivity, maxisrelax, ismaxsettoinfinity);
2746  }
2747  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2748  {
2749  assert(consdata->maxactivityposhuge >= 1);
2750 
2751  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2752  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2753  maxresactivity, maxisrelax, ismaxsettoinfinity);
2754  }
2755  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2756  {
2757  assert(consdata->maxactivityneghuge >= 1);
2758 
2759  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2760  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2761  maxresactivity, maxisrelax, ismaxsettoinfinity);
2762  }
2763  else
2764  {
2765  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2766  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2767  maxresactivity, maxisrelax, ismaxsettoinfinity);
2768  }
2769 }
2770 
2771 /** gets global activity bounds for constraint */
2772 static
2774  SCIP* scip, /**< SCIP data structure */
2775  SCIP_CONSDATA* consdata, /**< linear constraint */
2776  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2777  * relaxed acticities ignored, anyway? */
2778  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2779  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2780  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2781  * i.e. <= the exact minactivity (in case of huge contributions),
2782  * or equal to the exact minimal activity */
2783  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2784  * i.e. >= the exact maxactivity (in case of huge contributions),
2785  * or equal to the exact maximal activity */
2786  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2787  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2788  )
2789 {
2790  assert(scip != NULL);
2791  assert(consdata != NULL);
2792  assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2793  || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2794 
2795  if( !consdata->validactivities )
2796  {
2797  consdataCalcActivities(scip, consdata);
2798  assert(consdata->validglbminact);
2799  assert(consdata->validglbmaxact);
2800  }
2801  assert(consdata->glbminactivity < SCIP_INVALID);
2802  assert(consdata->glbmaxactivity < SCIP_INVALID);
2803  assert(consdata->glbminactivityneginf >= 0);
2804  assert(consdata->glbminactivityposinf >= 0);
2805  assert(consdata->glbmaxactivityneginf >= 0);
2806  assert(consdata->glbmaxactivityposinf >= 0);
2807  assert(consdata->glbminactivityneghuge >= 0);
2808  assert(consdata->glbminactivityposhuge >= 0);
2809  assert(consdata->glbmaxactivityneghuge >= 0);
2810  assert(consdata->glbmaxactivityposhuge >= 0);
2811 
2812  if( glbminactivity != NULL )
2813  {
2814  assert(isminsettoinfinity != NULL);
2815  assert(minisrelax != NULL);
2816 
2817  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2818  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2819  glbminactivity, minisrelax, isminsettoinfinity);
2820  }
2821 
2822  if( glbmaxactivity != NULL )
2823  {
2824  assert(ismaxsettoinfinity != NULL);
2825  assert(maxisrelax != NULL);
2826 
2827  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2828  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2829  glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2830  }
2831 }
2832 
2833 /** gets global activity bounds for constraint after setting variable to zero */
2834 static
2836  SCIP* scip, /**< SCIP data structure */
2837  SCIP_CONSDATA* consdata, /**< linear constraint */
2838  SCIP_VAR* var, /**< variable to calculate activity residual for */
2839  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2840  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2841  * relaxed acticities ignored, anyway? */
2842  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2843  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2844  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2845  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2846  * contributions), or equal to the exact residual minactivity */
2847  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2848  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2849  * contributions), or equal to the exact residual minactivity */
2850  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2851  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2852  )
2853 {
2854  SCIP_Real minactbound;
2855  SCIP_Real maxactbound;
2856  SCIP_Real absval;
2857 
2858  assert(scip != NULL);
2859  assert(consdata != NULL);
2860  assert(var != NULL);
2861  assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2862  || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2863 
2864  /* get activity bounds of linear constraint */
2865  if( !consdata->validactivities )
2866  consdataCalcActivities(scip, consdata);
2867 
2868  assert(consdata->glbminactivity < SCIP_INVALID);
2869  assert(consdata->glbmaxactivity < SCIP_INVALID);
2870  assert(consdata->glbminactivityneginf >= 0);
2871  assert(consdata->glbminactivityposinf >= 0);
2872  assert(consdata->glbmaxactivityneginf >= 0);
2873  assert(consdata->glbmaxactivityposinf >= 0);
2874 
2875  if( val > 0.0 )
2876  {
2877  minactbound = SCIPvarGetLbGlobal(var);
2878  maxactbound = SCIPvarGetUbGlobal(var);
2879  absval = val;
2880  }
2881  else
2882  {
2883  minactbound = -SCIPvarGetUbGlobal(var);
2884  maxactbound = -SCIPvarGetLbGlobal(var);
2885  absval = -val;
2886  }
2887 
2888  if( minresactivity != NULL )
2889  {
2890  assert(isminsettoinfinity != NULL);
2891  assert(minisrelax != NULL);
2892 
2893  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2894  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2895  */
2896  if( SCIPisInfinity(scip, minactbound) )
2897  {
2898  assert(consdata->glbminactivityposinf >= 1);
2899 
2900  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2901  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2902  minresactivity, minisrelax, isminsettoinfinity);
2903  }
2904  else if( SCIPisInfinity(scip, -minactbound) )
2905  {
2906  assert(consdata->glbminactivityneginf >= 1);
2907 
2908  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2909  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2910  minresactivity, minisrelax, isminsettoinfinity);
2911  }
2912  else if( SCIPisHugeValue(scip, minactbound * absval) )
2913  {
2914  assert(consdata->glbminactivityposhuge >= 1);
2915 
2916  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2917  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2918  minresactivity, minisrelax, isminsettoinfinity);
2919  }
2920  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2921  {
2922  assert(consdata->glbminactivityneghuge >= 1);
2923 
2924  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2925  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
2926  minresactivity, minisrelax, isminsettoinfinity);
2927  }
2928  else
2929  {
2930  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2931  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
2932  goodrelax, minresactivity, minisrelax, isminsettoinfinity);
2933  }
2934  }
2935 
2936  if( maxresactivity != NULL )
2937  {
2938  assert(ismaxsettoinfinity != NULL);
2939  assert(maxisrelax != NULL);
2940 
2941  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2942  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2943  */
2944  if( SCIPisInfinity(scip, -maxactbound) )
2945  {
2946  assert(consdata->glbmaxactivityneginf >= 1);
2947 
2948  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
2949  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2950  maxresactivity, maxisrelax, ismaxsettoinfinity);
2951  }
2952  else if( SCIPisInfinity(scip, maxactbound) )
2953  {
2954  assert(consdata->glbmaxactivityposinf >= 1);
2955 
2956  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
2957  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2958  maxresactivity, maxisrelax, ismaxsettoinfinity);
2959  }
2960  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2961  {
2962  assert(consdata->glbmaxactivityposhuge >= 1);
2963 
2964  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2965  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2966  maxresactivity, maxisrelax, ismaxsettoinfinity);
2967  }
2968  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2969  {
2970  assert(consdata->glbmaxactivityneghuge >= 1);
2971 
2972  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2973  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
2974  maxresactivity, maxisrelax, ismaxsettoinfinity);
2975  }
2976  else
2977  {
2978  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2979  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
2980  goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
2981  }
2982  }
2983 }
2984 
2985 /** calculates the activity of the linear constraint for given solution */
2986 static
2988  SCIP* scip, /**< SCIP data structure */
2989  SCIP_CONSDATA* consdata, /**< linear constraint data */
2990  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
2991  )
2992 {
2993  SCIP_Real activity;
2994 
2995  assert(scip != NULL);
2996  assert(consdata != NULL);
2997 
2998  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
2999  activity = consdataComputePseudoActivity(scip, consdata);
3000  else
3001  {
3002  SCIP_Real solval;
3003  int nposinf;
3004  int nneginf;
3005  SCIP_Bool negsign;
3006  int v;
3007 
3008  activity = 0.0;
3009  nposinf = 0;
3010  nneginf = 0;
3011 
3012  for( v = 0; v < consdata->nvars; ++v )
3013  {
3014  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
3015 
3016  if( consdata->vals[v] < 0 )
3017  negsign = TRUE;
3018  else
3019  negsign = FALSE;
3020 
3021  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
3022  ++nposinf;
3023  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
3024  ++nneginf;
3025  else
3026  activity += consdata->vals[v] * solval;
3027  }
3028  assert(nneginf >= 0 && nposinf >= 0);
3029 
3030  SCIPdebugMsg(scip, "activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
3031 
3032  /* check for amount of infinity values and correct the activity */
3033  if( nposinf > 0 && nneginf > 0 )
3034  activity = (consdata->rhs + consdata->lhs) / 2;
3035  else if( nposinf > 0 )
3036  activity = SCIPinfinity(scip);
3037  else if( nneginf > 0 )
3038  activity = -SCIPinfinity(scip);
3039 
3040  SCIPdebugMsg(scip, "corrected activity of linear constraint: %.15g\n", activity);
3041  }
3042 
3043  if( activity == SCIP_INVALID ) /*lint !e777*/
3044  return activity;
3045  else if( activity < 0 )
3046  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
3047  else
3048  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
3049 
3050  return activity;
3051 }
3052 
3053 /** calculates the feasibility of the linear constraint for given solution */
3054 static
3056  SCIP* scip, /**< SCIP data structure */
3057  SCIP_CONSDATA* consdata, /**< linear constraint data */
3058  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
3059  )
3060 {
3061  SCIP_Real activity;
3062 
3063  assert(scip != NULL);
3064  assert(consdata != NULL);
3065 
3066  activity = consdataGetActivity(scip, consdata, sol);
3067 
3068  if( activity == SCIP_INVALID ) /*lint !e777*/
3069  return -SCIPinfinity(scip);
3070 
3071  return MIN(consdata->rhs - activity, activity - consdata->lhs);
3073 
3074 /** updates bit signatures after adding a single coefficient */
3075 static
3077  SCIP_CONSDATA* consdata, /**< linear constraint data */
3078  int pos /**< position of coefficient to update signatures for */
3079  )
3080 {
3081  uint64_t varsignature;
3082  SCIP_Real lb;
3083  SCIP_Real ub;
3084  SCIP_Real val;
3085 
3086  assert(consdata != NULL);
3087  assert(consdata->validsignature);
3088 
3089  varsignature = SCIPhashSignature64(SCIPvarGetIndex(consdata->vars[pos]));
3090  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
3091  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
3092  val = consdata->vals[pos];
3093  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
3094  consdata->possignature |= varsignature;
3095  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
3096  consdata->negsignature |= varsignature;
3097 }
3098 
3099 /** calculates the bit signatures of the given constraint data */
3100 static
3102  SCIP_CONSDATA* consdata /**< linear constraint data */
3103  )
3104 {
3105  assert(consdata != NULL);
3106 
3107  if( !consdata->validsignature )
3108  {
3109  int i;
3110 
3111  consdata->validsignature = TRUE;
3112  consdata->possignature = 0;
3113  consdata->negsignature = 0;
3114  for( i = 0; i < consdata->nvars; ++i )
3115  consdataUpdateSignatures(consdata, i);
3116  }
3117 }
3119 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
3120 static
3121 SCIP_DECL_SORTINDCOMP(consdataCompVar)
3122 { /*lint --e{715}*/
3123  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
3124 
3125  assert(consdata != NULL);
3126  assert(0 <= ind1 && ind1 < consdata->nvars);
3127  assert(0 <= ind2 && ind2 < consdata->nvars);
3128 
3129  return SCIPvarCompare(consdata->vars[ind1], consdata->vars[ind2]);
3130 }
3131 
3132 /** permutes the constraint's variables according to a given permutation. */
3133 static
3134 void permSortConsdata(
3135  SCIP_CONSDATA* consdata, /**< the constraint data */
3136  int* perm, /**< the target permutation */
3137  int nvars /**< the number of variables */
3138  )
3139 { /*lint --e{715}*/
3140  SCIP_VAR* varv;
3141  SCIP_EVENTDATA* eventdatav;
3142  SCIP_Real valv;
3143  int v;
3144  int i;
3145  int nexti;
3146 
3147  assert(perm != NULL);
3148  assert(consdata != NULL);
3149 
3150  /* permute the variables in the linear constraint according to the target permutation */
3151  eventdatav = NULL;
3152  for( v = 0; v < nvars; ++v )
3153  {
3154  if( perm[v] != v )
3155  {
3156  varv = consdata->vars[v];
3157  valv = consdata->vals[v];
3158  if( consdata->eventdata != NULL )
3159  eventdatav = consdata->eventdata[v];
3160  i = v;
3161  do
3162  {
3163  assert(0 <= perm[i] && perm[i] < nvars);
3164  assert(perm[i] != i);
3165  consdata->vars[i] = consdata->vars[perm[i]];
3166  consdata->vals[i] = consdata->vals[perm[i]];
3167  if( consdata->eventdata != NULL )
3168  {
3169  consdata->eventdata[i] = consdata->eventdata[perm[i]];
3170  consdata->eventdata[i]->varpos = i;
3171  }
3172  nexti = perm[i];
3173  perm[i] = i;
3174  i = nexti;
3175  }
3176  while( perm[i] != v );
3177  consdata->vars[i] = varv;
3178  consdata->vals[i] = valv;
3179  if( consdata->eventdata != NULL )
3180  {
3181  consdata->eventdata[i] = eventdatav;
3182  consdata->eventdata[i]->varpos = i;
3183  }
3184  perm[i] = i;
3185  }
3186  }
3187 #ifdef SCIP_DEBUG
3188  /* check sorting */
3189  for( v = 0; v < nvars; ++v )
3190  {
3191  assert(perm[v] == v);
3192  assert(consdata->eventdata == NULL || consdata->eventdata[v]->varpos == v);
3193  }
3194 #endif
3195 }
3196 
3197 /** sorts linear constraint's variables depending on the stage of the solving process:
3198  * - during PRESOLVING
3199  * sorts variables by binaries, integers, implicit integers, and continuous variables,
3200  * and the variables of the same type by non-decreasing variable index
3201  *
3202  * - during SOLVING
3203  * sorts binary variables of the remaining problem w.r.t the absolute of their coefficient.
3204  * This fastens the propagation time of the constraint handler.
3205  */
3206 static
3208  SCIP* scip, /**< SCIP data structure */
3209  SCIP_CONSDATA* consdata /**< linear constraint data */
3210  )
3211 {
3212  assert(scip != NULL);
3213  assert(consdata != NULL);
3214 
3215  /* check if there are variables for sorting */
3216  if( consdata->nvars <= 1 )
3217  {
3218  consdata->sorted = TRUE;
3219  consdata->binvarssorted = TRUE;
3220  }
3221  else if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE && !consdata->sorted )
3222  {
3223  int* perm;
3225  /* get temporary memory to store the sorted permutation */
3226  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
3227 
3228  /* call sorting method */
3229  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
3230 
3231  permSortConsdata(consdata, perm, consdata->nvars);
3232 
3233  /* free temporary memory */
3234  SCIPfreeBufferArray(scip, &perm);
3235 
3236  consdata->sorted = TRUE;
3237  consdata->binvarssorted = FALSE;
3238  }
3239  else if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
3240  {
3241  SCIP_EVENTDATA** eventdata;
3242  SCIP_VAR** vars;
3243  SCIP_Real* vals;
3244  int nvars;
3245  int v;
3246  int lastbin;
3247 
3248  nvars = consdata->nvars;
3249  vars = consdata->vars;
3250  vals = consdata->vals;
3251  eventdata = consdata->eventdata;
3252  assert(vars != NULL || nvars == 0);
3253  assert(vals != NULL || nvars == 0);
3254 
3255  lastbin = 0;
3256  /* count binary variables and permute variables such that binaries appear first in the sorted vars array */
3257  for( v = 0; v < nvars; ++v )
3258  {
3259  assert( vars != NULL); /* for flexelint */
3260  assert( vals != NULL); /* for flexelint */
3261  if( SCIPvarIsBinary(vars[v]) )
3262  {
3263  /* swap variable at the end of the binary variables, if necessary */
3264  if( lastbin < v )
3265  {
3266  SCIP_VAR* tmpvar;
3267  SCIP_Real tmpval;
3268 
3269  tmpvar = vars[lastbin];
3270  tmpval = vals[lastbin];
3271 
3272  vars[lastbin] = vars[v];
3273  vals[lastbin] = vals[v];
3274 
3275  vars[v] = tmpvar;
3276  vals[v] = tmpval;
3277 
3278  if( eventdata != NULL )
3279  {
3280  SCIP_EVENTDATA* tmpeventdata;
3281 
3282  tmpeventdata = eventdata[lastbin];
3283  eventdata[lastbin] = eventdata[v];
3284  eventdata[lastbin]->varpos = lastbin;
3285  eventdata[v] = tmpeventdata;
3286  eventdata[v]->varpos = v;
3287  }
3288  assert(SCIPvarIsBinary(vars[lastbin]));
3289  }
3290 #ifndef NDEBUG
3291  else
3292  assert(lastbin == v);
3293 #endif
3294  ++lastbin;
3295  }
3296  }
3297  consdata->nbinvars = lastbin;
3298 
3299 #ifndef NDEBUG
3300  /* check sorting */
3301  for( v = 0; v < nvars; ++v )
3302  {
3303  assert(vars != NULL); /* for flexelint */
3304  assert(eventdata == NULL || eventdata[v]->varpos == v);
3305  assert((v >= consdata->nbinvars && !SCIPvarIsBinary(vars[v])) || (v < consdata->nbinvars && SCIPvarIsBinary(vars[v])));
3306  }
3307 #endif
3308 
3309  if( consdata->nbinvars > 1 )
3310  {
3311  SCIP_Real* absvals;
3312  int* perm;
3313 
3314  assert(lastbin == consdata->nbinvars);
3315  assert(lastbin <= nvars);
3316  assert(vals != NULL);
3317 
3318  /* initialize absolute coefficients and the target permutation for binary variables */
3319  SCIP_CALL( SCIPallocBufferArray(scip, &absvals, lastbin) );
3320  SCIP_CALL( SCIPallocBufferArray(scip, &perm, lastbin) );
3321 
3322  for( v = 0; v < lastbin; ++v )
3323  {
3324  absvals[v] = ABS(vals[v]);
3325  perm[v] = v;
3326  }
3327 
3328  /* execute the sorting */
3329  SCIPsortDownRealInt(absvals, perm, lastbin);
3330 
3331  permSortConsdata(consdata, perm, lastbin);
3332 
3333  /* free temporary arrays */
3334  SCIPfreeBufferArray(scip, &perm);
3335  SCIPfreeBufferArray(scip, &absvals);
3336  }
3337  consdata->binvarssorted = TRUE;
3338 
3339  /* presolve sorting cannot be guaranteed after binary sorting */
3340  consdata->sorted = (consdata->sorted && consdata->nbinvars == 0);
3341  }
3342  assert(SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE || consdata->binvarssorted);
3343  assert(SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE || consdata->sorted);
3344 
3345  return SCIP_OKAY;
3346 }
3347 
3348 
3349 /*
3350  * local linear constraint handler methods
3351  */
3352 
3353 /** sets left hand side of linear constraint */
3354 static
3356  SCIP* scip, /**< SCIP data structure */
3357  SCIP_CONS* cons, /**< linear constraint */
3358  SCIP_Real lhs /**< new left hand side */
3359  )
3360 {
3361  SCIP_CONSDATA* consdata;
3362 
3363  assert(scip != NULL);
3364  assert(cons != NULL);
3365  assert(!SCIPisInfinity(scip, lhs));
3366 
3367  /* adjust value to not be smaller than -inf */
3368  if ( SCIPisInfinity(scip, -lhs) )
3369  lhs = -SCIPinfinity(scip);
3370 
3371  consdata = SCIPconsGetData(cons);
3372  assert(consdata != NULL);
3373  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3374  assert(!SCIPisInfinity(scip, consdata->lhs));
3375 
3376  /* check whether the side is not changed */
3377  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3378  return SCIP_OKAY;
3379 
3380  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3381  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3382  {
3383  consdata->rhs = lhs;
3384  assert(consdata->row == NULL);
3385  }
3386 
3387  /* if necessary, update the rounding locks of variables */
3388  if( SCIPconsIsLocked(cons) )
3389  {
3390  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3391  {
3392  SCIP_VAR** vars;
3393  SCIP_Real* vals;
3394  int v;
3395 
3396  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3397  vars = consdata->vars;
3398  vals = consdata->vals;
3399 
3400  for( v = 0; v < consdata->nvars; ++v )
3401  {
3402  assert(vars[v] != NULL);
3403  assert(!SCIPisZero(scip, vals[v]));
3404 
3405  if( SCIPisPositive(scip, vals[v]) )
3406  {
3407  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3408  }
3409  else
3410  {
3411  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3412  }
3413  }
3414  }
3415  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3416  {
3417  SCIP_VAR** vars;
3418  SCIP_Real* vals;
3419  int v;
3420 
3421  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3422  vars = consdata->vars;
3423  vals = consdata->vals;
3424 
3425  for( v = 0; v < consdata->nvars; ++v )
3426  {
3427  assert(vars[v] != NULL);
3428  assert(!SCIPisZero(scip, vals[v]));
3429 
3430  if( SCIPisPositive(scip, vals[v]) )
3431  {
3432  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3433  }
3434  else
3435  {
3436  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3437  }
3438  }
3439  }
3440  }
3441 
3442  /* 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 */
3443  if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3444  {
3445  consdata->boundstightened = 0;
3446  consdata->presolved = FALSE;
3447  consdata->cliquesadded = FALSE;
3448  consdata->implsadded = FALSE;
3449 
3450  /* mark the constraint for propagation */
3451  if( SCIPconsIsTransformed(cons) )
3452  {
3453  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3454  }
3455  }
3456 
3457  /* set new left hand side and update constraint data */
3458  consdata->lhs = lhs;
3459  consdata->changed = TRUE;
3460  consdata->normalized = FALSE;
3461  consdata->upgradetried = FALSE;
3462  consdata->rangedrowpropagated = 0;
3463 
3464 
3465  /* update the lhs of the LP row */
3466  if( consdata->row != NULL )
3467  {
3468  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3469  }
3470 
3471  return SCIP_OKAY;
3472 }
3473 
3474 /** sets right hand side of linear constraint */
3475 static
3477  SCIP* scip, /**< SCIP data structure */
3478  SCIP_CONS* cons, /**< linear constraint */
3479  SCIP_Real rhs /**< new right hand side */
3480  )
3481 {
3482  SCIP_CONSDATA* consdata;
3483 
3484  assert(scip != NULL);
3485  assert(cons != NULL);
3486  assert(!SCIPisInfinity(scip, -rhs));
3487 
3488  /* adjust value to not be larger than inf */
3489  if ( SCIPisInfinity(scip, rhs) )
3490  rhs = SCIPinfinity(scip);
3491 
3492  consdata = SCIPconsGetData(cons);
3493  assert(consdata != NULL);
3494  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3495  assert(!SCIPisInfinity(scip, -consdata->rhs));
3496 
3497  /* check whether the side is not changed */
3498  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3499  return SCIP_OKAY;
3500 
3501  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3502  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3503  {
3504  consdata->lhs = rhs;
3505  assert(consdata->row == NULL);
3506  }
3507 
3508  /* if necessary, update the rounding locks of variables */
3509  if( SCIPconsIsLocked(cons) )
3510  {
3511  assert(SCIPconsIsTransformed(cons));
3512 
3513  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3514  {
3515  SCIP_VAR** vars;
3516  SCIP_Real* vals;
3517  int v;
3518 
3519  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3520  vars = consdata->vars;
3521  vals = consdata->vals;
3522 
3523  for( v = 0; v < consdata->nvars; ++v )
3524  {
3525  assert(vars[v] != NULL);
3526  assert(!SCIPisZero(scip, vals[v]));
3527 
3528  if( SCIPisPositive(scip, vals[v]) )
3529  {
3530  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3531  }
3532  else
3533  {
3534  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3535  }
3536  }
3537  }
3538  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3539  {
3540  SCIP_VAR** vars;
3541  SCIP_Real* vals;
3542  int v;
3543 
3544  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3545  vars = consdata->vars;
3546  vals = consdata->vals;
3547 
3548  for( v = 0; v < consdata->nvars; ++v )
3549  {
3550  assert(vars[v] != NULL);
3551  assert(!SCIPisZero(scip, vals[v]));
3552 
3553  if( SCIPisPositive(scip, vals[v]) )
3554  {
3555  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3556  }
3557  else
3558  {
3559  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3560  }
3561  }
3562  }
3563  }
3564 
3565  /* 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 */
3566  if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3567  {
3568  consdata->boundstightened = 0;
3569  consdata->presolved = FALSE;
3570  consdata->cliquesadded = FALSE;
3571  consdata->implsadded = FALSE;
3572 
3573  /* mark the constraint for propagation */
3574  if( SCIPconsIsTransformed(cons) )
3575  {
3576  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3577  }
3578  }
3579 
3580  /* set new right hand side and update constraint data */
3581  consdata->rhs = rhs;
3582  consdata->changed = TRUE;
3583  consdata->normalized = FALSE;
3584  consdata->upgradetried = FALSE;
3585  consdata->rangedrowpropagated = 0;
3586 
3587  /* update the rhs of the LP row */
3588  if( consdata->row != NULL )
3589  {
3590  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3591  }
3592 
3593  return SCIP_OKAY;
3594 }
3595 
3596 /** adds coefficient in linear constraint */
3597 static
3599  SCIP* scip, /**< SCIP data structure */
3600  SCIP_CONS* cons, /**< linear constraint */
3601  SCIP_VAR* var, /**< variable of constraint entry */
3602  SCIP_Real val /**< coefficient of constraint entry */
3603  )
3604 {
3605  SCIP_CONSDATA* consdata;
3606  SCIP_Bool transformed;
3607 
3608  assert(scip != NULL);
3609  assert(cons != NULL);
3610  assert(var != NULL);
3611 
3612  /* ignore coefficient if it is nearly zero */
3613  if( SCIPisZero(scip, val) )
3614  return SCIP_OKAY;
3616  consdata = SCIPconsGetData(cons);
3617  assert(consdata != NULL);
3618 
3619  /* are we in the transformed problem? */
3620  transformed = SCIPconsIsTransformed(cons);
3621 
3622  /* always use transformed variables in transformed constraints */
3623  if( transformed )
3624  {
3625  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3626  }
3627  assert(var != NULL);
3628  assert(transformed == SCIPvarIsTransformed(var));
3629 
3630  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3631  consdata->vars[consdata->nvars] = var;
3632  consdata->vals[consdata->nvars] = val;
3633  consdata->nvars++;
3634 
3635  /* capture variable */
3636  SCIP_CALL( SCIPcaptureVar(scip, var) );
3637 
3638  /* if we are in transformed problem, the variable needs an additional event data */
3639  if( transformed )
3640  {
3641  if( consdata->eventdata != NULL )
3642  {
3643  SCIP_CONSHDLR* conshdlr;
3644  SCIP_CONSHDLRDATA* conshdlrdata;
3645 
3646  /* check for event handler */
3647  conshdlr = SCIPconsGetHdlr(cons);
3648  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3649  assert(conshdlrdata != NULL);
3650  assert(conshdlrdata->eventhdlr != NULL);
3651 
3652  /* initialize eventdata array */
3653  consdata->eventdata[consdata->nvars-1] = NULL;
3654 
3655  /* catch bound change events of variable */
3656  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3657  }
3658 
3659  /* update minimum and maximum activities */
3660  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3661 
3662  /* update maximum activity delta */
3663  if( !SCIPisInfinity(scip, consdata->maxactdelta ) )
3664  {
3665  SCIP_Real lb;
3666  SCIP_Real ub;
3667 
3668  lb = SCIPvarGetLbLocal(var);
3669  ub = SCIPvarGetUbLocal(var);
3670 
3671  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3672  {
3673  consdata->maxactdelta = SCIPinfinity(scip);
3674  consdata->maxactdeltavar = var;
3675  }
3676  else
3677  {
3678  SCIP_Real domain = ub - lb;
3679  SCIP_Real delta = REALABS(val) * domain;
3680 
3681  if( delta > consdata->maxactdelta )
3682  {
3683  consdata->maxactdelta = delta;
3684  consdata->maxactdeltavar = var;
3685  }
3686  }
3687  }
3688  }
3689 
3690  /* install rounding locks for new variable */
3691  SCIP_CALL( lockRounding(scip, cons, var, val) );
3692 
3693  /* mark the constraint for propagation */
3694  if( transformed )
3695  {
3696  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3697  }
3698 
3699  consdata->boundstightened = 0;
3700  consdata->presolved = FALSE;
3701  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3702 
3703  if( consdata->validsignature )
3704  consdataUpdateSignatures(consdata, consdata->nvars-1);
3705 
3706  consdata->changed = TRUE;
3707  consdata->normalized = FALSE;
3708  consdata->upgradetried = FALSE;
3709  consdata->cliquesadded = FALSE;
3710  consdata->implsadded = FALSE;
3711  consdata->rangedrowpropagated = 0;
3712 
3713  if( consdata->nvars == 1 )
3714  {
3715  consdata->binvarssorted = TRUE;
3716  consdata->sorted = TRUE;
3717  consdata->merged = TRUE;
3718  }
3719  else
3720  {
3721  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3722  consdata->sorted = consdata->sorted
3723  && (SCIPvarCompare(consdata->vars[consdata->nvars-2], consdata->vars[consdata->nvars-1]) <= 0);
3724  consdata->merged = FALSE;
3725  }
3726 
3727  /* update hascontvar and hasnonbinvar flags */
3728  if( consdata->hasnonbinvalid && !consdata->hascontvar )
3729  {
3730  SCIP_VARTYPE vartype = SCIPvarGetType(var);
3731 
3732  if( vartype != SCIP_VARTYPE_BINARY )
3733  {
3734  consdata->hasnonbinvar = TRUE;
3735 
3736  if( vartype == SCIP_VARTYPE_CONTINUOUS )
3737  consdata->hascontvar = TRUE;
3738  }
3739  }
3740 
3741  /* add the new coefficient to the LP row */
3742  if( consdata->row != NULL )
3743  {
3744  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3745  }
3746 
3747  return SCIP_OKAY;
3748 }
3749 
3750 /** deletes coefficient at given position from linear constraint data */
3751 static
3753  SCIP* scip, /**< SCIP data structure */
3754  SCIP_CONS* cons, /**< linear constraint */
3755  int pos /**< position of coefficient to delete */
3756  )
3757 {
3758  SCIP_CONSDATA* consdata;
3759  SCIP_VAR* var;
3760  SCIP_Real val;
3761 
3762  assert(scip != NULL);
3763  assert(cons != NULL);
3764 
3765  consdata = SCIPconsGetData(cons);
3766  assert(consdata != NULL);
3767  assert(0 <= pos && pos < consdata->nvars);
3768 
3769  var = consdata->vars[pos];
3770  val = consdata->vals[pos];
3771  assert(var != NULL);
3772 
3773  /* remove rounding locks for deleted variable */
3774  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3775 
3776  /* if we are in transformed problem, delete the event data of the variable */
3777  if( SCIPconsIsTransformed(cons) )
3778  {
3779  SCIP_CONSHDLR* conshdlr;
3780  SCIP_CONSHDLRDATA* conshdlrdata;
3781 
3782  /* check for event handler */
3783  conshdlr = SCIPconsGetHdlr(cons);
3784  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3785  assert(conshdlrdata != NULL);
3786  assert(conshdlrdata->eventhdlr != NULL);
3787 
3788  /* drop bound change events of variable */
3789  if( consdata->eventdata != NULL )
3790  {
3791  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3792  assert(consdata->eventdata[pos] == NULL);
3793  }
3794  }
3795 
3796  /* move the last variable to the free slot */
3797  if( pos != consdata->nvars-1 )
3798  {
3799  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(consdata->vars[pos]);
3800 
3801  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3802  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3803 
3804  if( consdata->eventdata != NULL )
3805  {
3806  consdata->eventdata[pos] = consdata->eventdata[consdata->nvars-1];
3807  assert(consdata->eventdata[pos] != NULL);
3808  consdata->eventdata[pos]->varpos = pos;
3809  }
3810  consdata->sorted = consdata->sorted && (pos + 2 >= consdata->nvars || (SCIPvarCompare(consdata->vars[pos], consdata->vars[pos + 1]) <= 0));
3811  }
3812  consdata->nvars--;
3813 
3814  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3815  * of the remaining variable, or give exactly 0.0)
3816  */
3817  if( consdata->nvars <= 1 )
3818  consdataInvalidateActivities(consdata);
3819  else
3820  {
3821  if( SCIPconsIsTransformed(cons) )
3822  {
3823  /* if we are in transformed problem, update minimum and maximum activities */
3824  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3825 
3826  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
3827  * delta needs to be recalculated on the next real propagation
3828  */
3829  if( consdata->maxactdeltavar == var )
3830  {
3831  consdata->maxactdelta = SCIP_INVALID;
3832  consdata->maxactdeltavar = NULL;
3833  }
3834  }
3835  }
3836 
3837  /* mark the constraint for propagation */
3838  if( SCIPconsIsTransformed(cons) )
3839  {
3840  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3841  }
3842 
3843  consdata->boundstightened = 0;
3844  consdata->presolved = FALSE;
3845  consdata->validsignature = FALSE;
3846  consdata->changed = TRUE;
3847  consdata->normalized = FALSE;
3848  consdata->upgradetried = FALSE;
3849  consdata->cliquesadded = FALSE;
3850  consdata->implsadded = FALSE;
3851  consdata->rangedrowpropagated = 0;
3852 
3853  /* check if hasnonbinvar flag might be incorrect now */
3854  if( consdata->hasnonbinvar && SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
3855  {
3856  consdata->hasnonbinvalid = FALSE;
3857  }
3858 
3859  /* delete coefficient from the LP row */
3860  if( consdata->row != NULL )
3861  {
3862  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3863  }
3864 
3865  /* release variable */
3866  SCIP_CALL( SCIPreleaseVar(scip, &var) );
3867 
3868  return SCIP_OKAY;
3869 }
3870 
3871 /** changes coefficient value at given position of linear constraint data */
3872 static
3874  SCIP* scip, /**< SCIP data structure */
3875  SCIP_CONS* cons, /**< linear constraint */
3876  int pos, /**< position of coefficient to delete */
3877  SCIP_Real newval /**< new value of coefficient */
3878  )
3879 {
3880  SCIP_CONSDATA* consdata;
3881  SCIP_VAR* var;
3882  SCIP_Real val;
3883 
3884  assert(scip != NULL);
3885  assert(cons != NULL);
3886  assert(!SCIPisZero(scip, newval));
3887 
3888  consdata = SCIPconsGetData(cons);
3889  assert(consdata != NULL);
3890  assert(0 <= pos && pos < consdata->nvars);
3891  assert(!SCIPisZero(scip, newval));
3892 
3893  var = consdata->vars[pos];
3894  val = consdata->vals[pos];
3895  assert(var != NULL);
3896  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
3897 
3898  /* if necessary, update the rounding locks of the variable */
3899  if( SCIPconsIsLocked(cons) && newval * val < 0.0 )
3900  {
3901  assert(SCIPconsIsTransformed(cons));
3902 
3903  /* remove rounding locks for variable with old coefficient */
3904  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3905 
3906  /* install rounding locks for variable with new coefficient */
3907  SCIP_CALL( lockRounding(scip, cons, var, newval) );
3908  }
3909 
3910  /* change the value */
3911  consdata->vals[pos] = newval;
3912 
3913  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3914 
3915  /* update minimum and maximum activities */
3916  if( SCIPconsIsTransformed(cons) )
3917  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
3918 
3919  /* mark the constraint for propagation */
3920  if( SCIPconsIsTransformed(cons) )
3921  {
3922  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
3923  }
3924 
3925  consdata->boundstightened = 0;
3926  consdata->presolved = FALSE;
3927  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
3928  consdata->changed = TRUE;
3929  consdata->normalized = FALSE;
3930  consdata->upgradetried = FALSE;
3931  consdata->cliquesadded = FALSE;
3932  consdata->implsadded = FALSE;
3933  consdata->rangedrowpropagated = 0;
3934 
3935  return SCIP_OKAY;
3936 }
3937 
3938 /** scales a linear constraint with a constant scalar */
3939 static
3941  SCIP* scip, /**< SCIP data structure */
3942  SCIP_CONS* cons, /**< linear constraint to scale */
3943  SCIP_Real scalar /**< value to scale constraint with */
3944  )
3945 {
3946  SCIP_CONSDATA* consdata;
3947  SCIP_Real newval;
3948  SCIP_Real absscalar;
3949  int i;
3950 
3951  assert(scip != NULL);
3952  assert(cons != NULL);
3953 
3954  consdata = SCIPconsGetData(cons);
3955  assert(consdata != NULL);
3956  assert(consdata->row == NULL);
3957  assert(!SCIPisEQ(scip, scalar, 1.0));
3958 
3959  /* scale the coefficients */
3960  for( i = consdata->nvars - 1; i >= 0; --i )
3961  {
3962  newval = scalar * consdata->vals[i];
3963 
3964  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
3965  * flooring down our new value
3966  */
3967  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
3968  newval = SCIPfeasFloor(scip, newval + 0.5);
3969 
3970  if( SCIPisZero(scip, newval) )
3971  {
3972  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
3973  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
3974  SCIP_CALL( delCoefPos(scip, cons, i) );
3975  }
3976  else
3977  consdata->vals[i] = newval;
3978  }
3979 
3980  /* scale the sides */
3981  if( scalar < 0.0 )
3982  {
3983  SCIP_Real lhs;
3984 
3985  lhs = consdata->lhs;
3986  consdata->lhs = -consdata->rhs;
3987  consdata->rhs = -lhs;
3988  }
3989  absscalar = REALABS(scalar);
3990  if( !SCIPisInfinity(scip, -consdata->lhs) )
3991  {
3992  newval = absscalar * consdata->lhs;
3993 
3994  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
3995  * flooring down our new value
3996  */
3997  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
3998  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
3999  else
4000  consdata->lhs = newval;
4001  }
4002  if( !SCIPisInfinity(scip, consdata->rhs) )
4003  {
4004  newval = absscalar * consdata->rhs;
4005 
4006  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
4007  * our new value
4008  */
4009  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
4010  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
4011  else
4012  consdata->rhs = newval;
4013  }
4014 
4015  consdataInvalidateActivities(consdata);
4016  consdata->cliquesadded = FALSE;
4017  consdata->implsadded = FALSE;
4018 
4019  return SCIP_OKAY;
4020 }
4021 
4022 /* perform deletion of variables in all constraints of the constraint handler */
4023 static
4025  SCIP* scip, /**< SCIP data structure */
4026  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
4027  SCIP_CONS** conss, /**< array of constraints */
4028  int nconss /**< number of constraints */
4029  )
4030 {
4031  SCIP_CONSDATA* consdata;
4032  int i;
4033  int v;
4034 
4035  assert(scip != NULL);
4036  assert(conshdlr != NULL);
4037  assert(conss != NULL);
4038  assert(nconss >= 0);
4039  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
4040 
4041  /* iterate over all constraints */
4042  for( i = 0; i < nconss; i++ )
4043  {
4044  consdata = SCIPconsGetData(conss[i]);
4045 
4046  /* constraint is marked, that some of its variables were deleted */
4047  if( consdata->varsdeleted )
4048  {
4049  /* iterate over all variables of the constraint and delete them from the constraint */
4050  for( v = consdata->nvars - 1; v >= 0; --v )
4051  {
4052  if( SCIPvarIsDeleted(consdata->vars[v]) )
4053  {
4054  SCIP_CALL( delCoefPos(scip, conss[i], v) );
4055  }
4056  }
4057  consdata->varsdeleted = FALSE;
4058  }
4059  }
4060 
4061  return SCIP_OKAY;
4062 }
4063 
4064 
4065 /** normalizes a linear constraint with the following rules:
4066  * - if all coefficients have them same absolute value, change them to (-)1.0
4067  * - multiplication with +1 or -1:
4068  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
4069  * if the current rule doesn't determine the sign):
4070  * 1. the right hand side must not be negative
4071  * 2. the right hand side must not be infinite
4072  * 3. the absolute value of the right hand side must be greater than that of the left hand side
4073  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
4074  * 5. multiply with +1
4075  * - rationals to integrals
4076  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
4077  * by the smallest common multiple of all denominators to get integral coefficients.
4078  * Forbid large denominators due to numerical stability.
4079  * - division by greatest common divisor
4080  * If all coefficients are integral, divide them by the greatest common divisor.
4081  */
4082 static
4084  SCIP* scip, /**< SCIP data structure */
4085  SCIP_CONS* cons /**< linear constraint to normalize */
4086  )
4087 {
4088  SCIP_CONSDATA* consdata;
4089  SCIP_VAR** vars;
4090  SCIP_Real* vals;
4091  SCIP_Longint scm;
4092  SCIP_Longint nominator;
4093  SCIP_Longint denominator;
4094  SCIP_Longint gcd;
4095  SCIP_Longint maxmult;
4096  SCIP_Real epsilon;
4097  SCIP_Real feastol;
4098  SCIP_Real maxabsval;
4099  SCIP_Real minabsval;
4100  SCIP_Bool success;
4101  SCIP_Bool onlyintegral;
4102  int nvars;
4103  int mult;
4104  int nposcoeffs;
4105  int nnegcoeffs;
4106  int i;
4107  int v;
4108 
4109  assert(scip != NULL);
4110  assert(cons != NULL);
4111 
4112  /* we must not change a modifiable constraint in any way */
4113  if( SCIPconsIsModifiable(cons) )
4114  return SCIP_OKAY;
4115 
4116  /* get constraint data */
4117  consdata = SCIPconsGetData(cons);
4118  assert(consdata != NULL);
4119 
4120  /* check, if the constraint is already normalized */
4121  if( consdata->normalized )
4122  return SCIP_OKAY;
4123 
4124  /* get coefficient arrays */
4125  vals = consdata->vals;
4126  nvars = consdata->nvars;
4127  vars = consdata->vars;
4128  assert(nvars == 0 || vars != NULL);
4129  assert(nvars == 0 || vals != NULL);
4130 
4131  if( nvars == 0 )
4132  {
4133  consdata->normalized = TRUE;
4134  return SCIP_OKAY;
4135  }
4136 
4137  assert(vars != NULL);
4138  assert(vals != NULL);
4139 
4140  /* get maximal and minimal absolute coefficient */
4141  maxabsval = consdataGetMaxAbsval(consdata);
4142  minabsval = consdataGetMinAbsval(consdata);
4143 
4144  /* return if scaling by maxval will eliminate coefficients */
4145  if( SCIPisZero(scip, minabsval/maxabsval) )
4146  return SCIP_OKAY;
4147 
4148  /* check if all coefficients are in absolute value equal, and not 1.0 */
4149  if( !SCIPisEQ(scip, maxabsval, 1.0) )
4150  {
4151  SCIP_Bool abscoefsequ;
4152 
4153  abscoefsequ = TRUE;
4154 
4155  for( v = nvars - 1; v >= 0; --v )
4156  {
4157  if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
4158  {
4159  abscoefsequ = FALSE;
4160  break;
4161  }
4162  }
4163 
4164  /* all coefficients are in absolute value equal, so change them to (-)1.0 */
4165  if( abscoefsequ )
4166  {
4167  SCIPdebugMsg(scip, "divide linear constraint with %g, because all coefficents are in absolute value the same\n", maxabsval);
4168  SCIPdebugPrintCons(scip, cons, NULL);
4169  SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
4170 
4171  if( consdata->validmaxabsval )
4172  {
4173  if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
4174  consdata->maxabsval = 1.0;
4175  if( !SCIPisEQ(scip, consdata->minabsval, 1.0) )
4176  consdata->minabsval = 1.0;
4177 
4178  maxabsval = 1.0;
4179  }
4180  else
4181  {
4182  /* get maximal absolute coefficient */
4183  maxabsval = consdataGetMaxAbsval(consdata);
4184  }
4185 
4186  /* get new consdata information, because scalecons() might have deleted variables */
4187  vals = consdata->vals;
4188  nvars = consdata->nvars;
4189  vars = consdata->vars;
4190 
4191  assert(nvars == 0 || vars != NULL);
4192  assert(nvars == 0 || vals != NULL);
4193  }
4194  }
4195 
4196  /* nvars might have changed */
4197  if( nvars == 0 )
4198  {
4199  consdata->normalized = TRUE;
4200  return SCIP_OKAY;
4201  }
4202 
4203  assert(vars != NULL);
4204  assert(vals != NULL);
4205 
4206  /* calculate the maximal multiplier for common divisor calculation:
4207  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
4208  * which means, a value of feastol/epsilon should be used as maximal multiplier;
4209  * additionally, we don't want to scale the constraint if this would lead to too
4210  * large coefficients
4211  */
4212  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
4213  feastol = SCIPfeastol(scip);
4214  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
4215  maxmult = MIN(maxmult, (SCIP_Longint)( MAXSCALEDCOEF/MAX(maxabsval, 1.0)));
4216 
4217  if( !consdata->hasnonbinvalid )
4218  consdataCheckNonbinvar(consdata);
4219 
4220  /* if all variables are of integral type we will allow a greater multiplier */
4221  if( !consdata->hascontvar )
4222  {
4223  if( SCIPvarGetType(vars[nvars - 1]) != SCIP_VARTYPE_CONTINUOUS )
4224  {
4225  maxmult = (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0)));
4226  }
4227  }
4228  else
4229  {
4230  SCIP_Bool foundcont;
4231 
4232  foundcont = FALSE;
4233 
4234  for( v = nvars - 1; v >= 0; --v )
4235  {
4236  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
4237  {
4238  foundcont = TRUE;
4239  break;
4240  }
4241  }
4242 
4243  if( !foundcont )
4244  {
4245  maxmult = (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0)));
4246  }
4247  }
4248 
4249  /*
4250  * multiplication with +1 or -1
4251  */
4252  mult = 0;
4253 
4254  /* 1. the right hand side must not be negative */
4255  if( SCIPisPositive(scip, consdata->lhs) )
4256  mult = +1;
4257  else if( SCIPisNegative(scip, consdata->rhs) )
4258  mult = -1;
4259 
4260  if( mult == 0 )
4261  {
4262  /* 2. the right hand side must not be infinite */
4263  if( SCIPisInfinity(scip, -consdata->lhs) )
4264  mult = +1;
4265  else if( SCIPisInfinity(scip, consdata->rhs) )
4266  mult = -1;
4267  }
4268 
4269  if( mult == 0 )
4270  {
4271  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
4272  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4273  mult = +1;
4274  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
4275  mult = -1;
4276  }
4277 
4278  if( mult == 0 )
4279  {
4280  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
4281  nposcoeffs = 0;
4282  nnegcoeffs = 0;
4283  for( i = 0; i < nvars; ++i )
4284  {
4285  if( vals[i] > 0.0 )
4286  nposcoeffs++;
4287  else
4288  nnegcoeffs++;
4289  }
4290  if( nposcoeffs > nnegcoeffs )
4291  mult = +1;
4292  else if( nposcoeffs < nnegcoeffs )
4293  mult = -1;
4294  }
4295 
4296  if( mult == 0 )
4297  {
4298  /* 5. multiply with +1 */
4299  mult = +1;
4300  }
4301 
4302  assert(mult == +1 || mult == -1);
4303  if( mult == -1 )
4304  {
4305  /* scale the constraint with -1 */
4306  SCIPdebugMsg(scip, "multiply linear constraint with -1.0\n");
4307  SCIPdebugPrintCons(scip, cons, NULL);
4308  SCIP_CALL( scaleCons(scip, cons, -1.0) );
4309 
4310  /* scalecons() can delete variables, but scaling with -1 should not do that */
4311  assert(nvars == consdata->nvars);
4312  }
4313 
4314  /*
4315  * rationals to integrals
4316  *
4317  * @todo try scaling only on behalf of non-continuous variables
4318  */
4319  success = TRUE;
4320  scm = 1;
4321  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
4322  {
4323  if( !SCIPisIntegral(scip, vals[i]) )
4324  {
4325  /* epsilon has been slightly decreased above - to be on the safe side */
4326  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
4327  if( success )
4328  scm = SCIPcalcSmaComMul(scm, denominator);
4329  }
4330  }
4331  assert(scm >= 1);
4332 
4333  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
4334  * their greatest common divisor
4335  */
4336  onlyintegral = TRUE;
4337  if( scm == 1 )
4338  {
4339  for( i = nvars - 1; i >= 0; --i )
4340  {
4341  if( !SCIPisIntegral(scip, vals[i]) )
4342  {
4343  onlyintegral = FALSE;
4344  break;
4345  }
4346  }
4347  }
4348 
4349  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
4350  if( success && scm != 1 )
4351  {
4352  /* scale the constraint with the smallest common multiple of all denominators */
4353  SCIPdebugMsg(scip, "scale linear constraint with %" SCIP_LONGINT_FORMAT " to make coefficients integral\n", scm);
4354  SCIPdebugPrintCons(scip, cons, NULL);
4355  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
4356 
4357  if( consdata->validmaxabsval )
4358  {
4359  consdata->maxabsval *= REALABS((SCIP_Real)scm);
4360  if( !SCIPisIntegral(scip, consdata->maxabsval) )
4361  {
4362  consdata->validmaxabsval = FALSE;
4363  consdata->maxabsval = SCIP_INVALID;
4364  consdataCalcMaxAbsval(consdata);
4365  }
4366  }
4367 
4368  if( consdata->validminabsval )
4369  {
4370  consdata->minabsval *= REALABS((SCIP_Real)scm);
4371  if( !SCIPisIntegral(scip, consdata->minabsval) )
4372  {
4373  consdata->validminabsval = FALSE;
4374  consdata->minabsval = SCIP_INVALID;
4375  consdataCalcMinAbsval(consdata);
4376  }
4377  }
4378 
4379  /* get new consdata information, because scalecons() might have deleted variables */
4380  vals = consdata->vals;
4381  nvars = consdata->nvars;
4382  assert(nvars == 0 || vals != NULL);
4383  }
4384 
4385  /*
4386  * division by greatest common divisor
4387  */
4388  if( success && nvars >= 1 )
4389  {
4390  /* all coefficients are integral: divide them by their greatest common divisor */
4391  assert(SCIPisIntegral(scip, vals[0]));
4392 
4393  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
4394  for( i = 1; i < nvars && gcd > 1; ++i )
4395  {
4396  assert(SCIPisIntegral(scip, vals[i]));
4397  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
4398  }
4399 
4400  if( gcd > 1 )
4401  {
4402  /* divide the constraint by the greatest common divisor of the coefficients */
4403  SCIPdebugMsg(scip, "divide linear constraint by greatest common divisor %" SCIP_LONGINT_FORMAT "\n", gcd);
4404  SCIPdebugPrintCons(scip, cons, NULL);
4405  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
4406 
4407  if( consdata->validmaxabsval )
4408  {
4409  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
4410  }
4411  if( consdata->validminabsval )
4412  {
4413  consdata->minabsval /= REALABS((SCIP_Real)gcd);
4414  }
4415  }
4416  }
4417 
4418  /* mark constraint to be normalized */
4419  consdata->normalized = TRUE;
4420 
4421  SCIPdebugMsg(scip, "normalized constraint:\n");
4422  SCIPdebugPrintCons(scip, cons, NULL);
4423 
4424  return SCIP_OKAY;
4425 }
4426 
4427 /** replaces multiple occurrences of a variable by a single coefficient */
4428 static
4430  SCIP* scip, /**< SCIP data structure */
4431  SCIP_CONS* cons /**< linear constraint */
4432  )
4433 {
4434  SCIP_CONSDATA* consdata;
4435  SCIP_VAR* var;
4436  SCIP_Real valsum;
4437  int v;
4438 
4439  assert(scip != NULL);
4440  assert(cons != NULL);
4441 
4442  consdata = SCIPconsGetData(cons);
4443  assert(consdata != NULL);
4444 
4445  if( consdata->merged )
4446  return SCIP_OKAY;
4447 
4448  /* sort the constraint */
4449  SCIP_CALL( consdataSort(scip, consdata) );
4450 
4451  /* go backwards through the constraint looking for multiple occurrences of the same variable;
4452  * backward direction is necessary, since delCoefPos() modifies the given position and
4453  * the subsequent ones
4454  */
4455  v = consdata->nvars-1;
4456  while( v >= 1 )
4457  {
4458  var = consdata->vars[v];
4459  if( consdata->vars[v-1] == var )
4460  {
4461  valsum = consdata->vals[v];
4462  do
4463  {
4464  SCIP_CALL( delCoefPos(scip, cons, v) );
4465  --v;
4466  valsum += consdata->vals[v];
4467  }
4468  while( v >= 1 && consdata->vars[v-1] == var );
4469 
4470  /* modify the last existing occurrence of the variable */
4471  assert(consdata->vars[v] == var);
4472  if( SCIPisZero(scip, valsum) )
4473  {
4474  SCIP_CALL( delCoefPos(scip, cons, v) );
4475 
4476  /* if the variable defining the maximal activity delta was removed from the constraint, the maximal activity
4477  * delta needs to be recalculated on the next real propagation
4478  */
4479  if( consdata->maxactdeltavar == var )
4480  {
4481  consdata->maxactdelta = SCIP_INVALID;
4482  consdata->maxactdeltavar = NULL;
4483  }
4484  }
4485  else
4486  {
4487  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4488  }
4489  }
4490  --v;
4491  }
4492 
4493  consdata->merged = TRUE;
4494 
4495  return SCIP_OKAY;
4496 }
4497 
4498 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4499 static
4501  SCIP* scip, /**< SCIP data structure */
4502  SCIP_CONS* cons, /**< linear constraint */
4503  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4504  * information is not needed; in this case, we apply all fixings
4505  * instead of stopping after the first infeasible one */
4506  )
4507 {
4508  SCIP_CONSDATA* consdata;
4509  SCIP_VAR* var;
4510  SCIP_VAR** aggrvars;
4511  SCIP_Real val;
4512  SCIP_Real* aggrscalars;
4513  SCIP_Real fixedval;
4514  SCIP_Real aggrconst;
4515  int v;
4516  int naggrvars;
4517  int i;
4518 
4519  assert(scip != NULL);
4520  assert(cons != NULL);
4521 
4522  if( infeasible != NULL )
4523  *infeasible = FALSE;
4524 
4525  consdata = SCIPconsGetData(cons);
4526  assert(consdata != NULL);
4527 
4528  if( !consdata->removedfixings )
4529  {
4530  SCIP_Real lhssubtrahend;
4531  SCIP_Real rhssubtrahend;
4532 
4533  lhssubtrahend = 0.0;
4534  rhssubtrahend = 0.0;
4535 
4536  SCIPdebugMsg(scip, "applying fixings:\n");
4537  SCIPdebugPrintCons(scip, cons, NULL);
4538 
4539  v = 0;
4540  while( v < consdata->nvars )
4541  {
4542  var = consdata->vars[v];
4543  val = consdata->vals[v];
4544  assert(SCIPvarIsTransformed(var));
4545 
4546  switch( SCIPvarGetStatus(var) )
4547  {
4549  SCIPerrorMessage("original variable in transformed linear constraint\n");
4550  return SCIP_INVALIDDATA;
4551 
4552  case SCIP_VARSTATUS_LOOSE:
4553  case SCIP_VARSTATUS_COLUMN:
4554  ++v;
4555  break;
4556 
4557  case SCIP_VARSTATUS_FIXED:
4558  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4559  fixedval = SCIPvarGetLbGlobal(var);
4560  if( !SCIPisInfinity(scip, -consdata->lhs) )
4561  {
4562  if( SCIPisInfinity(scip, ABS(fixedval)) )
4563  {
4564  if( val * fixedval > 0.0 )
4565  {
4566  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4567  }
4568  else
4569  {
4570  if( infeasible != NULL )
4571  {
4572  /* if lhs gets infinity it means that the problem is infeasible */
4573  *infeasible = TRUE;
4574  return SCIP_OKAY;
4575  }
4576  else
4577  {
4578  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4579  }
4580  }
4581  }
4582  else
4583  lhssubtrahend += val * fixedval;
4584  }
4585  if( !SCIPisInfinity(scip, consdata->rhs) )
4586  {
4587  if( SCIPisInfinity(scip, ABS(fixedval)) )
4588  {
4589  if( val * fixedval > 0.0 )
4590  {
4591  if( infeasible != NULL )
4592  {
4593  /* if rhs gets -infinity it means that the problem is infeasible */
4594  *infeasible = TRUE;
4595  return SCIP_OKAY;
4596  }
4597  else
4598  {
4599  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4600  }
4601  }
4602  else
4603  {
4604  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4605  }
4606  }
4607  else
4608  rhssubtrahend += val * fixedval;
4609  }
4610  SCIP_CALL( delCoefPos(scip, cons, v) );
4611  break;
4612 
4614  {
4615  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4616  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4617  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4618 
4619  assert(activevar != NULL);
4620  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4621  assert(activevar != NULL);
4622 
4623  if( !SCIPisZero(scip, activescalar) )
4624  {
4625  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4626  }
4627 
4628  if( !SCIPisZero(scip, activeconstant) )
4629  {
4630  if( !SCIPisInfinity(scip, -consdata->lhs) )
4631  lhssubtrahend += activeconstant;
4632  if( !SCIPisInfinity(scip, consdata->rhs) )
4633  rhssubtrahend += activeconstant;
4634  }
4635 
4636  SCIP_CALL( delCoefPos(scip, cons, v) );
4637  break;
4638  }
4641  naggrvars = SCIPvarGetMultaggrNVars(var);
4642  aggrvars = SCIPvarGetMultaggrVars(var);
4643  aggrscalars = SCIPvarGetMultaggrScalars(var);
4644  for( i = 0; i < naggrvars; ++i )
4645  {
4646  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4647  }
4648  aggrconst = SCIPvarGetMultaggrConstant(var);
4649 
4650  if( !SCIPisInfinity(scip, -consdata->lhs) )
4651  lhssubtrahend += val * aggrconst;
4652  if( !SCIPisInfinity(scip, consdata->rhs) )
4653  rhssubtrahend += val * aggrconst;
4654 
4655  SCIP_CALL( delCoefPos(scip, cons, v) );
4656  break;
4657 
4659  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4660  aggrconst = SCIPvarGetNegationConstant(var);
4661 
4662  if( !SCIPisInfinity(scip, -consdata->lhs) )
4663  lhssubtrahend += val * aggrconst;
4664  if( !SCIPisInfinity(scip, consdata->rhs) )
4665  rhssubtrahend += val * aggrconst;
4666 
4667  SCIP_CALL( delCoefPos(scip, cons, v) );
4668  break;
4669 
4670  default:
4671  SCIPerrorMessage("unknown variable status\n");
4672  SCIPABORT();
4673  return SCIP_INVALIDDATA; /*lint !e527*/
4674  }
4675  }
4676 
4677  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4678  {
4679  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4680  * causing wrong fixings of other variables --> better use a real zero here;
4681  * for small numbers, polishing the difference might lead to wrong results -->
4682  * better use the exact difference in this case
4683  */
4684  if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4685  {
4686  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4687  }
4688  else
4689  {
4690  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4691  }
4692  }
4693  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4694  {
4695 
4696  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4697  * causing wrong fixings of other variables --> better use a real zero here;
4698  * for small numbers, polishing the difference might lead to wrong results -->
4699  * better use the exact difference in this case
4700  */
4701  if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4702  {
4703  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4704  }
4705  else
4706  {
4707  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4708  }
4709  }
4710 
4711  consdata->removedfixings = TRUE;
4712 
4713  SCIPdebugMsg(scip, "after fixings:\n");
4714  SCIPdebugPrintCons(scip, cons, NULL);
4715 
4716  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4717  * to clean up the constraint
4718  */
4719  SCIP_CALL( mergeMultiples(scip, cons) );
4720 
4721  SCIPdebugMsg(scip, "after merging:\n");
4722  SCIPdebugPrintCons(scip, cons, NULL);
4723  }
4724  assert(consdata->removedfixings);
4725 
4726 #ifndef NDEBUG
4727  /* check, if all fixings are applied */
4728  for( v = 0; v < consdata->nvars; ++v )
4729  assert(SCIPvarIsActive(consdata->vars[v]));
4730 #endif
4731 
4732  return SCIP_OKAY;
4733 }
4734 
4735 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4736  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4737  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4738  * conflict detecting constraint by using NULL as inferred variable
4739  */
4740 static
4742  SCIP* scip, /**< SCIP data structure */
4743  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4744  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4745  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4746  int inferpos, /**< position of the inferred variable in the vars array */
4747  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4748  )
4749 {
4750  SCIP_CONSDATA* consdata;
4751  SCIP_VAR** vars;
4752  SCIP_Real* vals;
4753  int nvars;
4754  int i;
4755 
4756  assert(scip != NULL);
4757  assert(cons != NULL);
4759  consdata = SCIPconsGetData(cons);
4760 
4761  assert(consdata != NULL);
4762 
4763  vars = consdata->vars;
4764  vals = consdata->vals;
4765  nvars = consdata->nvars;
4766 
4767  assert(vars != NULL || nvars == 0);
4768  assert(vals != NULL || nvars == 0);
4769 
4770  assert(-1 <= inferpos && inferpos < nvars);
4771  assert((infervar == NULL) == (inferpos == -1));
4772  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4773 
4774  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4775  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4776  * - if the right hand side is the reason, the minimal residual activity is responsible
4777  * - if the left hand side is the reason, the maximal residual activity is responsible
4778  */
4779 
4780  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4781  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4782  {
4783  SCIP_Real minresactivity;
4784  SCIP_Real maxresactivity;
4785  SCIP_Bool minisrelax;
4786  SCIP_Bool maxisrelax;
4787  SCIP_Bool isminsettoinfinity;
4788  SCIP_Bool ismaxsettoinfinity;
4789 
4790  minresactivity = -SCIPinfinity(scip);
4791  maxresactivity = SCIPinfinity(scip);
4792 
4793  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4794  if( infervar != NULL )
4795  {
4796  assert(vals != NULL); /* for flexelint */
4797  if( reasonisrhs )
4798  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4799  &minisrelax, NULL, &isminsettoinfinity, NULL);
4800  else
4801  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4802  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4803  }
4804  else
4805  {
4806  if( reasonisrhs )
4807  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4808  &minisrelax, NULL, &isminsettoinfinity, NULL);
4809  else
4810  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4811  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4812  }
4813 
4814  /* we can only do something clever, if the residual activity is finite and not relaxed */
4815  if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4816  {
4817  SCIP_Real rescap;
4818  SCIP_Bool resactisinf;
4819 
4820  resactisinf = FALSE;
4821 
4822  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4823  * than its inferred bound
4824  */
4825  if( infervar != NULL )
4826  {
4827  assert(vals != NULL); /* for flexelint */
4828 
4829  if( reasonisrhs )
4830  {
4831  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4832  {
4833  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4834  if( SCIPisInfinity(scip, -minresactivity) )
4835  resactisinf = TRUE;
4836  }
4837  rescap = consdata->rhs - minresactivity;
4838  }
4839  else
4840  {
4841  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4842  {
4843  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4844  if( SCIPisInfinity(scip, maxresactivity) )
4845  resactisinf = TRUE;
4846  }
4847  rescap = consdata->lhs - maxresactivity;
4848  }
4849 
4850  if( reasonisrhs == (vals[inferpos] > 0.0) )
4851  rescap -= vals[inferpos] * (SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) + 1.0);
4852  else
4853  rescap -= vals[inferpos] * (SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) - 1.0);
4854  }
4855  else
4856  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4857 
4858  if( !resactisinf )
4859  {
4860  /* now add bounds as reasons until the residual capacity is exceeded */
4861  for( i = 0; i < nvars; ++i )
4862  {
4863  assert( vars != NULL && vals != NULL ); /* for lint */
4864 
4865  /* zero coefficients and the infered variable can be ignored */
4866  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4867  continue;
4868 
4869  /* check if the residual capacity is exceeded */
4870  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4871  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4872  break;
4873 
4874  /* update the residual capacity due to the local bound of this variable */
4875  if( reasonisrhs == (vals[i] > 0.0) )
4876  {
4877  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4878  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4879  rescap -= vals[i] * (SCIPgetVarLbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4880  }
4881  else
4882  {
4883  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4884  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4885  rescap -= vals[i] * (SCIPgetVarUbAtIndex(scip, vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4886  }
4887  }
4888  return SCIP_OKAY;
4889  }
4890  }
4891  }
4892 
4893  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4894  for( i = 0; i < nvars; ++i )
4895  {
4896  assert(vars != NULL); /* for flexelint */
4897  assert(vals != NULL); /* for flexelint */
4898 
4899  /* zero coefficients and the infered variable can be ignored */
4900  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4901  continue;
4902 
4903  if( reasonisrhs == (vals[i] > 0.0) )
4904  {
4905  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4906  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4907  }
4908  else
4909  {
4910  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
4911  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4912  }
4913  }
4914 
4915  return SCIP_OKAY;
4916 }
4917 
4918 /** for each variable in the linear ranged row constraint, except the inferred variable, adds the bounds of all fixed
4919  * variables to the conflict analysis' candidate store; the conflict analysis can be initialized
4920  * with the linear constraint being the conflict detecting constraint by using NULL as inferred variable
4921  */
4922 static
4924  SCIP* scip, /**< SCIP data structure */
4925  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4926  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4927  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4928  int inferpos /**< position of the inferred variable in the vars array, or -1 */
4929  )
4930 {
4931  SCIP_CONSDATA* consdata;
4932  SCIP_VAR** vars;
4933  int nvars;
4934  int v;
4935 
4936  assert(scip != NULL);
4937  assert(cons != NULL);
4938 
4939  consdata = SCIPconsGetData(cons);
4940  assert(consdata != NULL);
4941  vars = consdata->vars;
4942  nvars = consdata->nvars;
4943  assert(vars != NULL || nvars == 0);
4944  assert(-1 <= inferpos && inferpos < nvars);
4945  assert((infervar == NULL) == (inferpos == -1));
4946  assert(inferpos == -1 || vars != NULL);
4947  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4948 
4949  /* collect all fixed variables */
4950  for( v = nvars - 1; v >= 0; --v )
4951  {
4952  assert(vars != NULL); /* for flexelint */
4953 
4954  /* need to add old bounds before propagation of inferrence variable */
4955  if( vars[v] == infervar )
4956  {
4957  assert(vars[v] != NULL);
4958 
4959  if( !SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetLbGlobal(vars[v])) )
4960  {
4961  /* @todo get boundchange index before this last boundchange and correct the index */
4962  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
4963  }
4964 
4965  if( !SCIPisEQ(scip, SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPvarGetUbGlobal(vars[v])) )
4966  {
4967  /* @todo get boundchange index before this last boundchange and correct the index */
4968  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
4969  }
4970 
4971  continue;
4972  }
4973 
4974  /* check for fixed variables */
4975  if( SCIPisEQ(scip, SCIPgetVarLbAtIndex(scip, vars[v], bdchgidx, FALSE), SCIPgetVarUbAtIndex(scip, vars[v], bdchgidx, FALSE)) )
4976  {
4977  /* add all bounds of fixed variables which lead to the boundchange of the given inference variable */
4978  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], bdchgidx) );
4979  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], bdchgidx) );
4980  }
4981  }
4982 
4983  return SCIP_OKAY;
4984 }
4985 
4986 /** add reasoning variables to conflict candidate queue which led to the conflict */
4987 static
4989  SCIP* scip, /**< SCIP data structure */
4990  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
4991  int nvars, /**< number of variables reasoning the infeasibility */
4992  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
4993  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
4994  )
4995 {
4996  int v;
4997 
4998  assert(scip != NULL);
4999 
5000  /* collect all variables for which the local bounds differ from their global bounds */
5001  for( v = nvars - 1; v >= 0; --v )
5002  {
5003  assert(vars != NULL);
5004 
5005  /* check for local bound changes variables */
5006  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(vars[v]), SCIPvarGetLbGlobal(vars[v])) )
5007  {
5008  /* add conflict bound */
5009  SCIP_CALL( SCIPaddConflictLb(scip, vars[v], 0) );
5010  }
5011 
5012  if( !SCIPisEQ(scip, SCIPvarGetUbLocal(vars[v]), SCIPvarGetUbGlobal(vars[v])) )
5013  {
5014  SCIP_CALL( SCIPaddConflictUb(scip, vars[v], 0) );
5015  }
5016  }
5017 
5018  if( var != NULL )
5019  {
5020  if( bound < SCIPvarGetLbLocal(var) )
5021  {
5022  SCIP_CALL( SCIPaddConflictLb(scip, var, 0) );
5023  }
5024 
5025  if( bound > SCIPvarGetUbLocal(var) )
5026  {
5027  SCIP_CALL( SCIPaddConflictUb(scip, var, 0) );
5028  }
5029  }
5030 
5031  return SCIP_OKAY;
5032 }
5033 
5034 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
5035  * propagation rule (see propagateCons()):
5036  * (1) activity residuals of all other variables tighten bounds of single variable
5037  */
5038 static
5040  SCIP* scip, /**< SCIP data structure */
5041  SCIP_CONS* cons, /**< constraint that inferred the bound change */
5042  SCIP_VAR* infervar, /**< variable that was deduced */
5043  INFERINFO inferinfo, /**< inference information */
5044  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
5045  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
5046  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
5047  )
5048 {
5049  SCIP_CONSDATA* consdata;
5050  SCIP_VAR** vars;
5051 #ifndef NDEBUG
5052  SCIP_Real* vals;
5053 #endif
5054  int nvars;
5055  int inferpos;
5057  assert(scip != NULL);
5058  assert(cons != NULL);
5059  assert(result != NULL);
5060 
5061  consdata = SCIPconsGetData(cons);
5062  assert(consdata != NULL);
5063  vars = consdata->vars;
5064  nvars = consdata->nvars;
5065 #ifndef NDEBUG
5066  vals = consdata->vals;
5067  assert(vars != NULL);
5068  assert(vals != NULL);
5069 #endif
5070 
5071  /* get the position of the inferred variable in the vars array */
5072  inferpos = inferInfoGetPos(inferinfo);
5073  if( inferpos >= nvars || vars[inferpos] != infervar )
5074  {
5075  /* find inference variable in constraint */
5076  /**@todo use a binary search here; the variables can be sorted by variable index */
5077  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
5078  {}
5079  }
5080  assert(inferpos < nvars);
5081  assert(vars[inferpos] == infervar);
5082  assert(!SCIPisZero(scip, vals[inferpos]));
5083 
5084  switch( inferInfoGetProprule(inferinfo) )
5085  {
5086  case PROPRULE_1_RHS:
5087  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5088  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5089  * domain in order to not exceed the right hand side of the inequality
5090  */
5091  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
5092  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
5093  *result = SCIP_SUCCESS;
5094  break;
5095 
5096  case PROPRULE_1_LHS:
5097  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
5098  * constraint (only taking the other variables into account) didn't leave enough space for a larger
5099  * domain in order to not fall below the left hand side of the inequality
5100  */
5101  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
5102  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
5103  *result = SCIP_SUCCESS;
5104  break;
5105 
5106  case PROPRULE_1_RANGEDROW:
5107  /* the bound of the variable was tightened, because some variables were already fixed and the leftover only allow
5108  * the given inference variable to their bounds in this given ranged row
5109  */
5110 
5111  /* check that we really have a ranged row here */
5112  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5113  SCIP_CALL( addConflictFixedVars(scip, cons, infervar, bdchgidx, inferpos) );
5114  *result = SCIP_SUCCESS;
5115  break;
5116 
5117  case PROPRULE_INVALID:
5118  default:
5119  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
5120  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
5121  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
5122  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
5123  SCIPinfoMessage(scip, NULL, ";\n");
5124  return SCIP_INVALIDDATA;
5125  }
5126 
5127  return SCIP_OKAY;
5128 }
5129 
5130 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
5131 static
5133  SCIP* scip, /**< SCIP data structure */
5134  SCIP_CONS* cons, /**< conflict detecting constraint */
5135  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
5136  )
5137 {
5138  /* conflict analysis can only be applied in solving stage and if it is turned on */
5140  return SCIP_OKAY;
5141 
5142  /* initialize conflict analysis */
5144 
5145  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
5146  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
5147 
5148  /* analyze the conflict */
5150 
5151  return SCIP_OKAY;
5152 }
5153 
5154 /** check if there is any hope of tightening some bounds */
5155 static
5157  SCIP* scip, /**< SCIP data structure */
5158  SCIP_CONS* cons /**< linear constraint */
5159  )
5160 {
5161  SCIP_CONSDATA* consdata;
5162  int infcountmin;
5163  int infcountmax;
5164 
5165  consdata = SCIPconsGetData(cons);
5166  assert(consdata != NULL);
5167 
5168  infcountmin = consdata->minactivityneginf
5169  + consdata->minactivityposinf
5170  + consdata->minactivityneghuge
5171  + consdata->minactivityposhuge;
5172  infcountmax = consdata->maxactivityneginf
5173  + consdata->maxactivityposinf
5174  + consdata->maxactivityneghuge
5175  + consdata->maxactivityposhuge;
5176 
5177  if( infcountmin > 1 && infcountmax > 1 )
5178  return FALSE;
5179 
5180  return TRUE;
5181 }
5182 
5183 /** tighten upper bound */
5184 static
5186  SCIP* scip, /**< SCIP data structure */
5187  SCIP_CONS* cons, /**< linear constraint */
5188  int pos, /**< variable position */
5189  PROPRULE proprule, /**< propagation rule that deduced the value */
5190  SCIP_Real newub, /**< new upper bound */
5191  SCIP_Real oldub, /**< old upper bound */
5192  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5193  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5194  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5195  )
5196 {
5197  SCIP_CONSDATA* consdata;
5198  SCIP_VAR* var;
5199  SCIP_Real lb;
5200  SCIP_Bool infeasible;
5201  SCIP_Bool tightened;
5203  assert(cons != NULL);
5204  assert(!SCIPisInfinity(scip, newub));
5205 
5206  consdata = SCIPconsGetData(cons);
5207  assert(consdata != NULL);
5208  var = consdata->vars[pos];
5209  assert(var != NULL);
5210 
5211  lb = SCIPvarGetLbLocal(var);
5212  newub = SCIPadjustedVarUb(scip, var, newub);
5213 
5214  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
5215  {
5216  SCIP_VARTYPE vartype;
5217 
5218  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5219  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newub);
5220 
5221  vartype = SCIPvarGetType(var);
5222 
5223  /* tighten upper bound */
5224  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5225 
5226  if( infeasible )
5227  {
5228  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5229  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5230 
5231  /* analyze conflict */
5232  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5233 
5234  *cutoff = TRUE;
5235  }
5236  else if( tightened )
5237  {
5238  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
5239  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5240  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
5241 
5242  (*nchgbds)++;
5243 
5244  /* if variable type was changed we might be able to upgrade the constraint */
5245  if( vartype != SCIPvarGetType(var) )
5246  consdata->upgradetried = FALSE;
5247  }
5248  }
5249  return SCIP_OKAY;
5250 }
5251 
5252 /** tighten lower bound */
5253 static
5255  SCIP* scip, /**< SCIP data structure */
5256  SCIP_CONS* cons, /**< linear constraint */
5257  int pos, /**< variable position */
5258  PROPRULE proprule, /**< propagation rule that deduced the value */
5259  SCIP_Real newlb, /**< new lower bound */
5260  SCIP_Real oldlb, /**< old lower bound */
5261  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5262  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5263  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5264  )
5265 {
5266  SCIP_CONSDATA* consdata;
5267  SCIP_VAR* var;
5268  SCIP_Real ub;
5269  SCIP_Bool infeasible;
5270  SCIP_Bool tightened;
5272  assert(cons != NULL);
5273  assert(!SCIPisInfinity(scip, newlb));
5274 
5275  consdata = SCIPconsGetData(cons);
5276  assert(consdata != NULL);
5277  var = consdata->vars[pos];
5278  assert(var != NULL);
5279 
5280  ub = SCIPvarGetUbLocal(var);
5281  newlb = SCIPadjustedVarLb(scip, var, newlb);
5282 
5283  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
5284  {
5285  SCIP_VARTYPE vartype;
5286 
5287  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5288  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newlb);
5289 
5290  vartype = SCIPvarGetType(var);
5291 
5292  /* tighten lower bound */
5293  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
5294 
5295  if( infeasible )
5296  {
5297  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5298  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5299 
5300  /* analyze conflict */
5301  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5302 
5303  *cutoff = TRUE;
5304  }
5305  else if( tightened )
5306  {
5307  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
5308  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5309  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
5310 
5311  (*nchgbds)++;
5312 
5313  /* if variable type was changed we might be able to upgrade the constraint */
5314  if( vartype != SCIPvarGetType(var) )
5315  consdata->upgradetried = FALSE;
5316  }
5317  }
5318  return SCIP_OKAY;
5319 }
5320 
5321 /** tightens bounds of a single variable due to activity bounds (easy case) */
5322 static
5324  SCIP* scip, /**< SCIP data structure */
5325  SCIP_CONS* cons, /**< linear constraint */
5326  int pos, /**< position of the variable in the vars array */
5327  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5328  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5329  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
5330  )
5331 {
5332  SCIP_CONSDATA* consdata;
5333  SCIP_VAR* var;
5334  SCIP_Real val;
5335  SCIP_Real lb;
5336  SCIP_Real ub;
5337  SCIP_Real lhs;
5338  SCIP_Real rhs;
5339 
5340  assert(scip != NULL);
5341  assert(cons != NULL);
5342  assert(cutoff != NULL);
5343  assert(nchgbds != NULL);
5344 
5345  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5346  if( SCIPconsIsModifiable(cons) )
5347  return SCIP_OKAY;
5348 
5349  consdata = SCIPconsGetData(cons);
5350  assert(consdata != NULL);
5351  assert(0 <= pos && pos < consdata->nvars);
5352 
5353  *cutoff = FALSE;
5354 
5355  var = consdata->vars[pos];
5356  assert(var != NULL);
5357 
5358  /* we cannot tighten bounds of multi-aggregated variables */
5360  return SCIP_OKAY;
5361 
5362  val = consdata->vals[pos];
5363  lhs = consdata->lhs;
5364  rhs = consdata->rhs;
5365  assert(!SCIPisZero(scip, val));
5366  assert(!SCIPisInfinity(scip, lhs));
5367  assert(!SCIPisInfinity(scip, -rhs));
5368 
5369  lb = SCIPvarGetLbLocal(var);
5370  ub = SCIPvarGetUbLocal(var);
5371  assert(SCIPisLE(scip, lb, ub));
5372 
5373  /* recompute activities if needed */
5374  if( !consdata->validactivities )
5375  consdataCalcActivities(scip, consdata);
5376  assert(consdata->validactivities);
5377  if( !consdata->validminact )
5378  consdataRecomputeMinactivity(scip, consdata);
5379  assert(consdata->validminact);
5380  if( !consdata->validmaxact )
5381  consdataRecomputeMaxactivity(scip, consdata);
5382  assert(consdata->validmaxact);
5383 
5384  if( val > 0.0 )
5385  {
5386  /* check, if we can tighten the variable's upper bound */
5387  if( !SCIPisInfinity(scip, rhs) )
5388  {
5389  SCIP_Real slack;
5390  SCIP_Real alpha;
5391 
5392  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5393  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5394  {
5395  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5396  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5397 
5398  *cutoff = TRUE;
5399  return SCIP_OKAY;
5400  }
5401 
5402  slack = rhs - consdata->minactivity;
5403 
5404  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5405  * it to zero
5406  */
5407  if( !SCIPisPositive(scip, slack) )
5408  slack = 0.0;
5409 
5410  alpha = val * (ub - lb);
5411  assert(!SCIPisNegative(scip, alpha));
5412 
5413  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5414  {
5415  SCIP_Real newub;
5416 
5417  /* compute new upper bound */
5418  newub = lb + (slack / val);
5419 
5420  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
5421 
5422  if( *cutoff )
5423  {
5424  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5425  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5426 
5427  return SCIP_OKAY;
5428  }
5429 
5430  /* collect the new upper bound which is needed for the lower bound computation */
5431  ub = SCIPvarGetUbLocal(var);
5432  }
5433  }
5434 
5435  /* check, if we can tighten the variable's lower bound */
5436  if( !SCIPisInfinity(scip, -lhs) )
5437  {
5438  SCIP_Real slack;
5439  SCIP_Real alpha;
5440 
5441  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5442  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5443  {
5444  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5445  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5446 
5447  *cutoff = TRUE;
5448  return SCIP_OKAY;
5449  }
5450 
5451  slack = consdata->maxactivity - lhs;
5452 
5453  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5454  * it to zero
5455  */
5456  if( !SCIPisPositive(scip, slack) )
5457  slack = 0.0;
5458 
5459  alpha = val * (ub - lb);
5460  assert(!SCIPisNegative(scip, alpha));
5461 
5462  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5463  {
5464  SCIP_Real newlb;
5465 
5466  /* compute new lower bound */
5467  newlb = ub - (slack / val);
5468 
5469  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
5470 
5471  if( *cutoff )
5472  {
5473  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5474  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5475 
5476  return SCIP_OKAY;
5477  }
5478  }
5479  }
5480  }
5481  else
5482  {
5483  /* check, if we can tighten the variable's lower bound */
5484  if( !SCIPisInfinity(scip, rhs) )
5485  {
5486  SCIP_Real slack;
5487  SCIP_Real alpha;
5488 
5489  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
5490  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
5491  {
5492  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
5493  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
5494 
5495  *cutoff = TRUE;
5496  return SCIP_OKAY;
5497  }
5498 
5499  slack = rhs - consdata->minactivity;
5500 
5501  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
5502  * it to zero
5503  */
5504  if( !SCIPisPositive(scip, slack) )
5505  slack = 0.0;
5506 
5507  alpha = val * (lb - ub);
5508  assert(!SCIPisNegative(scip, alpha));
5509 
5510  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
5511  {
5512  SCIP_Real newlb;
5513 
5514  /* compute new lower bound */
5515  newlb = ub + slack / val;
5516 
5517  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
5518 
5519  if( *cutoff )
5520  {
5521  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5522  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5523 
5524  return SCIP_OKAY;
5525  }
5526  /* collect the new lower bound which is needed for the upper bound computation */
5527  lb = SCIPvarGetLbLocal(var);
5528  }
5529  }
5530 
5531  /* check, if we can tighten the variable's upper bound */
5532  if( !SCIPisInfinity(scip, -lhs) )
5533  {
5534  SCIP_Real slack;
5535  SCIP_Real alpha;
5536 
5537  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
5538  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
5539  {
5540  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
5541  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
5542 
5543  *cutoff = TRUE;
5544  return SCIP_OKAY;
5545  }
5546 
5547  slack = consdata->maxactivity - lhs;
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 * (lb - ub);
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_LHS, 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  }
5576  }
5577 
5578  return SCIP_OKAY;
5579 }
5580 
5581 /** analyzes conflicting bounds on given ranged row constraint, and adds conflict constraint to problem */
5582 static
5584  SCIP* scip, /**< SCIP data structure */
5585  SCIP_CONS* cons, /**< conflict detecting constraint */
5586  SCIP_VAR** vars, /**< variables reasoning the infeasibility */
5587  int nvars, /**< number of variables reasoning the infeasibility */
5588  SCIP_VAR* var, /**< variable which was tried to fix/tighten, or NULL */
5589  SCIP_Real bound /**< bound of variable which was tried to apply, or SCIP_INVALID */
5590  )
5591 {
5592 #ifndef NDEBUG
5593  SCIP_CONSDATA* consdata;
5594 
5595  assert(scip != NULL);
5596  assert(cons != NULL);
5597 
5598  consdata = SCIPconsGetData(cons);
5599  assert(consdata != NULL);
5600  assert(!SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->rhs));
5601 #endif
5602 
5603  /* conflict analysis can only be applied in solving stage and if it is turned on */
5605  return SCIP_OKAY;
5606 
5607  /* initialize conflict analysis */
5609 
5610  /* add the conflicting fixed variables of this ranged row constraint to conflict candidate queue */
5611  SCIP_CALL( addConflictFixedVars(scip, cons, NULL, NULL, -1) );
5612 
5613  /* add reasoning variables to conflict candidate queue which led to the conflict */
5614  SCIP_CALL( addConflictReasonVars(scip, vars, nvars, var, bound) );
5615 
5616  /* analyze the conflict */
5617  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
5618 
5619  return SCIP_OKAY;
5620 }
5621 
5622 /** propagate ranged rows
5623  *
5624  * Check ranged rows for possible solutions, possibly detect infeasibility, fix variables due to having only one possible
5625  * solution, tighten bounds if having only two possible solutions or add constraints which propagate a subset of
5626  * variables better.
5627  *
5628  * Example:
5629  * c1: 12 x1 + 9 x2 - x3 = 0 with x1, x2 free and 1 <= x3 <= 2
5630  *
5631  * x3 needs to be a multiple of 3, so the instance is infeasible.
5632  *
5633  * Example:
5634  * c1: 12 x1 + 9 x2 - x3 = 1 with x1, x2 free and 1 <= x3 <= 2
5635  *
5636  * The only posible value for x3 is 2, so the variable will be fixed.
5637  *
5638  * @todo add holes if possible
5639  */
5640 static
5642  SCIP* scip, /**< SCIP data structure */
5643  SCIP_CONS* cons, /**< linear constraint */
5644  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5645  int* nfixedvars, /**< pointer to count number of fixed variables */
5646  int* nchgbds, /**< pointer to count the number of bound changes */
5647  int* naddconss /**< pointer to count number of added constraints */
5648  )
5649 {
5650  SCIP_CONSHDLRDATA* conshdlrdata;
5651  SCIP_CONSHDLR* conshdlr;
5652  SCIP_CONSDATA* consdata;
5653  SCIP_VAR** infcheckvars;
5654  SCIP_Real* infcheckvals;
5655  SCIP_Real minactinfvars;
5656  SCIP_Real maxactinfvars;
5657  SCIP_Real lb;
5659  SCIP_Real feastol;
5660  SCIP_Real fixedact;
5661  SCIP_Real lhs;
5662  SCIP_Real rhs;
5663  SCIP_Real absminbincoef;
5664  SCIP_Longint gcd;
5665  SCIP_Longint gcdtmp;
5666  SCIP_Bool minactinfvarsinvalid;
5667  SCIP_Bool maxactinfvarsinvalid;
5668  SCIP_Bool possiblegcd;
5669  SCIP_Bool gcdisone;
5670  SCIP_Bool addartconss;
5671  int ninfcheckvars;
5672  int nunfixedvars;
5673  int nfixedconsvars;
5674  int ncontvars;
5675  int pos;
5676  int v;
5677 
5678  assert(scip != NULL);
5679  assert(cons != NULL);
5680  assert(cutoff != NULL);
5681  assert(nfixedvars != NULL);
5682  assert(nchgbds != NULL);
5683  assert(naddconss != NULL);
5684 
5685  /* modifiable constraint can be changed so we do not have all necessary information */
5686  if( SCIPconsIsModifiable(cons) )
5687  return SCIP_OKAY;
5688 
5689  consdata = SCIPconsGetData(cons);
5690  assert(consdata != NULL);
5691 
5692  /* we already did full ranged row propagation */
5693  if( consdata->rangedrowpropagated == 2 )
5694  return SCIP_OKAY;
5695 
5696  /* at least three variables are needed */
5697  if( consdata->nvars < 3 )
5698  return SCIP_OKAY;
5699 
5700  /* do nothing on normal inequalities */
5701  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
5702  return SCIP_OKAY;
5703 
5704  /* get constraint handler data */
5705  conshdlr = SCIPconsGetHdlr(cons);
5706  assert(conshdlr != NULL);
5707  conshdlrdata = SCIPconshdlrGetData(conshdlr);
5708  assert(conshdlrdata != NULL);
5709 
5710  addartconss = conshdlrdata->rangedrowartcons && SCIPgetDepth(scip) < 1 && !SCIPinProbing(scip) && !SCIPinRepropagation(scip);
5711 
5712  /* we may add artificial constraints */
5713  if( addartconss )
5714  consdata->rangedrowpropagated = 2;
5715  /* we are not allowed to add artificial constraints during propagation; if nothing changed on this constraint since
5716  * the last rangedrowpropagation, we can stop; otherwise, we mark this constraint to be rangedrowpropagated without
5717  * artificial constraints
5718  */
5719  else
5720  {
5721  if( consdata->rangedrowpropagated > 0 )
5722  return SCIP_OKAY;
5723 
5724  consdata->rangedrowpropagated = 1;
5725  }
5726  fixedact = 0;
5727  nfixedconsvars = 0;
5728  /* calculate fixed activity and number of fixed variables */
5729  for( v = consdata->nvars - 1; v >= 0; --v )
5730  {
5731  /* all zero coefficients should be eliminated */
5732  assert(!SCIPisZero(scip, consdata->vals[v]));
5733 
5734  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5735  {
5736  fixedact += SCIPvarGetLbLocal(consdata->vars[v]) * consdata->vals[v];
5737  ++nfixedconsvars;
5738  }
5739  }
5740 
5741  /* do not work with huge fixed activities */
5742  if( SCIPisHugeValue(scip, REALABS(fixedact)) )
5743  return SCIP_OKAY;
5744 
5745  /* compute lhs and rhs for unfixed variables only and get number of unfixed variables */
5746  assert(!SCIPisInfinity(scip, -fixedact) && !SCIPisInfinity(scip, fixedact));
5747  lhs = consdata->lhs - fixedact;
5748  rhs = consdata->rhs - fixedact;
5749  nunfixedvars = consdata->nvars - nfixedconsvars;
5750 
5751  /* allocate temporary memory for variables and coefficients which may lead to infeasibility */
5752  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvars, nunfixedvars) );
5753  SCIP_CALL( SCIPallocBufferArray(scip, &infcheckvals, nunfixedvars) );
5754 
5755  absminbincoef = SCIP_REAL_MAX;
5756  ncontvars = 0;
5757  gcdisone = TRUE;
5758  possiblegcd = TRUE;
5759 
5760  /* we now partition all unfixed variables in two groups:
5761  *
5762  * the first one contains all integral variable with integral
5763  * coefficient so that all variables in this group will have a gcd greater than 1, this group will be implicitly
5764  * given
5765  *
5766  * the second group will contain all left unfixed variables and will be saved as infcheckvars with corresponding
5767  * coefficients as infcheckvals, the order of these variables should be the same as in the consdata object
5768  */
5769 
5770  /* find first integral variables with integral coefficient greater than 1, thereby collecting all other unfixed
5771  * variables
5772  */
5773  ninfcheckvars = 0;
5774  v = -1;
5775  pos = -1;
5776  do
5777  {
5778  ++v;
5779 
5780  /* partition the variables, do not change the order of collection, because it might be used later on */
5781  while( v < consdata->nvars && (SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5782  !SCIPisIntegral(scip, consdata->vals[v]) || SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0)) )
5783  {
5784  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5785  {
5786  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5787  {
5788  ++ncontvars;
5789  }
5790  else if( SCIPvarIsBinary(consdata->vars[v]) )
5791  {
5792  SCIP_Real absval;
5793 
5794  absval = REALABS(consdata->vals[v]);
5795 
5796  if( absminbincoef > absval )
5797  absminbincoef = absval;
5798  }
5799 
5800  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5801  possiblegcd = FALSE;
5802  infcheckvars[ninfcheckvars] = consdata->vars[v];
5803  infcheckvals[ninfcheckvars] = consdata->vals[v];
5804  ++ninfcheckvars;
5805 
5806  if( pos == -1 )
5807  pos = v;
5808  }
5809  ++v;
5810  }
5811  }
5812  while( v < consdata->nvars && SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) );
5813 
5814  /* if the first group of variables is empty, we stop */
5815  /* @todo try to propagate/split up a constraint of the form:
5816  * x_1 + ... + x_m + a_1*y_1 + ... + a_n*y_n = k + c,
5817  * 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]
5818  */
5819  if( v == consdata->nvars )
5820  goto TERMINATE;
5821 
5822  /* we need at least two non-continuous variables */
5823  if( ncontvars + 2 > nunfixedvars )
5824  goto TERMINATE;
5825 
5826  assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])));
5827  assert(SCIPisIntegral(scip, consdata->vals[v]) && SCIPvarGetType(consdata->vars[v]) != SCIP_VARTYPE_CONTINUOUS && REALABS(consdata->vals[v]) > 1.5);
5828 
5829  feastol = SCIPfeastol(scip);
5830 
5831  gcd = (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol);
5832  assert(gcd >= 2);
5833 
5834  /* go on to partition the variables, do not change the order of collection, because it might be used later on;
5835  * calculate gcd over the first part of variables */
5836  for( ; v < consdata->nvars; ++v )
5837  {
5838  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
5839  continue;
5840 
5841  if( SCIPvarIsBinary(consdata->vars[v]) )
5842  {
5843  SCIP_Real absval;
5844 
5845  absval = REALABS(consdata->vals[v]);
5846 
5847  if( absminbincoef > absval )
5848  absminbincoef = absval;
5849  }
5850 
5851  if( !SCIPisIntegral(scip, consdata->vals[v]) || SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS ||
5852  SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0) )
5853  {
5854  if( SCIPvarGetType(consdata->vars[v]) == SCIP_VARTYPE_CONTINUOUS )
5855  ++ncontvars;
5856 
5857  gcdisone = gcdisone && SCIPisEQ(scip, REALABS(consdata->vals[v]), 1.0);
5858  possiblegcd = FALSE;
5859  infcheckvars[ninfcheckvars] = consdata->vars[v];
5860  infcheckvals[ninfcheckvars] = consdata->vals[v];
5861 
5862  ++ninfcheckvars;
5863 
5864  if( pos == -1 )
5865  pos = v;
5866  }
5867  else
5868  {
5869  assert(REALABS(consdata->vals[v]) > 1.5);
5870 
5871  gcdtmp = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(consdata->vals[v]) + feastol));
5872  assert(gcdtmp >= 1);
5873 
5874  if( gcdtmp == 1 )
5875  {
5876  infcheckvars[ninfcheckvars] = consdata->vars[v];
5877  infcheckvals[ninfcheckvars] = consdata->vals[v];
5878 
5879  ++ninfcheckvars;
5880 
5881  if( pos == -1 )
5882  pos = v;
5883  }
5884  else
5885  gcd = gcdtmp;
5886  }
5887  }
5888  assert(gcd >= 2);
5889 
5890  /* it should not happen that all variables are of integral type and have a gcd >= 2, this should be done by
5891  * normalizeCons() */
5892  if( ninfcheckvars == 0 )
5893  goto TERMINATE;
5894 
5895  assert(pos >= 0);
5896 
5897  minactinfvarsinvalid = FALSE;
5898  maxactinfvarsinvalid = FALSE;
5899  maxactinfvars = 0.0;
5900  minactinfvars = 0.0;
5901 
5902  /* calculate activities over all infcheckvars */
5903  for( v = ninfcheckvars - 1; v >= 0; --v )
5904  {
5905  lb = SCIPvarGetLbLocal(infcheckvars[v]);
5906  ub = SCIPvarGetUbLocal(infcheckvars[v]);
5907 
5908  if( SCIPisInfinity(scip, -lb) )
5909  {
5910  if( infcheckvals[v] < 0.0 )
5911  maxactinfvarsinvalid = TRUE;
5912  else
5913  minactinfvarsinvalid = TRUE;
5914  }
5915  else
5916  {
5917  if( infcheckvals[v] < 0.0 )
5918  maxactinfvars += infcheckvals[v] * lb;
5919  else
5920  minactinfvars += infcheckvals[v] * lb;
5921  }
5922 
5923  if( SCIPisInfinity(scip, ub) )
5924  {
5925  if( infcheckvals[v] > 0.0 )
5926  maxactinfvarsinvalid = TRUE;
5927  else
5928  minactinfvarsinvalid = TRUE;
5929  }
5930  else
5931  {
5932  if( infcheckvals[v] > 0.0 )
5933  maxactinfvars += infcheckvals[v] * ub;
5934  else
5935  minactinfvars += infcheckvals[v] * ub;
5936  }
5937 
5938  /* better abort on to big values */
5939  if( SCIPisHugeValue(scip, -minactinfvars) )
5940  minactinfvarsinvalid = TRUE;
5941  if( SCIPisHugeValue(scip, maxactinfvars) )
5942  maxactinfvarsinvalid = TRUE;
5943 
5944  if( minactinfvarsinvalid || maxactinfvarsinvalid )
5945  goto TERMINATE;
5946  }
5947  assert(!minactinfvarsinvalid && !maxactinfvarsinvalid);
5948 
5949  SCIPdebugMsg(scip, "minactinfvarsinvalid = %u, minactinfvars = %g, maxactinfvarsinvalid = %u, maxactinfvars = %g, gcd = %lld, ninfcheckvars = %d, ncontvars = %d\n",
5950  minactinfvarsinvalid, minactinfvars, maxactinfvarsinvalid, maxactinfvars, gcd, ninfcheckvars, ncontvars);
5951 
5952  /* @todo maybe we took the wrong variables as infcheckvars we could try to exchange integer variables */
5953  /* @todo if minactinfvarsinvalid or maxactinfvarsinvalid are true, try to exchange both partitions to maybe get valid
5954  * activities */
5955  /* @todo calculate minactivity and maxactivity for all non-intcheckvars, and use this for better bounding,
5956  * !!!note!!!
5957  * that therefore the conflict variables in addConflictFixedVars() need to be extended by all variables which
5958  * are not at their global bound
5959  */
5960 
5961  /* check if between left hand side and right hand side exist a feasible point, if not the constraint leads to
5962  * infeasibility */
5963  if( !SCIPisIntegral(scip, (lhs - maxactinfvars) / gcd) &&
5964  SCIPisGT(scip, SCIPceil(scip, (lhs - maxactinfvars) / gcd) * gcd, rhs - minactinfvars) )
5965  {
5966  SCIPdebugMsg(scip, "no feasible value exist, constraint <%s> lead to infeasibility", SCIPconsGetName(cons));
5967  SCIPdebugPrintCons(scip, cons, NULL);
5968 
5969  /* start conflict analysis */
5970  /* @todo improve conflict analysis by adding relaxed bounds */
5971  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
5972 
5973  *cutoff = TRUE;
5974  }
5975  else if( ncontvars == 0 )
5976  {
5977  SCIP_Longint gcdinfvars = -1;
5978 
5979  /* check for gcd over all infcheckvars */
5980  if( possiblegcd )
5981  {
5982  v = ninfcheckvars - 1;
5983  gcdinfvars = (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol);
5984  assert(gcdinfvars >= 2);
5985 
5986  for( ; v >= 0 && gcdinfvars >= 2; --v )
5987  {
5988  gcdinfvars = SCIPcalcGreComDiv(gcdinfvars, (SCIP_Longint)(REALABS(infcheckvals[v]) + feastol));
5989  }
5990  }
5991  else if( gcdisone )
5992  gcdinfvars = 1;
5993 
5994  SCIPdebugMsg(scip, "gcdinfvars =%lld, possiblegcd = %u\n", gcdinfvars, possiblegcd);
5995 
5996  /* compute solutions for this ranged row, if all variables are of integral type with integral coefficients */
5997  if( gcdinfvars >= 1 )
5998  {
5999  SCIP_Real value;
6000  SCIP_Real value2;
6001  SCIP_Real minvalue = SCIP_INVALID;
6002  SCIP_Real maxvalue = SCIP_INVALID;
6003  int nsols = 0;
6004 
6005  value = SCIPceil(scip, minactinfvars - SCIPfeastol(scip));
6006 
6007  /* check how many possible solutions exist */
6008  while( SCIPisLE(scip, value, maxactinfvars) )
6009  {
6010  value2 = value + gcd * (SCIPceil(scip, (lhs - value) / gcd));
6011 
6012  if( SCIPisGE(scip, value2, lhs) && SCIPisLE(scip, value2, rhs) )
6013  {
6014  ++nsols;
6015 
6016  /* early termination if we found more than two solutions */
6017  if( nsols == 3 )
6018  break;
6019 
6020  if( minvalue == SCIP_INVALID ) /*lint !e777*/
6021  minvalue = value;
6022 
6023  maxvalue = value;
6024  }
6025  value += gcdinfvars;
6026  }
6027  assert(nsols < 2 || minvalue <= maxvalue);
6028 
6029  /* determine last possible solution for better bounding */
6030  if( nsols == 3 )
6031  {
6032 #ifndef NDEBUG
6033  SCIP_Real secondsolval = maxvalue;
6034 #endif
6035  value = SCIPfloor(scip, maxactinfvars + SCIPfeastol(scip));
6036 
6037  /* check how many possible solutions exist */
6038  while( SCIPisGE(scip, value, minactinfvars) )
6039  {
6040  value2 = value + gcd * (SCIPfloor(scip, (rhs - value) / gcd));
6041 
6042  if( SCIPisGE(scip, value2, lhs) && SCIPisLE(scip, value2, rhs) )
6043  {
6044  maxvalue = value;
6045  assert(maxvalue > minvalue);
6046  break;
6047  }
6048  value -= gcdinfvars;
6049  }
6050  assert(maxvalue > secondsolval);
6051  }
6052 
6053  SCIPdebugMsg(scip, "here nsols %s %d, minsolvalue = %g, maxsolvalue = %g, ninfcheckvars = %d, nunfixedvars = %d\n",
6054  nsols > 2 ? ">=" : "=", nsols, minvalue, maxvalue, ninfcheckvars, nunfixedvars);
6055 
6056  /* no possible solution found */
6057  if( nsols == 0 )
6058  {
6059  SCIPdebugMsg(scip, "gcdinfvars = %lld, gcd = %lld, correctedlhs = %g, correctedrhs = %g\n",
6060  gcdinfvars, gcd, lhs, rhs);
6061  SCIPdebugMsg(scip, "no solution found; constraint <%s> lead to infeasibility\n", SCIPconsGetName(cons));
6062  SCIPdebugPrintCons(scip, cons, NULL);
6063 
6064  /* start conflict analysis */
6065  /* @todo improve conflict analysis by adding relaxed bounds */
6066  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6067 
6068  *cutoff = TRUE;
6069  }
6070  /* if only one solution exist we can extract a new constraint or fix variables */
6071  else if( nsols == 1 )
6072  {
6073  assert(minvalue == maxvalue); /*lint !e777*/
6074 
6075  /* we can fix the only variable in our second set of variables */
6076  if( ninfcheckvars == 1 )
6077  {
6078  SCIP_Bool fixed;
6079 
6080  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6081 
6082  SCIPdebugMsg(scip, "fixing single variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6083  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]),
6084  SCIPvarGetUbLocal(infcheckvars[0]), maxvalue/infcheckvals[0]);
6085 
6086  /* fix variable to only possible value */
6087  SCIP_CALL( SCIPinferVarFixCons(scip, infcheckvars[0], maxvalue/infcheckvals[0], cons,
6088  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &fixed) );
6089 
6090  if( *cutoff )
6091  {
6092  /* start conflict analysis */
6093  /* @todo improve conflict analysis by adding relaxed bounds */
6094  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6095  }
6096 
6097  if( fixed )
6098  ++(*nfixedvars);
6099  }
6100  else
6101  {
6102  /* check for exactly one unfixed variable which is not part of the infcheckvars */
6103  if( ninfcheckvars == nunfixedvars - 1 )
6104  {
6105  SCIP_Real bound;
6106  SCIP_Bool foundvar = FALSE;
6107  SCIP_Bool fixed;
6108  int w = 0;
6109 
6110  assert(ninfcheckvars > 0);
6111 
6112  /* find variable which is not an infcheckvar and fix it */
6113  for( v = 0; v < consdata->nvars - 1; ++v )
6114  {
6115  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6116  {
6117  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6118  {
6119 #ifndef NDEBUG
6120  int v2 = v + 1;
6121  int w2 = w;
6122 
6123  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6124 
6125  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6126  {
6127  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6128  continue;
6129 
6130  assert(consdata->vars[v2] == infcheckvars[w2]);
6131  ++w2;
6132  }
6133  assert(w2 == ninfcheckvars);
6134 #endif
6135  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6136 
6137  foundvar = TRUE;
6138 
6139  if( consdata->vals[v] < 0 )
6140  {
6141  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6142  }
6143  else
6144  {
6145  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6146  }
6147 
6148  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6149  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6150  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6151 
6152  /* fix variable to only possible value */
6153  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6154  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6155 
6156  if( *cutoff )
6157  {
6158  /* start conflict analysis */
6159  /* @todo improve conflict analysis by adding relaxed bounds */
6160  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6161  consdata->vars[v], bound) );
6162  }
6163 
6164  if( fixed )
6165  ++(*nfixedvars);
6166 
6167  break;
6168  }
6169 
6170  ++w;
6171  }
6172  }
6173 
6174  /* maybe last variable was the not infcheckvar */
6175  if( !foundvar )
6176  {
6177  assert(v == consdata->nvars - 1);
6178  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6179 
6180  if( consdata->vals[v] < 0 )
6181  {
6182  bound = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6183  }
6184  else
6185  {
6186  bound = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6187  }
6188 
6189  SCIPdebugMsg(scip, "fixing variable <%s> with bounds [%.15g,%.15g] to %.15g\n",
6190  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]),
6191  SCIPvarGetUbLocal(consdata->vars[v]), bound);
6192 
6193  /* fix variable to only possible value */
6194  SCIP_CALL( SCIPinferVarFixCons(scip, consdata->vars[v], bound, cons,
6195  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &fixed) );
6196 
6197  if( *cutoff )
6198  {
6199  /* start conflict analysis */
6200  /* @todo improve conflict analysis by adding relaxed bounds */
6201  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6202  consdata->vars[v], bound) );
6203  }
6204 
6205  if( fixed )
6206  ++(*nfixedvars);
6207  }
6208  }
6209  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6210  {
6211  /* aggregation possible if we have two variables, but this will be done later on */
6212  SCIP_CONS* newcons;
6213  char name[SCIP_MAXSTRLEN];
6214 
6215  /* create, add, and release new artificial constraint */
6216  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6217  ++conshdlrdata->naddconss;
6218 
6219  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6220 
6221  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals,
6222  maxvalue, maxvalue, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6223  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6224 
6225  SCIPdebugPrintCons(scip, newcons, NULL);
6226 
6227  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6228 
6229  ++(*naddconss);
6230  }
6231  }
6232  }
6233  /* at least two solutions */
6234  else
6235  {
6236  /* @todo if we found more then one solution, we may reduced domains due to dualpresolving? */
6237 
6238  /* only one variable in the second set, so we can bound this variables */
6239  if( ninfcheckvars == 1 )
6240  {
6241  SCIP_Bool tightened;
6242  SCIP_Real newlb;
6243  SCIP_Real newub;
6244 
6245  assert(SCIPisEQ(scip, (SCIP_Real)gcdinfvars, REALABS(infcheckvals[0])));
6246 
6247  if( infcheckvals[0] < 0 )
6248  {
6249  newlb = maxvalue/infcheckvals[0];
6250  newub = minvalue/infcheckvals[0];
6251  }
6252  else
6253  {
6254  newlb = minvalue/infcheckvals[0];
6255  newub = maxvalue/infcheckvals[0];
6256  }
6257  assert(newlb < newub);
6258 
6259  if( newlb > SCIPvarGetLbLocal(infcheckvars[0]) )
6260  {
6261  /* update lower bound of variable */
6262  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6263  SCIPvarGetName(infcheckvars[0]), SCIPvarGetLbLocal(infcheckvars[0]), newlb);
6264 
6265  /* tighten variable lower bound to minimal possible value */
6266  SCIP_CALL( SCIPinferVarLbCons(scip, infcheckvars[0], newlb, cons,
6267  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6268 
6269  if( *cutoff )
6270  {
6271  /* start conflict analysis */
6272  /* @todo improve conflict analysis by adding relaxed bounds */
6273  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6274  }
6275 
6276  if( tightened )
6277  ++(*nchgbds);
6278  }
6279 
6280  if( newub < SCIPvarGetUbLocal(infcheckvars[0]) )
6281  {
6282  /* update upper bound of variable */
6283  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6284  SCIPvarGetName(infcheckvars[0]), SCIPvarGetUbLocal(infcheckvars[0]), newub);
6285 
6286  /* tighten variable upper bound to maximal possible value */
6287  SCIP_CALL( SCIPinferVarUbCons(scip, infcheckvars[0], newub, cons,
6288  getInferInt(PROPRULE_1_RANGEDROW, pos), TRUE, cutoff, &tightened) );
6289 
6290  if( *cutoff )
6291  {
6292  /* start conflict analysis */
6293  /* @todo improve conflict analysis by adding relaxed bounds */
6294  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, NULL, SCIP_INVALID) );
6295  }
6296 
6297  if( tightened )
6298  ++(*nchgbds);
6299  }
6300  }
6301  /* check if we have only one not infcheckvars, if so we can tighten this variable */
6302  else if( ninfcheckvars == nunfixedvars - 1 )
6303  {
6304  SCIP_Bool foundvar = FALSE;
6305  SCIP_Bool tightened;
6306  SCIP_Real newlb;
6307  SCIP_Real newub;
6308  int w = 0;
6309 
6310  assert(ninfcheckvars > 0);
6311  assert(minvalue < maxvalue);
6312 
6313  /* find variable which is not an infcheckvar and fix it */
6314  for( v = 0; v < consdata->nvars - 1; ++v )
6315  {
6316  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6317  {
6318  if( w >= ninfcheckvars || consdata->vars[v] != infcheckvars[w] )
6319  {
6320 #ifndef NDEBUG
6321  int v2 = v + 1;
6322  int w2 = w;
6323 
6324  assert((nfixedconsvars == 0) ? (consdata->nvars - v - 1 == ninfcheckvars - w) : TRUE);
6325 
6326  for( ; v2 < consdata->nvars && w2 < ninfcheckvars; ++v2 )
6327  {
6328  if( SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v2]), SCIPvarGetUbLocal(consdata->vars[v2])) )
6329  continue;
6330 
6331  assert(consdata->vars[v2] == infcheckvars[w2]);
6332  ++w2;
6333  }
6334  assert(w2 == ninfcheckvars);
6335 #endif
6336 
6337  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6338  foundvar = TRUE;
6339 
6340  if( consdata->vals[v] < 0 )
6341  {
6342  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6343  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6344  }
6345  else
6346  {
6347  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6348  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6349  }
6350  assert(SCIPisLE(scip, newlb, newub));
6351 
6352  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6353  {
6354  /* update lower bound of variable */
6355  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6356  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6357 
6358  /* tighten variable lower bound to minimal possible value */
6359  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6360  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6361 
6362  if( *cutoff )
6363  {
6364  /* start conflict analysis */
6365  /* @todo improve conflict analysis by adding relaxed bounds */
6366  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6367  consdata->vars[v], newlb) );
6368  }
6369 
6370  if( tightened )
6371  ++(*nchgbds);
6372  }
6373 
6374  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6375  {
6376  /* update upper bound of variable */
6377  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6378  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6379 
6380  /* tighten variable upper bound to maximal possible value */
6381  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6382  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6383 
6384  if( *cutoff )
6385  {
6386  /* start conflict analysis */
6387  /* @todo improve conflict analysis by adding relaxed bounds */
6388  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars,
6389  consdata->vars[v], newub) );
6390  }
6391 
6392  if( tightened )
6393  ++(*nchgbds);
6394  }
6395 
6396  break;
6397  }
6398 
6399  ++w;
6400  }
6401  }
6402 
6403  /* maybe last variable was the not infcheckvar */
6404  if( !foundvar )
6405  {
6406  assert(v == consdata->nvars - 1);
6407  assert(SCIPisEQ(scip, (SCIP_Real)gcd, REALABS(consdata->vals[v])));
6408 
6409  if( consdata->vals[v] < 0 )
6410  {
6411  newlb = SCIPfloor(scip, (rhs - minvalue) / consdata->vals[v]);
6412  newub = SCIPfloor(scip, (lhs - maxvalue) / consdata->vals[v]);
6413  }
6414  else
6415  {
6416  newlb = SCIPceil(scip, (lhs - maxvalue) / consdata->vals[v]);
6417  newub = SCIPceil(scip, (rhs - minvalue) / consdata->vals[v]);
6418  }
6419  assert(SCIPisLE(scip, newlb, newub));
6420 
6421  if( newlb > SCIPvarGetLbLocal(consdata->vars[v]) )
6422  {
6423  /* update lower bound of variable */
6424  SCIPdebugMsg(scip, "tightening lower bound of variable <%s> from %g to %g\n",
6425  SCIPvarGetName(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v]), newlb);
6426 
6427  /* tighten variable lower bound to minimal possible value */
6428  SCIP_CALL( SCIPinferVarLbCons(scip, consdata->vars[v], newlb, cons,
6429  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6430 
6431  if( *cutoff )
6432  {
6433  /* start conflict analysis */
6434  /* @todo improve conflict analysis by adding relaxed bounds */
6435  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newlb) );
6436  }
6437 
6438  if( tightened )
6439  ++(*nchgbds);
6440  }
6441 
6442  if( newub < SCIPvarGetUbLocal(consdata->vars[v]) )
6443  {
6444  /* update upper bound of variable */
6445  SCIPdebugMsg(scip, "tightening upper bound of variable <%s> from %g to %g\n",
6446  SCIPvarGetName(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v]), newub);
6447 
6448  /* tighten variable upper bound to maximal possible value */
6449  SCIP_CALL( SCIPinferVarUbCons(scip, consdata->vars[v], newub, cons,
6450  getInferInt(PROPRULE_1_RANGEDROW, v), TRUE, cutoff, &tightened) );
6451 
6452  if( *cutoff )
6453  {
6454  /* start conflict analysis */
6455  /* @todo improve conflict analysis by adding relaxed bounds */
6456  SCIP_CALL( analyzeConflictRangedRow(scip, cons, infcheckvars, ninfcheckvars, consdata->vars[v], newub) );
6457  }
6458 
6459  if( tightened )
6460  ++(*nchgbds);
6461  }
6462  }
6463  }
6464  /* at least two solutions and more than one variable, so we add a new constraint which bounds the feasible
6465  * region for our infcheckvars, if possible
6466  */
6467  else if( addartconss && (SCIPisGT(scip, minvalue, minactinfvars) || SCIPisLT(scip, maxvalue, maxactinfvars)) )
6468  {
6469  SCIP_CONS* newcons;
6470  char name[SCIP_MAXSTRLEN];
6471  SCIP_Real newlhs;
6472  SCIP_Real newrhs;
6473 
6474  assert(maxvalue > minvalue);
6475 
6476  if( SCIPisGT(scip, minvalue, minactinfvars) )
6477  newlhs = minvalue;
6478  else
6479  newlhs = -SCIPinfinity(scip);
6480 
6481  if( SCIPisLT(scip, maxvalue, maxactinfvars) )
6482  newrhs = maxvalue;
6483  else
6484  newrhs = SCIPinfinity(scip);
6485 
6486  if( !SCIPisInfinity(scip, -newlhs) || !SCIPisInfinity(scip, newrhs) )
6487  {
6488  /* create, add, and release new artificial constraint */
6489  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons1_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6490  ++conshdlrdata->naddconss;
6491 
6492  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6493 
6494  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6495  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6496  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6497 
6498  SCIPdebugPrintCons(scip, newcons, NULL);
6499  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6500 
6501  ++(*naddconss);
6502  }
6503  /* @todo maybe add constraint for all variables which are not infcheckvars, lhs should be minvalue, rhs
6504  * should be maxvalue */
6505  }
6506  }
6507  }
6508  }
6509  else if( addartconss && ncontvars < ninfcheckvars )
6510  {
6511  SCIP_Real maxact = 0.0;
6512  SCIP_Real minact = 0.0;
6513  int w = 0;
6514 
6515  /* compute activities of non-infcheckvars */
6516  for( v = 0; v < consdata->nvars; ++v )
6517  {
6518  if( w < ninfcheckvars && consdata->vars[v] == infcheckvars[w] )
6519  {
6520  ++w;
6521  continue;
6522  }
6523 
6524  if( !SCIPisEQ(scip, SCIPvarGetLbLocal(consdata->vars[v]), SCIPvarGetUbLocal(consdata->vars[v])) )
6525  {
6526  if( SCIPvarIsBinary(consdata->vars[v]) )
6527  {
6528  if( consdata->vals[v] > 0.0 )
6529  maxact += consdata->vals[v];
6530  else
6531  minact += consdata->vals[v];
6532  }
6533  else
6534  {
6535  SCIP_Real tmpval;
6536 
6537  assert(SCIPvarIsIntegral(consdata->vars[v]));
6538 
6539  if( consdata->vals[v] > 0.0 )
6540  {
6541  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6542 
6543  if( SCIPisHugeValue(scip, -tmpval) )
6544  break;
6545 
6546  minact += tmpval;
6547 
6548  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6549 
6550  if( SCIPisHugeValue(scip, tmpval) )
6551  break;
6552 
6553  maxact += tmpval;
6554  }
6555  else
6556  {
6557  tmpval = consdata->vals[v] * SCIPvarGetUbLocal(consdata->vars[v]);
6558 
6559  if( SCIPisHugeValue(scip, -tmpval) )
6560  break;
6561 
6562  minact += tmpval;
6563 
6564  tmpval = consdata->vals[v] * SCIPvarGetLbLocal(consdata->vars[v]);
6565 
6566  if( SCIPisHugeValue(scip, tmpval) )
6567  break;
6568 
6569  maxact += tmpval;
6570  }
6571  }
6572  }
6573  }
6574  if( v == consdata->nvars && !SCIPisHugeValue(scip, -minact) && !SCIPisHugeValue(scip, maxact) )
6575  {
6576  SCIP_CONS* newcons;
6577  char name[SCIP_MAXSTRLEN];
6578  SCIP_Real newlhs;
6579  SCIP_Real newrhs;
6580 
6581  assert(maxact > minact);
6582  assert(w == ninfcheckvars);
6583 
6584  newlhs = lhs - maxact;
6585  newrhs = rhs - minact;
6586  assert(newlhs < newrhs);
6587 
6588  /* create, add, and release new artificial constraint */
6589  (void)SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s_artcons2_%d", SCIPconsGetName(cons), conshdlrdata->naddconss);
6590  ++conshdlrdata->naddconss;
6591 
6592  SCIPdebugMsg(scip, "adding artificial constraint %s\n", name);
6593 
6594  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, name, ninfcheckvars, infcheckvars, infcheckvals, newlhs, newrhs,
6595  TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE) );
6596  SCIP_CALL( SCIPaddConsLocal(scip, newcons, NULL) );
6597 
6598  SCIPdebugPrintCons(scip, newcons, NULL);
6599  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
6600 
6601  ++(*naddconss);
6602  }
6603  }
6604 
6605  TERMINATE:
6606  SCIPfreeBufferArray(scip, &infcheckvals);
6607  SCIPfreeBufferArray(scip, &infcheckvars);
6608 
6609  return SCIP_OKAY;
6610 }
6611 
6612 /** tightens bounds of a single variable due to activity bounds */
6613 static
6615  SCIP* scip, /**< SCIP data structure */
6616  SCIP_CONS* cons, /**< linear constraint */
6617  int pos, /**< position of the variable in the vars array */
6618  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6619  int* nchgbds, /**< pointer to count the total number of tightened bounds */
6620  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
6621  )
6622 {
6623  SCIP_CONSDATA* consdata;
6624  SCIP_VAR* var;
6625  SCIP_Real val;
6626  SCIP_Real lb;
6627  SCIP_Real ub;
6628  SCIP_Real minresactivity;
6629  SCIP_Real maxresactivity;
6630  SCIP_Real lhs;
6632  SCIP_Bool infeasible;
6633  SCIP_Bool tightened;
6634  SCIP_Bool minisrelax;
6635  SCIP_Bool maxisrelax;
6636  SCIP_Bool isminsettoinfinity;
6637  SCIP_Bool ismaxsettoinfinity;
6638 
6639  assert(scip != NULL);
6640  assert(cons != NULL);
6641  assert(cutoff != NULL);
6642  assert(nchgbds != NULL);
6643 
6644  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6645  if( SCIPconsIsModifiable(cons) )
6646  return SCIP_OKAY;
6647 
6648  consdata = SCIPconsGetData(cons);
6649  assert(consdata != NULL);
6650  assert(0 <= pos && pos < consdata->nvars);
6651 
6652  *cutoff = FALSE;
6653 
6654  var = consdata->vars[pos];
6655 
6656  /* we cannot tighten bounds of multi-aggregated variables */
6658  return SCIP_OKAY;
6659 
6660  val = consdata->vals[pos];
6661  lhs = consdata->lhs;
6662  rhs = consdata->rhs;
6663  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
6664  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
6665  assert(var != NULL);
6666  assert(!SCIPisZero(scip, val));
6667  assert(!SCIPisInfinity(scip, lhs));
6668  assert(!SCIPisInfinity(scip, -rhs));
6669 
6670  lb = SCIPvarGetLbLocal(var);
6671  ub = SCIPvarGetUbLocal(var);
6672  assert(SCIPisLE(scip, lb, ub));
6673 
6674  if( val > 0.0 )
6675  {
6676  /* check, if we can tighten the variable's bounds */
6677  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6678  {
6679  SCIP_Real newub;
6680 
6681  newub = (rhs - minresactivity)/val;
6682 
6683  if( !SCIPisInfinity(scip, newub) &&
6684  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6685  {
6686  SCIP_Bool activityunreliable;
6687  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6688 
6689  /* check minresactivities for reliability */
6690  if( activityunreliable )
6691  {
6692  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6693  newub = (rhs - minresactivity)/val;
6694  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
6695  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
6696  && (!force || !SCIPisLT(scip, newub, ub)));
6697  }
6698 
6699  if( !activityunreliable )
6700  {
6701  /* tighten upper bound */
6702  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
6703  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6704  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6705  &infeasible, &tightened) );
6706  if( infeasible )
6707  {
6708  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6709  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6710 
6711  /* analyze conflict */
6712  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6713 
6714  *cutoff = TRUE;
6715  return SCIP_OKAY;
6716  }
6717  if( tightened )
6718  {
6719  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6720  assert(SCIPisFeasLE(scip, ub, newub));
6721  (*nchgbds)++;
6722 
6723  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6724  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6725  }
6726  }
6727  }
6728  }
6729 
6730  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6731  {
6732  SCIP_Real newlb;
6733 
6734  newlb = (lhs - maxresactivity)/val;
6735  if( !SCIPisInfinity(scip, -newlb) &&
6736  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6737  {
6738  /* check maxresactivities for reliability */
6739  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6740  {
6741  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6742  newlb = (lhs - maxresactivity)/val;
6743 
6744  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
6745  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6746  && (!force || !SCIPisGT(scip, newlb, lb))) )
6747  return SCIP_OKAY;
6748  }
6749 
6750  /* tighten lower bound */
6751  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6752  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6753  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6754  &infeasible, &tightened) );
6755  if( infeasible )
6756  {
6757  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6758  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6759 
6760  /* analyze conflict */
6761  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6762 
6763  *cutoff = TRUE;
6764  return SCIP_OKAY;
6765  }
6766  if( tightened )
6767  {
6768  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6769  assert(SCIPisFeasGE(scip, lb, newlb));
6770  (*nchgbds)++;
6771  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6772  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6773  }
6774  }
6775  }
6776  }
6777  else
6778  {
6779  /* check, if we can tighten the variable's bounds */
6780  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
6781  {
6782  SCIP_Real newlb;
6783 
6784  newlb = (rhs - minresactivity)/val;
6785  if( !SCIPisInfinity(scip, -newlb) &&
6786  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
6787  {
6788  SCIP_Bool activityunreliable;
6789  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
6790  /* check minresactivities for reliability */
6791  if( activityunreliable )
6792  {
6793  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
6794  newlb = (rhs - minresactivity)/val;
6795 
6796  activityunreliable = SCIPisInfinity(scip, -minresactivity)
6797  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
6798  && (!force || !SCIPisGT(scip, newlb, lb)));
6799  }
6800 
6801  if( !activityunreliable )
6802  {
6803  /* tighten lower bound */
6804  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
6805  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
6806  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
6807  &infeasible, &tightened) );
6808  if( infeasible )
6809  {
6810  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6811  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
6812 
6813  /* analyze conflict */
6814  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
6815 
6816  *cutoff = TRUE;
6817  return SCIP_OKAY;
6818  }
6819  if( tightened )
6820  {
6821  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6822  assert(SCIPisFeasGE(scip, lb, newlb));
6823  (*nchgbds)++;
6824  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6825  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6826  }
6827  }
6828  }
6829  }
6830 
6831  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
6832  {
6833  SCIP_Real newub;
6834 
6835  newub = (lhs - maxresactivity)/val;
6836  if( !SCIPisInfinity(scip, newub) &&
6837  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
6838  {
6839  /* check maxresactivities for reliability */
6840  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
6841  {
6842  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
6843  newub = (lhs - maxresactivity)/val;
6844 
6845  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
6846  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
6847  && (!force || !SCIPisLT(scip, newub, ub))) )
6848  return SCIP_OKAY;
6849  }
6850 
6851  /* tighten upper bound */
6852  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
6853  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
6854  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
6855  &infeasible, &tightened) );
6856  if( infeasible )
6857  {
6858  SCIPdebugMsg(scip, "linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
6859  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
6860 
6861  /* analyze conflict */
6862  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
6863 
6864  *cutoff = TRUE;
6865  return SCIP_OKAY;
6866  }
6867  if( tightened )
6868  {
6869  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
6870  assert(SCIPisFeasLE(scip, ub, newub));
6871  (*nchgbds)++;
6872  SCIPdebugMsg(scip, "linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
6873  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
6874  }
6875  }
6876  }
6877  }
6878 
6879  return SCIP_OKAY;
6880 }
6881 
6882 #define MAXTIGHTENROUNDS 10
6883 
6884 /** tightens bounds of variables in constraint due to activity bounds */
6885 static
6887  SCIP* scip, /**< SCIP data structure */
6888  SCIP_CONS* cons, /**< linear constraint */
6889  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
6890  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
6891  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
6892  int* nchgbds /**< pointer to count the total number of tightened bounds */
6893  )
6894 {
6895  SCIP_CONSDATA* consdata;
6896  unsigned int tightenmode;
6897  int nvars;
6898  int nrounds;
6899  int lastchange;
6900  int oldnchgbds;
6901 #ifndef SCIP_DEBUG
6902  int oldnchgbdstotal;
6903 #endif
6904  int v;
6905  SCIP_Bool force;
6906  SCIP_Bool easycase;
6907 
6908  assert(scip != NULL);
6909  assert(cons != NULL);
6910  assert(nchgbds != NULL);
6911  assert(cutoff != NULL);
6912 
6913  *cutoff = FALSE;
6914 
6915  /* we cannot tighten variables' bounds, if the constraint may be not complete */
6916  if( SCIPconsIsModifiable(cons) )
6917  return SCIP_OKAY;
6918 
6919  /* if a constraint was created after presolve, then it may hold fixed variables
6920  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
6921  * thus, ensure here again that variable fixings have been applied
6922  */
6923  SCIP_CALL( applyFixings(scip, cons, cutoff) );
6924  if( *cutoff )
6925  return SCIP_OKAY;
6926 
6927  /* check if constraint has any chances of tightening bounds */
6928  if( !canTightenBounds(scip, cons) )
6929  return SCIP_OKAY;
6930 
6931  consdata = SCIPconsGetData(cons);
6932  assert(consdata != NULL);
6933 
6934  nvars = consdata->nvars;
6935  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
6936 
6937  /* we are at the root node or during presolving */
6938  if( SCIPgetDepth(scip) < 1 )
6939  tightenmode = 2;
6940  else
6941  tightenmode = 1;
6942 
6943  /* stop if we already tightened the constraint and the tightening is not forced */
6944  if( !force && (consdata->boundstightened >= tightenmode) ) /*lint !e574*/
6945  return SCIP_OKAY;
6946 
6947  /* ensure that the variables are properly sorted */
6948  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
6949  {
6950  SCIP_CALL( consdataSort(scip, consdata) );
6951  assert(consdata->binvarssorted);
6952  }
6953 
6954  /* update maximal activity delta if necessary */
6955  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
6956  consdataRecomputeMaxActivityDelta(scip, consdata);
6957 
6958  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
6959  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
6960  checkMaxActivityDelta(scip, consdata);
6961 
6962  /* this may happen if all variables are fixed */
6963  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
6964  return SCIP_OKAY;
6965 
6966  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
6967  {
6968  SCIP_Real slack;
6969  SCIP_Real surplus;
6970  SCIP_Real minactivity;
6971  SCIP_Real maxactivity;
6972  SCIP_Bool minisrelax;
6973  SCIP_Bool maxisrelax;
6974 
6975  /* use maximal activity delta to skip propagation (cannot deduce anything) */
6976  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax);
6977  assert(!SCIPisInfinity(scip, minactivity));
6978  assert(!SCIPisInfinity(scip, -maxactivity));
6979 
6980  slack = (SCIPisInfinity(scip, consdata->rhs) || SCIPisInfinity(scip, -minactivity)) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
6981  surplus = (SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, maxactivity)) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
6982 
6983  /* check if the constraint will propagate */
6984  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
6985  return SCIP_OKAY;
6986  }
6987 
6988  /* check if we can use fast implementation for easy and numerically well behaved cases */
6989  easycase = SCIPisLT(scip, consdata->maxactdelta, maxeasyactivitydelta);
6990 
6991  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
6992  lastchange = -1;
6993  oldnchgbds = 0;
6994 
6995 #ifndef SCIP_DEBUG
6996  oldnchgbdstotal = *nchgbds;
6997 #endif
6998 
6999  for( nrounds = 0; (force || consdata->boundstightened < tightenmode) && nrounds < MAXTIGHTENROUNDS; ++nrounds ) /*lint !e574*/
7000  {
7001  /* mark the constraint to have the variables' bounds tightened */
7002  consdata->boundstightened = (unsigned int)tightenmode;
7003 
7004  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
7005  * sorting enables skipping variables
7006  */
7007  v = 0;
7008  while( v < nvars && v != lastchange && !(*cutoff) )
7009  {
7010  oldnchgbds = *nchgbds;
7011 
7012  assert(!sortvars || SCIPgetStage(scip) < SCIP_STAGE_SOLVING || consdata->binvarssorted);
7013 
7014  if( easycase )
7015  {
7016  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
7017  }
7018  else
7019  {
7020  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
7021  }
7022 
7023  /* if there was no progress, skip the rest of the binary variables */
7024  if( *nchgbds > oldnchgbds )
7025  {
7026  lastchange = v;
7027  ++v;
7028  }
7029  else if( consdata->binvarssorted && v < consdata->nbinvars - 1
7030  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
7031  v = consdata->nbinvars;
7032  else
7033  ++v;
7034  }
7035 
7036 #ifndef SCIP_DEBUG
7037  SCIPdebugMessage("linear constraint <%s> found %d bound changes in round %d\n", SCIPconsGetName(cons),
7038  *nchgbds - oldnchgbdstotal, nrounds);
7039  oldnchgbdstotal += oldnchgbds;
7040 #endif
7041  }
7042 
7043 #ifndef NDEBUG
7044  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
7045  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
7046 #endif
7047 
7048  return SCIP_OKAY;
7049 }
7050 
7051 /** checks linear constraint for feasibility of given solution or current solution */
7052 static
7054  SCIP* scip, /**< SCIP data structure */
7055  SCIP_CONS* cons, /**< linear constraint */
7056  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
7057  SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */
7058  SCIP_Bool checkrelmaxabs, /**< Should the violation for a constraint with side 0.0 be checked relative
7059  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
7060  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
7061  )
7062 {
7063  SCIP_CONSDATA* consdata;
7064  SCIP_Real activity;
7065 
7066  assert(scip != NULL);
7067  assert(cons != NULL);
7068  assert(violated != NULL);
7069 
7070  SCIPdebugMsg(scip, "checking linear constraint <%s>\n", SCIPconsGetName(cons));
7071  SCIPdebugPrintCons(scip, cons, NULL);
7072 
7073  consdata = SCIPconsGetData(cons);
7074  assert(consdata != NULL);
7075 
7076  *violated = FALSE;
7077 
7078  if( consdata->row != NULL )
7079  {
7080  if( !checklprows && SCIProwIsInLP(consdata->row) )
7081  return SCIP_OKAY;
7082  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
7083  activity = consdataComputePseudoActivity(scip, consdata);
7084  else
7085  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
7086  }
7087  else
7088  activity = consdataGetActivity(scip, consdata, sol);
7089 
7090  SCIPdebugMsg(scip, " consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
7091  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
7092  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
7093  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
7094 
7095  /* the activity of pseudo solutions may be invalid if it comprises positive and negative infinity contributions; we
7096  * return infeasible for safety
7097  */
7098  if( activity == SCIP_INVALID ) /*lint !e777*/
7099  {
7100  assert(sol == NULL);
7101  *violated = TRUE;
7102 
7103  /* reset constraint age since we are in enforcement */
7104  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7105  }
7106  else if( SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs) )
7107  {
7108  /* the "normal" check: one of the two sides is violated */
7109  if( !checkrelmaxabs )
7110  {
7111  *violated = TRUE;
7112 
7113  /* only reset constraint age if we are in enforcement */
7114  if( sol == NULL )
7115  {
7116  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7117  }
7118  }
7119  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
7120  * small compared to the absolute values occuring in the activity
7121  */
7122  else
7123  {
7124  SCIP_Real maxabs;
7125  SCIP_Real coef;
7126  SCIP_Real absval;
7127  SCIP_Real solval;
7128  int v;
7129 
7130  maxabs = 1.0;
7131 
7132  /* compute maximum absolute value */
7133  for( v = 0; v < consdata->nvars; ++v )
7134  {
7135  if( consdata->vals != NULL )
7136  {
7137  coef = consdata->vals[v];
7138  }
7139  else
7140  coef = 1.0;
7141 
7142  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
7143  absval = REALABS( coef * solval );
7144  maxabs = MAX( maxabs, absval );
7145  }
7146 
7147  /* regard left hand side, first */
7148  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
7149  {
7150  /* check whether violation is random noise */
7151  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
7152  {
7153  SCIPdebugMsg(scip, " lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7154  consdata->lhs - activity, maxabs);
7155  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
7156 
7157  /* only increase constraint age if we are in enforcement */
7158  if( sol == NULL )
7159  {
7160  SCIP_CALL( SCIPincConsAge(scip, cons) );
7161  }
7162  }
7163  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
7164  else if( SCIPisZero(scip, consdata->lhs) )
7165  {
7166  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
7167  {
7168  SCIPdebugMsg(scip, " lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7169  consdata->lhs - activity, maxabs);
7170  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
7171 
7172  /* only increase constraint age if we are in enforcement */
7173  if( sol == NULL )
7174  {
7175  SCIP_CALL( SCIPincConsAge(scip, cons) );
7176  }
7177  }
7178  else
7179  {
7180  *violated = TRUE;
7181 
7182  /* only reset constraint age if we are in enforcement */
7183  if( sol == NULL )
7184  {
7185  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7186  }
7187  }
7188  }
7189  else
7190  {
7191  *violated = TRUE;
7192 
7193  /* only reset constraint age if we are in enforcement */
7194  if( sol == NULL )
7195  {
7196  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7197  }
7198  }
7199  }
7200 
7201  /* now regard right hand side */
7202  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
7203  {
7204  /* check whether violation is random noise */
7205  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
7206  {
7207  SCIPdebugMsg(scip, " rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
7208  activity - consdata->rhs, maxabs);
7209  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
7210 
7211  /* only increase constraint age if we are in enforcement */
7212  if( sol == NULL )
7213  {
7214  SCIP_CALL( SCIPincConsAge(scip, cons) );
7215  }
7216  }
7217  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
7218  else if( SCIPisZero(scip, consdata->rhs) )
7219  {
7220  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
7221  {
7222  SCIPdebugMsg(scip, " rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
7223  activity - consdata->rhs, maxabs);
7224  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
7225 
7226  /* only increase constraint age if we are in enforcement */
7227  if( sol == NULL )
7228  {
7229  SCIP_CALL( SCIPincConsAge(scip, cons) );
7230  }
7231  }
7232  else
7233  {
7234  *violated = TRUE;
7235 
7236  /* only reset constraint age if we are in enforcement */
7237  if( sol == NULL )
7238  {
7239  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7240  }
7241  }
7242  }
7243  else
7244  {
7245  *violated = TRUE;
7246 
7247  /* only reset constraint age if we are in enforcement */
7248  if( sol == NULL )
7249  {
7250  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7251  }
7252  }
7253  }
7254  }
7255  }
7256  else
7257  {
7258  /* only increase constraint age if we are in enforcement */
7259  if( sol == NULL )
7260  {
7261  SCIP_CALL( SCIPincConsAge(scip, cons) );
7262  }
7263  }
7264 
7265  return SCIP_OKAY;
7266 }
7267 
7268 /** creates an LP row in a linear constraint data */
7269 static
7271  SCIP* scip, /**< SCIP data structure */
7272  SCIP_CONS* cons /**< linear constraint */
7273  )
7274 {
7275  SCIP_CONSDATA* consdata;
7276 
7277  assert(scip != NULL);
7278  assert(cons != NULL);
7279 
7280  consdata = SCIPconsGetData(cons);
7281  assert(consdata != NULL);
7282  assert(consdata->row == NULL);
7283 
7284  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, SCIPconsGetHdlr(cons), SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
7286 
7287  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
7288 
7289  return SCIP_OKAY;
7290 }
7291 
7292 /** adds linear constraint as cut to the LP */
7293 static
7295  SCIP* scip, /**< SCIP data structure */
7296  SCIP_CONS* cons, /**< linear constraint */
7297  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7298  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7299  )
7300 {
7301  SCIP_CONSDATA* consdata;
7302 
7303  assert(scip != NULL);
7304  assert(cons != NULL);
7305 
7306  consdata = SCIPconsGetData(cons);
7307  assert(consdata != NULL);
7308 
7309  if( consdata->row == NULL )
7310  {
7311  /* convert consdata object into LP row */
7312  SCIP_CALL( createRow(scip, cons) );
7313  }
7314  assert(consdata->row != NULL);
7315 
7316  /* insert LP row as cut */
7317  if( !SCIProwIsInLP(consdata->row) )
7318  {
7319  SCIPdebugMsg(scip, "adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
7320  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
7321  /* if presolving is turned off, the row might be trivial */
7322  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
7323  {
7324  SCIP_CALL( SCIPaddCut(scip, sol, consdata->row, FALSE, cutoff) );
7325  }
7326 #ifndef NDEBUG
7327  else
7328  {
7329  int pr;
7330  int cr;
7331  SCIP_CALL( SCIPgetIntParam(scip, "presolving/maxrounds", &pr) );
7332  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &cr) );
7333  assert( pr == 0 || cr == 0 );
7334  }
7335 #endif
7336  }
7337 
7338  return SCIP_OKAY;
7339 }
7340 
7341 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
7342 static
7344  SCIP* scip, /**< SCIP data structure */
7345  SCIP_CONS* cons, /**< linear constraint */
7346  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
7347  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
7348  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
7349  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
7350  * the ones with non-zero dual value? */
7351  int* ncuts, /**< pointer to add up the number of found cuts */
7352  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
7353  )
7354 {
7355  SCIP_CONSDATA* consdata;
7356  SCIP_Bool violated;
7357  int oldncuts;
7358 
7359  assert(scip != NULL);
7360  assert(conshdlrdata != NULL);
7361  assert(cons != NULL);
7362  assert(cutoff != NULL);
7363 
7364  consdata = SCIPconsGetData(cons);
7365  assert(ncuts != NULL);
7366  assert(consdata != NULL);
7367 
7368  oldncuts = *ncuts;
7369  *cutoff = FALSE;
7370 
7371  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
7372 
7373  if( violated )
7374  {
7375  /* insert LP row as cut */
7376  SCIP_CALL( addRelaxation(scip, cons, sol, cutoff) );
7377  (*ncuts)++;
7378  }
7379  else if( !SCIPconsIsModifiable(cons) && separatecards )
7380  {
7381  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
7382  if( !separateall && sol == NULL )
7383  {
7384  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
7385  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
7386  {
7387  SCIP_Real dualsol;
7388 
7389  dualsol = SCIProwGetDualsol(consdata->row);
7390  if( SCIPisFeasNegative(scip, dualsol) )
7391  {
7392  if( !SCIPisInfinity(scip, consdata->rhs) )
7393  {
7394  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7395  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7396  }
7397  }
7398  else if( SCIPisFeasPositive(scip, dualsol) )
7399  {
7400  if( !SCIPisInfinity(scip, -consdata->lhs) )
7401  {
7402  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7403  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7404  }
7405  }
7406  }
7407  }
7408  else
7409  {
7410  if( !SCIPisInfinity(scip, consdata->rhs) )
7411  {
7412  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7413  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
7414  }
7415  if( !SCIPisInfinity(scip, -consdata->lhs) )
7416  {
7417  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
7418  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
7419  }
7420  }
7421  }
7422 
7423  if( *ncuts > oldncuts )
7424  {
7425  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7426  }
7427 
7428  return SCIP_OKAY;
7429 }
7430 
7431 /** propagation method for linear constraints */
7432 static
7434  SCIP* scip, /**< SCIP data structure */
7435  SCIP_CONS* cons, /**< linear constraint */
7436  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
7437  SCIP_Bool rangedrowpropagation,/**< should ranged row propagation be performed? */
7438  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7439  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
7440  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
7441  int* nchgbds /**< pointer to count the total number of tightened bounds */
7442  )
7443 {
7444  SCIP_CONSDATA* consdata;
7445  SCIP_Real minactivity;
7446  SCIP_Real maxactivity;
7447  SCIP_Bool minactisrelax;
7448  SCIP_Bool maxactisrelax;
7449 
7450  assert(scip != NULL);
7451  assert(cons != NULL);
7452  assert(cutoff != NULL);
7453  assert(nchgbds != NULL);
7454 
7455  /*SCIPdebugMsg(scip, "propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
7456 
7457  consdata = SCIPconsGetData(cons);
7458  assert(consdata != NULL);
7459 
7460  *cutoff = FALSE;
7461 
7462  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
7463  if( !SCIPconsIsModifiable(cons) )
7464  {
7465  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
7466  if( !SCIPinRepropagation(scip) )
7467  {
7468  SCIP_CALL( SCIPincConsAge(scip, cons) );
7469  }
7470 
7471  /* tighten the variable's bounds */
7472  if( tightenbounds )
7473  {
7474  int oldnchgbds;
7475 
7476  oldnchgbds = *nchgbds;
7477 
7478  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7479 
7480  if( *nchgbds > oldnchgbds )
7481  {
7482  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7483  }
7484  }
7485 
7486  /* propagate ranged rows */
7487  if( rangedrowpropagation && tightenbounds && !(*cutoff) )
7488  {
7489  int nfixedvars;
7490  int naddconss;
7491  int oldnchgbds;
7492 
7493  nfixedvars = 0;
7494  naddconss = 0;
7495  SCIPdebug( oldnchgbds = *nchgbds; )
7496 
7497  SCIP_CALL( rangedRowPropagation(scip, cons, cutoff, &nfixedvars, nchgbds, &naddconss) );
7498 
7499  if( *cutoff )
7500  {
7501  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible\n", SCIPconsGetName(cons));
7502  }
7503  else
7504  {
7505  SCIPdebugMsg(scip, "linear constraint <%s> found %d bound changes and %d fixings\n", SCIPconsGetName(cons), *nchgbds - oldnchgbds, nfixedvars);
7506  }
7507 
7508  if( nfixedvars > 0 )
7509  *nchgbds += 2*nfixedvars;
7510  }
7511 
7512  /* check constraint for infeasibility and redundancy */
7513  if( !(*cutoff) )
7514  {
7515  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7516 
7517  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
7518  {
7519  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7520  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7521 
7522  /* analyze conflict */
7523  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
7524 
7525  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7526  *cutoff = TRUE;
7527  }
7528  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
7529  {
7530  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7531  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7532 
7533  /* analyze conflict */
7534  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
7535 
7536  SCIP_CALL( SCIPresetConsAge(scip, cons) );
7537  *cutoff = TRUE;
7538  }
7539  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
7540  {
7541  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
7542  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
7543  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
7544  }
7545  }
7546  }
7547 
7548  return SCIP_OKAY;
7549 }
7550 
7551 
7552 /*
7553  * Presolving methods
7554  */
7555 
7556 /** converts all variables with fixed domain into FIXED variables */
7557 static
7559  SCIP* scip, /**< SCIP data structure */
7560  SCIP_CONS* cons, /**< linear constraint */
7561  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7562  int* nfixedvars /**< pointer to count the total number of fixed variables */
7563  )
7564 {
7565  SCIP_CONSDATA* consdata;
7566  SCIP_VAR* var;
7567  SCIP_VARSTATUS varstatus;
7568  SCIP_Real lb;
7569  SCIP_Real ub;
7570  SCIP_Bool fixed;
7571  SCIP_Bool infeasible;
7572  int v;
7573 
7574  assert(scip != NULL);
7575  assert(cons != NULL);
7576  assert(cutoff != NULL);
7577  assert(nfixedvars != NULL);
7578 
7579  consdata = SCIPconsGetData(cons);
7580  assert(consdata != NULL);
7581 
7582  for( v = 0; v < consdata->nvars; ++v )
7583  {
7584  assert(consdata->vars != NULL);
7585  var = consdata->vars[v];
7586  varstatus = SCIPvarGetStatus(var);
7587 
7588  if( varstatus != SCIP_VARSTATUS_FIXED )
7589  {
7590  lb = SCIPvarGetLbGlobal(var);
7591  ub = SCIPvarGetUbGlobal(var);
7592  if( SCIPisEQ(scip, lb, ub) )
7593  {
7594  SCIP_Real fixval;
7595 
7596  fixval = SCIPselectSimpleValue(lb, ub, MAXDNOM);
7597  SCIPdebugMsg(scip, "converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
7598  SCIPvarGetName(var), lb, ub, fixval);
7599  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7600  if( infeasible )
7601  {
7602  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7603  *cutoff = TRUE;
7604  return SCIP_OKAY;
7605  }
7606  if( fixed )
7607  (*nfixedvars)++;
7608  }
7609  }
7610  }
7611 
7612  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
7613 
7614  if( infeasible )
7615  {
7616  SCIPdebugMsg(scip, " -> infeasible fixing\n");
7617  *cutoff = TRUE;
7618  return SCIP_OKAY;
7619  }
7620 
7621  assert(consdata->removedfixings);
7622 
7623  return SCIP_OKAY;
7624 }
7625 
7626 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
7627 
7628 /** extracts cliques of the constraint and adds them to SCIP
7629  *
7630  * The following clique extraction mechanism are implemeneted
7631  *
7632  * 1. collect binary variables and sort them in non increasing order, then
7633  *
7634  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
7635  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
7636  * condition
7637  *
7638  * minactivity + vals[i] + vals[i+1] > rhs
7639  *
7640  * and also add the binary to binary implication also for non-successive variables for which the same argument
7641  * holds
7642  *
7643  * minactivity + vals[i] + vals[j] > rhs
7644  *
7645  * 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
7646  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
7647  *
7648  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
7649  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
7650  * condition
7651  *
7652  * maxactivity + vals[i] + vals[i-1] < lhs
7653  *
7654  * and also add the binary to binary implication also for non-successive variables for which the same argument
7655  * holds
7656  *
7657  * maxactivity + vals[i] + vals[j] < lhs
7658  *
7659  * e.g. you could multiply the above example by -1
7660  *
7661  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
7662  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7663  * condition
7664  *
7665  * minactivity - vals[i] - vals[i-1] > rhs
7666  *
7667  * and also add the binary to binary implication also for non-successive variables for which the
7668  * same argument holds
7669  *
7670  * minactivity - vals[i] - vals[j] > rhs
7671  *
7672  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
7673  * implication x1 = 0 => x3 = 1
7674  *
7675  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
7676  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
7677  * condition
7678  *
7679  * maxactivity - vals[i] - vals[i+1] < lhs
7680  *
7681  * and also add the binary to binary implication also for non-successive variables for which the same argument
7682  * holds
7683  *
7684  * maxactivity - vals[i] - vals[j] < lhs
7685  *
7686  * e.g. you could multiply the above example by -1
7687  *
7688  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
7689  * as clique, (this part is done at the end of the method)
7690  *
7691  */
7692 static
7694  SCIP* scip, /**< SCIP data structure */
7695  SCIP_CONS* cons, /**< linear constraint */
7696  SCIP_Real maxeasyactivitydelta,/**< maximum activity delta to run easy propagation on linear constraint */
7697  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
7698  int* nfixedvars, /**< pointer to count number of fixed variables */
7699  int* nchgbds, /**< pointer to count the total number of tightened bounds */
7700  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
7701  )
7702 {
7703  SCIP_VAR** vars;
7704  SCIP_Real* vals;
7705  SCIP_CONSDATA* consdata;
7706  SCIP_Bool lhsclique;
7707  SCIP_Bool rhsclique;
7708  SCIP_Bool finitelhs;
7709  SCIP_Bool finiterhs;
7710  SCIP_Bool finiteminact;
7711  SCIP_Bool finitemaxact;
7712  SCIP_Bool finitenegminact;
7713  SCIP_Bool finitenegmaxact;
7714  SCIP_Bool finiteposminact;
7715  SCIP_Bool finiteposmaxact;
7716  SCIP_Bool infeasible;
7717  SCIP_Bool stopped;
7718  int cliquenonzerosadded;
7719  int v;
7720  int i;
7721  int nposcoefs;
7722  int nnegcoefs;
7723  int nvars;
7724 
7725  assert(scip != NULL);
7726  assert(cons != NULL);
7727  assert(nfixedvars != NULL);
7728  assert(nchgbds != NULL);
7729  assert(cutoff != NULL);
7730  assert(!SCIPconsIsDeleted(cons));
7731 
7732  consdata = SCIPconsGetData(cons);
7733  assert(consdata != NULL);
7734 
7735  if( consdata->nvars < 2 )
7736  return SCIP_OKAY;
7737 
7738  /* add implications if posibble
7739  *
7740  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
7741  * maximal absolute contribution and also only if this variable would force all other variables to their bound
7742  * corresponding to the global minimal activity of the constraint
7743  */
7744  if( !consdata->implsadded )
7745  {
7746  /* sort variables by variable type */
7747  SCIP_CALL( consdataSort(scip, consdata) );
7748 
7749  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
7750  * up front, might change sorting correspondingly
7751  */
7752  /* fast abort if no binaries exist */
7753  if( !SCIPvarIsBinary(consdata->vars[0]) )
7754  return SCIP_OKAY;
7755 
7756  nvars = consdata->nvars;
7757  vars = consdata->vars;
7758  vals = consdata->vals;
7759 
7760  /* recompute activities if needed */
7761  if( !consdata->validactivities )
7762  consdataCalcActivities(scip, consdata);
7763  assert(consdata->validactivities);
7764 
7765  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
7766  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
7767  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
7768  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
7769  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
7770  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
7771  finiteminact = (finitenegminact && finiteposminact);
7772  finitemaxact = (finitenegmaxact && finiteposmaxact);
7773 
7774  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
7775  {
7776  SCIP_Real maxabscontrib = -1.0;
7777  SCIP_Bool posval = FALSE;
7778  SCIP_Bool allbinary = TRUE;
7779  int oldnchgbds = *nchgbds;
7780  int nbdchgs = 0;
7781  int nimpls = 0;
7782  int position = -1;
7783 
7784  /* we need a valid minimal/maximal activity to add cliques */
7785  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
7786  {
7787  consdataRecomputeGlbMinactivity(scip, consdata);
7788  assert(consdata->validglbminact);
7789  }
7790 
7791  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
7792  {
7793  consdataRecomputeGlbMaxactivity(scip, consdata);
7794  assert(consdata->validglbmaxact);
7795  }
7796  assert(consdata->validglbminact || consdata->validglbmaxact);
7797 
7798  /* @todo extend this to local/constraint probing */
7799 
7800  /* determine maximal contribution to the activity */
7801  for( v = nvars - 1; v >= 0; --v )
7802  {
7803  if( SCIPvarIsBinary(vars[v]) )
7804  {
7805  if( vals[v] > 0 )
7806  {
7807  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
7808 
7809  if( value > maxabscontrib )
7810  {
7811  maxabscontrib = value;
7812  position = v;
7813  posval = TRUE;
7814  }
7815  }
7816  else
7817  {
7818  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
7819 
7820  value = REALABS(value);
7821 
7822  if( value > maxabscontrib )
7823  {
7824  maxabscontrib = value;
7825  position = v;
7826  posval = FALSE;
7827  }
7828  }
7829  }
7830  else
7831  allbinary = FALSE;
7832  }
7833  assert(0 <= position && position < nvars);
7834 
7835  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
7836  {
7837  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
7838  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
7839  * implications
7840  */
7841  if( finiterhs && finiteminact && SCIPisEQ(scip, consdata->glbminactivity, consdata->rhs - maxabscontrib) )
7842  {
7843  for( v = nvars - 1; v >= 0; --v )
7844  {
7845  /* binary to binary implications will be collected when extrating cliques */
7846  if( !SCIPvarIsBinary(vars[v]) )
7847  {
7848  if( v != position )
7849  {
7850  if( vals[v] > 0 )
7851  {
7852  /* add implications */
7853  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
7854  ++nimpls;
7855  *nchgbds += nbdchgs;
7856  }
7857  else
7858  {
7859  /* add implications */
7860  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
7861  ++nimpls;
7862  *nchgbds += nbdchgs;
7863  }
7864 
7865  if( infeasible )
7866  {
7867  *cutoff = TRUE;
7868  break;
7869  }
7870  }
7871  }
7872  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
7873  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
7874  break;
7875  }
7876  }
7877 
7878  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
7879  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
7880  * implications
7881  */
7882  if( finitelhs && finitemaxact && SCIPisEQ(scip, consdata->glbmaxactivity, consdata->lhs - maxabscontrib) )
7883  {
7884  for( v = nvars - 1; v >= 0; --v )
7885  {
7886  /* binary to binary implications will be collected when extrating cliques */
7887  if( !SCIPvarIsBinary(vars[v]) )
7888  {
7889  if( v != position )
7890  {
7891  if( vals[v] > 0 )
7892  {
7893  /* add implications */
7894  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
7895  ++nimpls;
7896  *nchgbds += nbdchgs;
7897  }
7898  else
7899  {
7900  /* add implications */
7901  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
7902  ++nimpls;
7903  *nchgbds += nbdchgs;
7904  }
7905 
7906  if( infeasible )
7907  {
7908  *cutoff = TRUE;
7909  break;
7910  }
7911  }
7912  }
7913  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
7914  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
7915  break;
7916  }
7917  }
7918 
7919  /* did we find some implications */
7920  if( nimpls > 0 )
7921  {
7922  SCIPdebugMsg(scip, "extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
7923 
7924  if( *cutoff )
7925  return SCIP_OKAY;
7926 
7927  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
7928  if( *nchgbds - oldnchgbds > 0 )
7929  {
7930  /* check for fixed variables */
7931  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
7932  if( *cutoff )
7933  return SCIP_OKAY;
7934 
7935  /* tighten variable's bounds */
7936  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
7937  if( *cutoff )
7938  return SCIP_OKAY;
7939 
7940  /* check for fixed variables */
7941  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
7942  if( *cutoff )
7943  return SCIP_OKAY;
7944  }
7945  }
7946  }
7947  }
7948 
7949  consdata->implsadded = TRUE;
7950  }
7951 
7952  /* check if we already added the cliques of this constraint */
7953  if( consdata->cliquesadded )
7954  return SCIP_OKAY;
7955 
7956  consdata->cliquesadded = TRUE;
7957  cliquenonzerosadded = 0;
7958  stopped = FALSE;
7959 
7960  /* sort variables by variable type */
7961  SCIP_CALL( consdataSort(scip, consdata) );
7962 
7963  nvars = consdata->nvars;
7964  vars = consdata->vars;
7965  vals = consdata->vals;
7966 
7967  /**@todo extract more cliques, implications and variable bounds from linear constraints */
7968 
7969  /* recompute activities if needed */
7970  if( !consdata->validactivities )
7971  consdataCalcActivities(scip, consdata);
7972  assert(consdata->validactivities);
7973 
7974  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
7975  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
7976  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
7977  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
7978  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
7979  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
7980  finiteminact = (finitenegminact && finiteposminact);
7981  finitemaxact = (finitenegmaxact && finiteposmaxact);
7982 
7983  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
7984  * information
7985  */
7986  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
7987  {
7988  SCIP_VAR** binvars;
7989  SCIP_Real* binvarvals;
7990  int nposbinvars = 0;
7991  int nnegbinvars = 0;
7992  int allonebinary = 0;
7993 
7994  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
7995  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
7996 
7997  /* collect binary variables */
7998  for( i = 0; i < nvars; ++i )
7999  {
8000  if( SCIPvarIsBinary(vars[i]) )
8001  {
8002  assert(!SCIPisZero(scip, vals[i]));
8003 
8004  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8005  ++allonebinary;
8006 
8007  binvars[nposbinvars + nnegbinvars] = vars[i];
8008  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8009 
8010  if( SCIPisPositive(scip, vals[i]) )
8011  ++nposbinvars;
8012  else
8013  ++nnegbinvars;
8014 
8015  assert(nposbinvars + nnegbinvars <= nvars);
8016  }
8017  /* stop searching for binary variables, because the constraint data is sorted */
8018  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8019  break;
8020  }
8021  assert(nposbinvars + nnegbinvars <= nvars);
8022 
8023  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
8024  * cliques
8025  */
8026  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
8027  {
8028  SCIP_Real threshold;
8029  int oldnchgbds = *nchgbds;
8030  int nbdchgs;
8031  int jstart;
8032  int j;
8033 
8034  /* we need a valid minimal/maximal activity to add cliques */
8035  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
8036  {
8037  consdataRecomputeGlbMinactivity(scip, consdata);
8038  assert(consdata->validglbminact);
8039  }
8040 
8041  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
8042  {
8043  consdataRecomputeGlbMaxactivity(scip, consdata);
8044  assert(consdata->validglbmaxact);
8045  }
8046  assert(consdata->validglbminact || consdata->validglbmaxact);
8047 
8048  /* sort coefficients non-increasing to be faster in the clique search */
8049  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
8050 
8051  /* case a) */
8052  if( finiterhs && finitenegminact && nposbinvars >= 2 )
8053  {
8054  /* compute value that needs to be exceeded */
8055  threshold = consdata->rhs - consdata->glbminactivity;
8056 
8057  i = 0;
8058  j = i + 1;
8059 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8060  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8061  assert(SCIPisFeasLE(scip, binvarvals[i], threshold));
8062 #endif
8063  /* check if at least two variables are in a clique */
8064  if( SCIPisFeasGT(scip, binvarvals[i] + binvarvals[j], threshold) )
8065  {
8066  ++j;
8067  /* check for extending the clique */
8068  while( j < nposbinvars )
8069  {
8070  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
8071  break;
8072  ++j;
8073  }
8074  assert(j >= 2);
8075 
8076  /* add clique with at least two variables */
8077  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), NULL, j - i, FALSE, &infeasible, &nbdchgs) );
8078 
8079  if( infeasible )
8080  *cutoff = TRUE;
8081 
8082  *nchgbds += nbdchgs;
8083 
8084  cliquenonzerosadded += j;
8085  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8086  stopped = TRUE;
8087 
8088  /* exchange the last variable in the clique if possible and add all new ones */
8089  if( !stopped && !(*cutoff) && j < nposbinvars )
8090  {
8091  SCIP_VAR** clqvars;
8092  int lastfit = j - 2;
8093  assert(lastfit >= i);
8094 
8095  /* copy all 'main'-clique variables */
8096  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
8097 
8098  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8099  while( lastfit >= i && j < nposbinvars )
8100  {
8101  /* check if two variables are in a clique */
8102  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8103  {
8104  clqvars[lastfit + 1] = binvars[j];
8105 
8106  /* add clique with at least two variables */
8107  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit - i + 2, FALSE, &infeasible, &nbdchgs) );
8108 
8109  if( infeasible )
8110  {
8111  *cutoff = TRUE;
8112  break;
8113  }
8114 
8115  *nchgbds += nbdchgs;
8116 
8117  cliquenonzerosadded += (lastfit - i + 2);
8118  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8119  {
8120  stopped = TRUE;
8121  break;
8122  }
8123 
8124  ++j;
8125  }
8126  else
8127  --lastfit;
8128  }
8129 
8130  SCIPfreeBufferArray(scip, &clqvars);
8131  }
8132  }
8133  }
8134 
8135  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8136  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8137  {
8138  /* check for fixed variables */
8139  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8140 
8141  if( !*cutoff )
8142  {
8143  /* tighten variable's bounds */
8144  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8145 
8146  if( !*cutoff )
8147  {
8148  /* check for fixed variables */
8149  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8150 
8151  if( !*cutoff )
8152  {
8153  /* sort variables by variable type */
8154  SCIP_CALL( consdataSort(scip, consdata) );
8155 
8156  /* recompute activities if needed */
8157  if( !consdata->validactivities )
8158  consdataCalcActivities(scip, consdata);
8159  assert(consdata->validactivities);
8160 
8161  nvars = consdata->nvars;
8162  vars = consdata->vars;
8163  vals = consdata->vals;
8164  nposbinvars = 0;
8165  nnegbinvars = 0;
8166  allonebinary = 0;
8167 
8168  /* update binary variables */
8169  for( i = 0; i < nvars; ++i )
8170  {
8171  if( SCIPvarIsBinary(vars[i]) )
8172  {
8173  assert(!SCIPisZero(scip, vals[i]));
8174 
8175  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8176  ++allonebinary;
8177 
8178  binvars[nposbinvars + nnegbinvars] = vars[i];
8179  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8180 
8181  if( SCIPisPositive(scip, vals[i]) )
8182  ++nposbinvars;
8183  else
8184  ++nnegbinvars;
8185 
8186  assert(nposbinvars + nnegbinvars <= nvars);
8187  }
8188  /* stop searching for binary variables, because the constraint data is sorted */
8189  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8190  break;
8191  }
8192  assert(nposbinvars + nnegbinvars <= nvars);
8193  }
8194  }
8195  }
8196 
8197  oldnchgbds = *nchgbds;
8198  }
8199 
8200  /* case b) */
8201  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
8202  {
8203  /* compute value that needs to be deceeded */
8204  threshold = consdata->lhs - consdata->glbmaxactivity;
8205 
8206  i = nposbinvars + nnegbinvars - 1;
8207  j = i - 1;
8208 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8209  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
8210  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
8211 #endif
8212  /* check if two variables are in a clique */
8213  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
8214  {
8215  --j;
8216  /* check for extending the clique */
8217  while( j >= nposbinvars )
8218  {
8219  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
8220  break;
8221  --j;
8222  }
8223  jstart = j;
8224 
8225  assert(i - j >= 2);
8226  /* add clique with at least two variables */
8227  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, FALSE, &infeasible, &nbdchgs) );
8228 
8229  if( infeasible )
8230  *cutoff = TRUE;
8231 
8232  *nchgbds += nbdchgs;
8233 
8234  cliquenonzerosadded += (i - j);
8235  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8236  stopped = TRUE;
8237 
8238  /* exchange the last variable in the clique if possible and add all new ones */
8239  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8240  {
8241  SCIP_VAR** clqvars;
8242  int lastfit = jstart + 1;
8243  assert(lastfit < i);
8244 
8245  /* copy all 'main'-clique variables */
8246  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8247  ++lastfit;
8248 
8249  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8250  while( lastfit <= i && j >= nposbinvars )
8251  {
8252  /* check if two variables are in a clique */
8253  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
8254  {
8255  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8256  clqvars[lastfit - jstart - 2] = binvars[j];
8257 
8258  assert(i - lastfit + 2 >= 2);
8259  /* add clique with at least two variables */
8260  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8261 
8262  if( infeasible )
8263  {
8264  *cutoff = TRUE;
8265  break;
8266  }
8267 
8268  *nchgbds += nbdchgs;
8269 
8270  cliquenonzerosadded += (i - lastfit + 2);
8271  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8272  {
8273  stopped = TRUE;
8274  break;
8275  }
8276 
8277  --j;
8278  }
8279  else
8280  ++lastfit;
8281  }
8282 
8283  SCIPfreeBufferArray(scip, &clqvars);
8284  }
8285  }
8286  }
8287 
8288  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8289  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8290  {
8291  /* check for fixed variables */
8292  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8293 
8294  if( !*cutoff )
8295  {
8296  /* tighten variable's bounds */
8297  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8298 
8299  if( !*cutoff )
8300  {
8301  /* check for fixed variables */
8302  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8303 
8304  if( !*cutoff )
8305  {
8306  /* sort variables by variable type */
8307  SCIP_CALL( consdataSort(scip, consdata) );
8308 
8309  /* recompute activities if needed */
8310  if( !consdata->validactivities )
8311  consdataCalcActivities(scip, consdata);
8312  assert(consdata->validactivities);
8313 
8314  nvars = consdata->nvars;
8315  vars = consdata->vars;
8316  vals = consdata->vals;
8317  nposbinvars = 0;
8318  nnegbinvars = 0;
8319  allonebinary = 0;
8320 
8321  /* update binary variables */
8322  for( i = 0; i < nvars; ++i )
8323  {
8324  if( SCIPvarIsBinary(vars[i]) )
8325  {
8326  assert(!SCIPisZero(scip, vals[i]));
8327 
8328  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8329  ++allonebinary;
8330 
8331  binvars[nposbinvars + nnegbinvars] = vars[i];
8332  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8333 
8334  if( SCIPisPositive(scip, vals[i]) )
8335  ++nposbinvars;
8336  else
8337  ++nnegbinvars;
8338 
8339  assert(nposbinvars + nnegbinvars <= nvars);
8340  }
8341  /* stop searching for binary variables, because the constraint data is sorted */
8342  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8343  break;
8344  }
8345  assert(nposbinvars + nnegbinvars <= nvars);
8346  }
8347  }
8348  }
8349 
8350  oldnchgbds = *nchgbds;
8351  }
8352 
8353  /* case c) */
8354  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
8355  {
8356  SCIP_Bool* values;
8357 
8358  /* initialize clique values array for adding a negated clique */
8359  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
8360  BMSclearMemoryArray(values, nnegbinvars);
8361 
8362  /* compute value that needs to be exceeded */
8363  threshold = consdata->rhs - consdata->glbminactivity;
8364 
8365  i = nposbinvars + nnegbinvars - 1;
8366  j = i - 1;
8367 
8368 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8369  /* check if the variable should not have already been fixed to one */
8370  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
8371 #endif
8372 
8373  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8374  {
8375  --j;
8376  /* check for extending the clique */
8377  while( j >= nposbinvars )
8378  {
8379  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
8380  break;
8381  --j;
8382  }
8383  jstart = j;
8384 
8385  assert(i - j >= 2);
8386  /* add negated clique with at least two variables */
8387  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, FALSE, &infeasible, &nbdchgs) );
8388 
8389  if( infeasible )
8390  *cutoff = TRUE;
8391 
8392  *nchgbds += nbdchgs;
8393 
8394  cliquenonzerosadded += (i - j);
8395  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8396  stopped = TRUE;
8397 
8398  /* exchange the last variable in the clique if possible and add all new ones */
8399  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
8400  {
8401  SCIP_VAR** clqvars;
8402  int lastfit = j + 1;
8403  assert(lastfit < i);
8404 
8405  /* copy all 'main'-clique variables */
8406  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
8407  ++lastfit;
8408 
8409  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
8410  while( lastfit <= i && j >= nposbinvars )
8411  {
8412  /* check if two variables are in a negated clique */
8413  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8414  {
8415  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
8416  clqvars[lastfit - jstart - 2] = binvars[j];
8417 
8418  assert(i - lastfit + 2 >= 2);
8419  /* add clique with at least two variables */
8420  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, FALSE, &infeasible, &nbdchgs) );
8421 
8422  if( infeasible )
8423  {
8424  *cutoff = TRUE;
8425  break;
8426  }
8427 
8428  *nchgbds += nbdchgs;
8429 
8430  cliquenonzerosadded += (i - lastfit + 2);
8431  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8432  {
8433  stopped = TRUE;
8434  break;
8435  }
8436 
8437  --j;
8438  }
8439  else
8440  ++lastfit;
8441  }
8442 
8443  SCIPfreeBufferArray(scip, &clqvars);
8444  }
8445  }
8446 
8447  SCIPfreeBufferArray(scip, &values);
8448  }
8449 
8450  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
8451  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
8452  {
8453  /* check for fixed variables */
8454  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8455 
8456  if( !*cutoff )
8457  {
8458  /* tighten variable's bounds */
8459  SCIP_CALL( tightenBounds(scip, cons, maxeasyactivitydelta, sortvars, cutoff, nchgbds) );
8460 
8461  if( !*cutoff )
8462  {
8463  /* check for fixed variables */
8464  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
8465 
8466  if( !*cutoff )
8467  {
8468  /* sort variables by variable type */
8469  SCIP_CALL( consdataSort(scip, consdata) );
8470 
8471  /* recompute activities if needed */
8472  if( !consdata->validactivities )
8473  consdataCalcActivities(scip, consdata);
8474  assert(consdata->validactivities);
8475 
8476  nvars = consdata->nvars;
8477  vars = consdata->vars;
8478  vals = consdata->vals;
8479  nposbinvars = 0;
8480  nnegbinvars = 0;
8481  allonebinary = 0;
8482 
8483  /* update binary variables */
8484  for( i = 0; i < nvars; ++i )
8485  {
8486  if( SCIPvarIsBinary(vars[i]) )
8487  {
8488  assert(!SCIPisZero(scip, vals[i]));
8489 
8490  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
8491  ++allonebinary;
8492 
8493  binvars[nposbinvars + nnegbinvars] = vars[i];
8494  binvarvals[nposbinvars + nnegbinvars] = vals[i];
8495 
8496  if( SCIPisPositive(scip, vals[i]) )
8497  ++nposbinvars;
8498  else
8499  ++nnegbinvars;
8500 
8501  assert(nposbinvars + nnegbinvars <= nvars);
8502  }
8503  /* stop searching for binary variables, because the constraint data is sorted */
8504  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
8505  break;
8506  }
8507  assert(nposbinvars + nnegbinvars <= nvars);
8508  }
8509  }
8510  }
8511  }
8512 
8513  /* case d) */
8514  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
8515  {
8516  SCIP_Bool* values;
8517 
8518  /* initialize clique values array for adding a negated clique */
8519  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
8520  BMSclearMemoryArray(values, nposbinvars);
8521 
8522  /* compute value that needs to be exceeded */
8523  threshold = consdata->lhs - consdata->glbmaxactivity;
8524 
8525  i = 0;
8526  j = i + 1;
8527 
8528 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
8529  /* check if the variable should not have already been fixed to one */
8530  assert(!SCIPisFeasLT(scip, -binvarvals[i], threshold));
8531 #endif
8532 
8533  if( SCIPisFeasLT(scip, -binvarvals[i] - binvarvals[j], threshold) )
8534  {
8535  ++j;
8536  /* check for extending the clique */
8537  while( j < nposbinvars )
8538  {
8539  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
8540  break;
8541  ++j;
8542  }
8543  assert(j >= 2);
8544 
8545  /* add negated clique with at least two variables */
8546  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), values, j - i, FALSE, &infeasible, &nbdchgs) );
8547 
8548  if( infeasible )
8549  *cutoff = TRUE;
8550 
8551  *nchgbds += nbdchgs;
8552 
8553  cliquenonzerosadded += j;
8554  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8555  stopped = TRUE;
8556 
8557  /* exchange the last variable in the clique if possible and add all new ones */
8558  if( !stopped && !(*cutoff) && j < nposbinvars )
8559  {
8560  SCIP_VAR** clqvars;
8561  int lastfit = j - 2;
8562  assert(lastfit >= i);
8563 
8564  /* copy all 'main'-clique variables */
8565  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
8566 
8567  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
8568  while( lastfit >= i && j < nposbinvars )
8569  {
8570  /* check if two variables are in a negated clique */
8571  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
8572  {
8573  clqvars[lastfit + 1] = binvars[j];
8574 
8575  /* add clique with at least two variables */
8576  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit - i + 2, FALSE, &infeasible, &nbdchgs) );
8577 
8578  if( infeasible )
8579  {
8580  *cutoff = TRUE;
8581  break;
8582  }
8583 
8584  *nchgbds += nbdchgs;
8585 
8586  cliquenonzerosadded += (lastfit - i + 2);
8587  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
8588  break;
8589 
8590  ++j;
8591  }
8592  else
8593  --lastfit;
8594  }
8595 
8596  SCIPfreeBufferArray(scip, &clqvars);
8597  }
8598  }
8599 
8600  SCIPfreeBufferArray(scip, &values);
8601  }
8602  }
8603 
8604  SCIPfreeBufferArray(scip, &binvarvals);
8605  SCIPfreeBufferArray(scip, &binvars);
8606 
8607  if( *cutoff )
8608  return SCIP_OKAY;
8609  }
8610 
8611  /* 2. we only check if the constraint is a set packing / partitioning constraint */
8612 
8613  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
8614  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
8615  */
8616  nposcoefs = 0;
8617  nnegcoefs = 0;
8618  for( i = 0; i < nvars; ++i )
8619  {
8620  if( !SCIPvarIsBinary(vars[i]) )
8621  return SCIP_OKAY;
8622  else if( SCIPisEQ(scip, vals[i], +1.0) )
8623  nposcoefs++;
8624  else if( SCIPisEQ(scip, vals[i], -1.0) )
8625  nnegcoefs++;
8626  else
8627  return SCIP_OKAY;
8628  }
8629 
8630  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
8631  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
8632 
8633  if( lhsclique || rhsclique )
8634  {
8635  SCIP_Bool* values;
8636  int nbdchgs;
8637 
8638  SCIPdebugMsg(scip, "linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
8639  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
8640  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
8641 
8642  for( i = 0; i < nvars; ++i )
8643  values[i] = (rhsclique == (vals[i] > 0.0));
8644 
8645  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, SCIPisEQ(scip, consdata->lhs, consdata->rhs), &infeasible, &nbdchgs) );
8646 
8647  if( infeasible )
8648  *cutoff = TRUE;
8649 
8650  *nchgbds += nbdchgs;
8651  SCIPfreeBufferArray(scip, &values);
8652  }
8653 
8654  return SCIP_OKAY;
8655 }
8656 
8657 /** tightens left and right hand side of constraint due to integrality */
8658 static
8660  SCIP* scip, /**< SCIP data structure */
8661  SCIP_CONS* cons, /**< linear constraint */
8662  int* nchgsides /**< pointer to count number of side changes */
8663  )
8664 {
8665  SCIP_CONSDATA* consdata;
8666  SCIP_Bool integral;
8667  int i;
8668 
8669  assert(scip != NULL);
8670  assert(cons != NULL);
8671  assert(nchgsides != NULL);
8672 
8673  consdata = SCIPconsGetData(cons);
8674  assert(consdata != NULL);
8675 
8676  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
8677  {
8678  integral = TRUE;
8679  for( i = 0; i < consdata->nvars && integral; ++i )
8680  {
8681  integral = SCIPisIntegral(scip, consdata->vals[i])
8682  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
8683  }
8684  if( integral )
8685  {
8686  SCIPdebugMsg(scip, "linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
8687  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8688  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
8689  {
8690  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
8691  if( !consdata->upgraded )
8692  (*nchgsides)++;
8693  }
8694  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
8695  {
8696  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
8697  if( !consdata->upgraded )
8698  (*nchgsides)++;
8699  }
8700  SCIPdebugMsg(scip, "linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
8701  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
8702  }
8703  }
8704 
8705  return SCIP_OKAY;
8706 }
8707 
8708 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
8709  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
8710  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
8711  * (i) ai >= 0:
8712  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
8713  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
8714  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8715  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8716  * - change coefficients:
8717  * ai' := max(lhs - minact, maxact - rhs)
8718  * lhs' := lhs - (ai - ai')*li
8719  * rhs' := rhs - (ai - ai')*ui
8720  * (ii) ai < 0:
8721  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
8722  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
8723  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
8724  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
8725  * - change coefficients:
8726  * ai' := min(rhs - maxact, minact - lhs)
8727  * lhs' := lhs - (ai - ai')*ui
8728  * rhs' := rhs - (ai - ai')*li
8729  *
8730  * We further try to remove redundant variable from the constraint;
8731  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
8732  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
8733  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
8734  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
8735  * 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
8736  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
8737  *
8738  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
8739  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
8740  */
8741 static
8743  SCIP* scip, /**< SCIP data structure */
8744  SCIP_CONS* cons, /**< linear constraint */
8745  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
8746  int* nchgsides /**< pointer to count number of side changes */
8747  )
8748 {
8749  SCIP_CONSDATA* consdata;
8750  SCIP_VAR* var;
8751  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
8752  * activity, ignoring the coefficients contributing with infinite value */
8753  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
8754  * activity, ignoring the coefficients contributing with infinite value */
8755  SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
8756  SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
8757  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
8758  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
8759  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
8760  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
8761  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
8762  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
8763  SCIP_Real val;
8764  SCIP_Real newval;
8765  SCIP_Real newlhs;
8766  SCIP_Real newrhs;
8767  SCIP_Real lb;
8768  SCIP_Real ub;
8769  int i;
8770 
8771  assert(scip != NULL);
8772  assert(cons != NULL);
8773  assert(nchgcoefs != NULL);
8774  assert(nchgsides != NULL);
8775 
8776  consdata = SCIPconsGetData(cons);
8777  assert(consdata != NULL);
8778 
8779  /* @todo Is this still needed with automatic recomputation of activities? */
8780  /* if the maximal coefficient is too large, recompute the activities */
8781  if( (consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP)
8782  || (consdata->validminabsval && consdata->minabsval < MINVALRECOMP) )
8783  {
8784  consdataRecomputeMinactivity(scip, consdata);
8785  consdataRecomputeMaxactivity(scip, consdata);
8786  }
8787 
8788  /* get the minimal and maximal activity of the constraint */
8789  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
8790 
8791  minleftactivity = 0.0;
8792  maxleftactivity = 0.0;
8793 
8794  /* try to tighten each coefficient */
8795  i = 0;
8796  while( i < consdata->nvars )
8797  {
8798  var = consdata->vars[i];
8799 
8800  /* get coefficient and variable's bounds */
8801  lb = SCIPvarGetLbLocal(var);
8802  ub = SCIPvarGetUbLocal(var);
8803  val = consdata->vals[i];
8804  assert(!SCIPisZero(scip, val));
8805 
8806  /* check sign of coefficient */
8807  if( val >= 0.0 )
8808  {
8809  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
8811  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
8812  {
8813  /* change coefficients:
8814  * ai' := max(lhs - minact, maxact - rhs)
8815  * lhs' := lhs - (ai - ai')*li
8816  * rhs' := rhs - (ai - ai')*ui
8817  */
8818 
8819  lval = consdata->lhs - minactivity;
8820  rval = maxactivity - consdata->rhs;
8821 
8822  /* Try to avoid cancellation, if there are only two variables */
8823  if( consdata->nvars == 2 )
8824  {
8825  SCIP_Real otherval;
8826  otherval = consdata->vals[1-i];
8827 
8828  if( !SCIPisInfinity(scip, -consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
8829  {
8830  lval = consdata->lhs - val*lb;
8831  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
8832  }
8833 
8834  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
8835  {
8836  rval = val*ub - consdata->rhs;
8837  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
8838  }
8839  }
8840 
8841  newval = MAX(lval, rval);
8842  assert(SCIPisSumRelLE(scip, newval, val));
8843 
8844  /* Try to avoid cancellation in computation of lhs/rhs */
8845  newlhs = consdata->lhs - val * lb;
8846  newlhs += newval * lb;
8847  newrhs = consdata->rhs - val * ub;
8848  newrhs += newval * ub;
8849 
8850  if( !SCIPisSumRelEQ(scip, newval, val) )
8851  {
8852  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
8853  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
8854  minactivity, maxactivity, consdata->lhs, consdata->rhs);
8855 
8856  /* update the coefficient and the activity bounds */
8857  if( SCIPisZero(scip, newval) )
8858  {
8859  SCIP_CALL( delCoefPos(scip, cons, i) );
8860  i--;
8861  }
8862  else
8863  {
8864  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
8865  }
8866  (*nchgcoefs)++;
8867 
8868  /* get the new minimal and maximal activity of the constraint */
8869  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
8870 
8871  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
8872  {
8873  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
8874 
8875  SCIP_CALL( chgLhs(scip, cons, newlhs) );
8876  (*nchgsides)++;
8877  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
8878  }
8879 
8880  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
8881  {
8882  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
8883 
8884  SCIP_CALL( chgRhs(scip, cons, newrhs) );
8885  (*nchgsides)++;
8886  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
8887  }
8888  }
8889  }
8890  else
8891  {
8892  if( !SCIPisInfinity(scip, -minleftactivity) )
8893  {
8894  assert(!SCIPisInfinity(scip, val));
8895  assert(!SCIPisInfinity(scip, lb));
8896  if( SCIPisInfinity(scip, -lb) )
8897  minleftactivity = -SCIPinfinity(scip);
8898  else
8899  minleftactivity += val * lb;
8900  }
8901 
8902  if( !SCIPisInfinity(scip, maxleftactivity) )
8903  {
8904  assert(!SCIPisInfinity(scip, val));
8905  assert(!SCIPisInfinity(scip, -ub));
8906  if( SCIPisInfinity(scip,ub) )
8907  maxleftactivity = SCIPinfinity(scip);
8908  else
8909  maxleftactivity += val * ub;
8910  }
8911  }
8912  }
8913  else
8914  {
8915  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
8917  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
8918  {
8919  /* change coefficients:
8920  * ai' := min(rhs - maxact, minact - lhs)
8921  * lhs' := lhs - (ai - ai')*ui
8922  * rhs' := rhs - (ai - ai')*li
8923  */
8924 
8925  lval = minactivity - consdata->lhs;
8926  rval = consdata->rhs - maxactivity;
8927 
8928  /* Try to avoid cancellation, if there are only two variables */
8929  if( consdata->nvars == 2 )
8930  {
8931  SCIP_Real otherval;
8932  otherval = consdata->vals[1-i];
8933 
8934  if( !SCIPisInfinity(scip,-consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
8935  {
8936  lval = val*ub - consdata->lhs;
8937  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
8938  }
8939 
8940  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
8941  {
8942  rval = consdata->rhs - val*lb;
8943  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
8944  }
8945  }
8946 
8947  newval = MIN(lval, rval);
8948  assert(SCIPisSumRelGE(scip, newval, val));
8949 
8950  /* Try to avoid cancellation in computation of lhs/rhs */
8951  newlhs = consdata->lhs - val * ub;
8952  newlhs += newval * ub;
8953  newrhs = consdata->rhs - val * lb;
8954  newrhs += newval * lb;
8955 
8956  if( !SCIPisSumRelEQ(scip, newval, val) )
8957  {
8958  SCIPdebugMsg(scip, "linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
8959  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
8960  minactivity, maxactivity, consdata->lhs, consdata->rhs);
8961 
8962  /* update the coefficient and the activity bounds */
8963  if( SCIPisZero(scip, newval) )
8964  {
8965  SCIP_CALL( delCoefPos(scip, cons, i) );
8966  i--;
8967  }
8968  else
8969  {
8970  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
8971  }
8972  (*nchgcoefs)++;
8973 
8974  /* get the new minimal and maximal activity of the constraint */
8975  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
8976 
8977  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
8978  {
8979  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
8980 
8981  SCIP_CALL( chgLhs(scip, cons, newlhs) );
8982  (*nchgsides)++;
8983  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
8984  }
8985 
8986  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
8987  {
8988  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
8989 
8990  SCIP_CALL( chgRhs(scip, cons, newrhs) );
8991  (*nchgsides)++;
8992  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
8993  }
8994  }
8995  }
8996  else
8997  {
8998  if( !SCIPisInfinity(scip, -minleftactivity) )
8999  {
9000  assert(!SCIPisInfinity(scip, -val));
9001  assert(!SCIPisInfinity(scip, -ub));
9002  if( SCIPisInfinity(scip, ub) )
9003  minleftactivity = -SCIPinfinity(scip);
9004  else
9005  minleftactivity += val * ub;
9006  }
9007 
9008  if( !SCIPisInfinity(scip, maxleftactivity) )
9009  {
9010  assert(!SCIPisInfinity(scip, -val));
9011  assert(!SCIPisInfinity(scip, lb));
9012  if( SCIPisInfinity(scip, -lb) )
9013  maxleftactivity = SCIPinfinity(scip);
9014  else
9015  maxleftactivity += val * lb;
9016  }
9017  }
9018  }
9019  ++i;
9020  }
9021 
9022  SCIPdebugMsg(scip, "minleftactivity = %.15g, rhs = %.15g\n",
9023  minleftactivity, consdata->rhs);
9024  SCIPdebugMsg(scip, "maxleftactivity = %.15g, lhs = %.15g\n",
9025  maxleftactivity, consdata->lhs);
9026 
9027  /* minleft == \infty ==> minactivity == \infty */
9028  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
9029  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
9030 
9031  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
9032  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
9033  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
9034  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
9035  */
9036  assert(!SCIPisInfinity(scip, minactivity));
9037  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
9038  return SCIP_OKAY;
9039 
9040  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
9041  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
9042  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
9043  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
9044  */
9045  assert(!SCIPisInfinity(scip, -maxactivity));
9046  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
9047  return SCIP_OKAY;
9048 
9049  /* correct lhs and rhs by min/max activity of surely non-redundant variables
9050  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
9051  */
9052  aggrlhs = consdata->lhs - minactivity + minleftactivity;
9053  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
9054 
9055  /* check if the constraint contains variables which are redundant. The reasoning is the following:
9056  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
9057  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
9058  * they can be removed from the constraint.
9059  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
9060  */
9061  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
9062  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
9063  {
9064  SCIP_Real minleftactivitypart;
9065  SCIP_Real maxleftactivitypart;
9066 
9067  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
9068 
9069  /* try to remove redundant variables from constraint */
9070  i = 0;
9071  while( i < consdata->nvars )
9072  {
9073  var = consdata->vars[i];
9074  minleftactivitypart = 0.0;
9075  maxleftactivitypart = 0.0;
9076  lb = SCIPvarGetLbLocal(var);
9077  ub = SCIPvarGetUbLocal(var);
9078 
9079  /* get coefficient and variable's bounds */
9080  val = consdata->vals[i];
9081  assert(!SCIPisZero(scip, val));
9082 
9083  /* check sign of coefficient */
9084  if( val >= 0.0 )
9085  {
9086  /* negation of condition above in case of positive val */
9087  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9088  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
9089  {
9090  SCIPdebugMsg(scip, "minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
9091  SCIPdebugMsg(scip, "maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
9092  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9093  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9094 
9095  minleftactivitypart = val * lb;
9096  maxleftactivitypart = val * ub;
9097 
9098  SCIP_CALL( delCoefPos(scip, cons, i) );
9099  i--;
9100 
9101  /* get the new minimal and maximal activity of the constraint */
9102  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9103 
9104  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9105  * huge contributions
9106  */
9107  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9108  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9109  }
9110  }
9111  else
9112  {
9113  /* negation of condition above in case of negative val */
9114  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
9115  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
9116  {
9117  SCIPdebugMsg(scip, "linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
9118  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
9119 
9120  minleftactivitypart = val * ub;
9121  maxleftactivitypart = val * lb;
9122 
9123  SCIP_CALL( delCoefPos(scip, cons, i) );
9124  i--;
9125 
9126  /* get the new minimal and maximal activity of the constraint */
9127  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
9128 
9129  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
9130  * huge contributions
9131  */
9132  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
9133  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
9134  }
9135  }
9136 
9137  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
9138  * redundant variables could get deleted,
9139  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
9140  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
9141  * we would also delete y2 and as a result we would have gotten infeasibility */
9142  /* adjust lhs and right hand side */
9143  newlhs = consdata->lhs - minleftactivitypart;
9144  newrhs = consdata->rhs - maxleftactivitypart;
9145 
9146  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
9147  {
9148  SCIPdebugMsg(scip, "linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
9149  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9150  ++(*nchgsides);
9151  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
9152  }
9153  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
9154  {
9155  SCIPdebugMsg(scip, "linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
9156  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9157  ++(*nchgsides);
9158  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
9159  }
9160  ++i;
9161  }
9162  }
9163 
9164  return SCIP_OKAY;
9165 }
9166 
9167 /* processes equality with only one variable by fixing the variable and deleting the constraint */
9168 static
9170  SCIP* scip, /**< SCIP data structure */
9171  SCIP_CONS* cons, /**< linear constraint */
9172  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9173  int* nfixedvars, /**< pointer to count number of fixed variables */
9174  int* ndelconss /**< pointer to count number of deleted constraints */
9175  )
9176 {
9177  SCIP_CONSDATA* consdata;
9178  SCIP_VAR* var;
9179  SCIP_Real val;
9180  SCIP_Real fixval;
9181  SCIP_Bool infeasible;
9182  SCIP_Bool fixed;
9183 
9184  assert(scip != NULL);
9185  assert(cons != NULL);
9186  assert(cutoff != NULL);
9187  assert(nfixedvars != NULL);
9188  assert(ndelconss != NULL);
9189 
9190  consdata = SCIPconsGetData(cons);
9191  assert(consdata != NULL);
9192  assert(consdata->nvars == 1);
9193  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9194 
9195  /* calculate the value to fix the variable to */
9196  var = consdata->vars[0];
9197  val = consdata->vals[0];
9198  assert(!SCIPisZero(scip, val));
9199  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
9200  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
9201  SCIPdebugMsg(scip, "linear equality <%s>: fix <%s> == %.15g\n",
9202  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
9203 
9204  /* fix variable */
9205  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
9206  if( infeasible )
9207  {
9208  SCIPdebugMsg(scip, " -> infeasible fixing\n");
9209  *cutoff = TRUE;
9210  return SCIP_OKAY;
9211  }
9212  if( fixed )
9213  (*nfixedvars)++;
9214 
9215  /* disable constraint */
9216  SCIP_CALL( SCIPdelCons(scip, cons) );
9217  if( !consdata->upgraded )
9218  (*ndelconss)++;
9219 
9220  return SCIP_OKAY;
9221 }
9222 
9223 /* processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
9224 static
9226  SCIP* scip, /**< SCIP data structure */
9227  SCIP_CONS* cons, /**< linear constraint */
9228  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9229  int* naggrvars, /**< pointer to count number of aggregated variables */
9230  int* ndelconss /**< pointer to count number of deleted constraints */
9231  )
9232 {
9233  SCIP_CONSDATA* consdata;
9234  SCIP_Bool infeasible;
9235  SCIP_Bool redundant;
9236  SCIP_Bool aggregated;
9237 
9238  assert(scip != NULL);
9239  assert(cons != NULL);
9240  assert(cutoff != NULL);
9241  assert(naggrvars != NULL);
9242  assert(ndelconss != NULL);
9243 
9244  consdata = SCIPconsGetData(cons);
9245  assert(consdata != NULL);
9246  assert(consdata->nvars == 2);
9247  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9248 
9249  SCIPdebugMsg(scip, "linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
9250  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
9251  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
9252 
9253  /* aggregate the equality */
9254  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
9255  consdata->rhs, &infeasible, &redundant, &aggregated) );
9256 
9257  /* check for infeasibility of aggregation */
9258  if( infeasible )
9259  {
9260  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
9261  *cutoff = TRUE;
9262  return SCIP_OKAY;
9263  }
9264 
9265  /* count the aggregation */
9266  if( aggregated )
9267  (*naggrvars)++;
9268 
9269  /* delete the constraint, if it is redundant */
9270  if( redundant )
9271  {
9272  SCIP_CALL( SCIPdelCons(scip, cons) );
9273 
9274  if( !consdata->upgraded )
9275  (*ndelconss)++;
9276  }
9277 
9278  return SCIP_OKAY;
9279 }
9280 
9281 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
9282 static
9284  SCIP* scip, /**< SCIP data structure */
9285  SCIP_CONSDATA* consdata, /**< linear constraint data */
9286  SCIP_VAR* slackvar, /**< variable to be aggregated out */
9287  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
9288  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
9289  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
9290  )
9291 {
9292  SCIP_Real slackvarlb;
9293  SCIP_Real slackvarub;
9294 
9295  assert(scip != NULL);
9296  assert(consdata != NULL);
9297  assert(newlhs != NULL);
9298  assert(newrhs != NULL);
9299  assert(!SCIPisInfinity(scip, -consdata->lhs));
9300  assert(!SCIPisInfinity(scip, consdata->rhs));
9301 
9302  slackvarlb = SCIPvarGetLbGlobal(slackvar);
9303  slackvarub = SCIPvarGetUbGlobal(slackvar);
9304  if( slackcoef > 0.0 )
9305  {
9306  if( SCIPisInfinity(scip, -slackvarlb) )
9307  *newrhs = SCIPinfinity(scip);
9308  else
9309  *newrhs = consdata->rhs - slackcoef * slackvarlb;
9310  if( SCIPisInfinity(scip, slackvarub) )
9311  *newlhs = -SCIPinfinity(scip);
9312  else
9313  *newlhs = consdata->lhs - slackcoef * slackvarub;
9314  }
9315  else
9316  {
9317  if( SCIPisInfinity(scip, -slackvarlb) )
9318  *newlhs = -SCIPinfinity(scip);
9319  else
9320  *newlhs = consdata->rhs - slackcoef * slackvarlb;
9321  if( SCIPisInfinity(scip, slackvarub) )
9322  *newrhs = SCIPinfinity(scip);
9323  else
9324  *newrhs = consdata->lhs - slackcoef * slackvarub;
9325  }
9326  assert(SCIPisLE(scip, *newlhs, *newrhs));
9327 }
9328 
9329 #define MAXMULTIAGGRQUOTIENT 1e+03
9330 
9331 /* processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
9332  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
9333  * is implicitly integral by this constraint
9334  *
9335  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
9336  * can help.
9337  */
9338 static
9340  SCIP* scip, /**< SCIP data structure */
9341  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
9342  SCIP_CONS* cons, /**< linear constraint */
9343  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9344  int* naggrvars, /**< pointer to count number of aggregated variables */
9345  int* ndelconss /**< pointer to count number of deleted constraints */
9346  )
9347 {
9348  SCIP_CONSDATA* consdata;
9349  SCIP_VAR** vars;
9350  SCIP_Real* vals;
9351  SCIP_VARTYPE bestslacktype;
9352  SCIP_VARTYPE slacktype;
9353  SCIP_Real lhs;
9354  SCIP_Real rhs;
9355  SCIP_Real bestslackdomrng;
9356  SCIP_Real minabsval;
9357  SCIP_Real maxabsval;
9358  SCIP_Bool bestremovescons;
9359  SCIP_Bool coefszeroone;
9360  SCIP_Bool coefsintegral;
9361  SCIP_Bool varsintegral;
9362  SCIP_Bool infeasible;
9363  SCIP_Bool samevar;
9364  int supinf; /* counter for infinite contributions to the supremum of a possible
9365  * multi-aggregation
9366  */
9367  int infinf; /* counter for infinite contributions to the infimum of a possible
9368  * multi-aggregation
9369  */
9370  int maxnlocksstay;
9371  int maxnlocksremove;
9372  int bestslackpos;
9373  int bestnlocks;
9374  int ncontvars;
9375  int contvarpos;
9376  int nintvars;
9377  int nimplvars;
9378  int intvarpos;
9379  int v;
9380 
9381  assert(scip != NULL);
9382  assert(cons != NULL);
9383  assert(cutoff != NULL);
9384  assert(naggrvars != NULL);
9385 
9386  consdata = SCIPconsGetData(cons);
9387  assert(consdata != NULL);
9388  assert(consdata->nvars > 2);
9389  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9390 
9391  SCIPdebugMsg(scip, "linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
9392 
9393  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
9394  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
9395  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
9396  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
9397  */
9398  lhs = consdata->lhs;
9399  rhs = consdata->rhs;
9400  maxnlocksstay = 0;
9401  if( consdata->nvars == 3 )
9402  {
9403  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
9404  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
9405  */
9406  maxnlocksremove = 3;
9407  }
9408  else if( consdata->nvars == 4 )
9409  {
9410  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
9411  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
9412  */
9413  maxnlocksremove = 2;
9414  }
9415  else
9416  {
9417  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
9418  maxnlocksremove = 1;
9419  }
9420 
9421  /* the locks on this constraint can be ignored */
9422  if( SCIPconsIsChecked(cons) )
9423  {
9424  if( !SCIPisInfinity(scip, -lhs) )
9425  {
9426  maxnlocksstay++;
9427  maxnlocksremove++;
9428  }
9429  if( !SCIPisInfinity(scip, rhs) )
9430  {
9431  maxnlocksstay++;
9432  maxnlocksremove++;
9433  }
9434  }
9435 
9436  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
9437  vars = consdata->vars;
9438  vals = consdata->vals;
9439  bestslackpos = -1;
9440  bestslacktype = SCIP_VARTYPE_BINARY;
9441  bestnlocks = INT_MAX;
9442  bestremovescons = FALSE;
9443  bestslackdomrng = 0.0;
9444  coefszeroone = TRUE;
9445  coefsintegral = TRUE;
9446  varsintegral = TRUE;
9447  ncontvars = 0;
9448  contvarpos = -1;
9449  nintvars = 0;
9450  nimplvars = 0;
9451  intvarpos = -1;
9452  minabsval = SCIPinfinity(scip);
9453  maxabsval = -1.0;
9454  for( v = 0; v < consdata->nvars; ++v )
9455  {
9456  SCIP_VAR* var;
9457  SCIP_Real val;
9458  SCIP_Real absval;
9459  SCIP_Real varlb;
9460  SCIP_Real varub;
9461  SCIP_Bool iscont;
9462  int nlocks;
9463 
9464  assert(vars != NULL);
9465  assert(vals != NULL);
9466 
9467  var = vars[v];
9468  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDown(var) >= 1); /* because variable is locked in this equality */
9469  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUp(var) >= 1);
9470  varlb = SCIPvarGetLbGlobal(var);
9471  varub = SCIPvarGetUbGlobal(var);
9472 
9473  val = vals[v];
9474  absval = REALABS(val);
9475  assert(SCIPisPositive(scip, absval));
9476 
9477  /* calculate minimal and maximal absolute value */
9478  if( absval < minabsval )
9479  minabsval = absval;
9480  if( absval > maxabsval )
9481  maxabsval = absval;
9482 
9483  /* do not try to multi aggregate, when numerical bad */
9484  if( maxabsval / minabsval > MAXMULTIAGGRQUOTIENT )
9485  return SCIP_OKAY;
9486 
9487  slacktype = SCIPvarGetType(var);
9488  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
9489  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
9490  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
9491  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
9492 
9493  /* update candidates for continuous -> implint and integer -> implint conversion */
9494  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
9495  {
9496  ncontvars++;
9497  contvarpos = v;
9498  }
9499  else if( slacktype == SCIP_VARTYPE_IMPLINT )
9500  {
9501  ++nimplvars;
9502  }
9503  else if( slacktype == SCIP_VARTYPE_INTEGER )
9504  {
9505  nintvars++;
9506  intvarpos = v;
9507  }
9508 
9509  /* check, if variable is already fixed or aggregated */
9510  if( !SCIPvarIsActive(var) )
9511  continue;
9512 
9513  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
9514  nlocks = SCIPvarGetNLocksDown(var) + SCIPvarGetNLocksUp(var);
9515 
9516  if( nlocks > maxnlocksremove )
9517  continue;
9518 
9519  /* check, if variable can be used as a slack variable */
9520  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
9521  !SCIPdoNotMultaggrVar(scip, var) )
9522  {
9523  SCIP_Bool better;
9524  SCIP_Bool equal;
9525  SCIP_Real slackdomrng;
9526 
9527  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
9528  slackdomrng = SCIPinfinity(scip);
9529  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
9530  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
9531  return SCIP_OKAY;
9532  else
9533  {
9534  slackdomrng = (varub - varlb)*absval;
9535  assert(!SCIPisInfinity(scip, slackdomrng));
9536  }
9537  equal = FALSE;
9538  better = (slacktype > bestslacktype) || (bestslackpos == -1);
9539  if( !better && slacktype == bestslacktype )
9540  {
9541  better = (nlocks < bestnlocks);
9542  if( nlocks == bestnlocks && !bestremovescons )
9543  {
9544  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
9545  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
9546  }
9547  }
9548 
9549  if( better || equal )
9550  {
9551  SCIP_Real minresactivity;
9552  SCIP_Real maxresactivity;
9553  SCIP_Real newlhs;
9554  SCIP_Real newrhs;
9555  SCIP_Bool removescons;
9556  SCIP_Bool minisrelax;
9557  SCIP_Bool maxisrelax;
9558  SCIP_Bool isminsettoinfinity;
9559  SCIP_Bool ismaxsettoinfinity;
9560 
9561  /* check if the constraint becomes redundant after multi-aggregation */
9562  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
9563  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9564 
9565  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
9566  * activity
9567  */
9568  if( minisrelax || maxisrelax )
9569  continue;
9570 
9571  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
9572  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9573 
9574  /* check resactivities for reliability */
9575  if( removescons )
9576  {
9577  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
9578  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
9579 
9580  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
9581  && SCIPisFeasLE(scip, newlhs, minresactivity))
9582  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
9583 
9584  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
9585  }
9586 
9587  /* if parameter multaggrremove is set to TRUE, only aggregate when this removes constraint */
9588  if( conshdlrdata->multaggrremove && !removescons )
9589  continue;
9590 
9591  /* prefer variables that make the constraints redundant */
9592  if( bestremovescons && !removescons )
9593  continue;
9594 
9595  /* if the constraint does not become redundant, only accept the variable if it does not appear in
9596  * other constraints
9597  */
9598  if( !removescons && nlocks > maxnlocksstay )
9599  continue;
9600 
9601  better = better || (!bestremovescons && removescons);
9602  if( better )
9603  {
9604  bestslackpos = v;
9605  bestslacktype = slacktype;
9606  bestnlocks = nlocks;
9607  bestslackdomrng = slackdomrng;
9608  bestremovescons = removescons;
9609  }
9610  }
9611  }
9612  }
9613 
9614  /* if all coefficients and variables are integral, the right hand side must also be integral */
9615  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
9616  {
9617  SCIPdebugMsg(scip, "linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
9618  SCIPdebugPrintCons(scip, cons, NULL);
9619  *cutoff = TRUE;
9620  return SCIP_OKAY;
9621  }
9622 
9623  supinf = 0;
9624  infinf = 0;
9625  samevar = FALSE;
9626 
9627  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
9628  for( v = 0; v < consdata->nvars; ++v )
9629  {
9630  if( v != bestslackpos )
9631  {
9632  if( SCIPisPositive(scip, consdata->vals[v]) )
9633  {
9634  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9635  {
9636  ++supinf;
9637  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9638  {
9639  ++infinf;
9640  samevar = TRUE;
9641  }
9642  }
9643  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9644  ++infinf;
9645 
9646  }
9647  else if( SCIPisNegative(scip, consdata->vals[v]) )
9648  {
9649  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
9650  {
9651  ++supinf;
9652  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9653  {
9654  ++infinf;
9655  samevar = TRUE;
9656  }
9657  }
9658  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
9659  ++infinf;
9660  }
9661  }
9662  }
9663  assert(!samevar || (supinf > 0 && infinf > 0));
9664 
9665  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
9666  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
9667  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
9668  {
9669  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
9670  return SCIP_OKAY;
9671  }
9672 
9673  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
9674  * we cannot aggregate the variable, because the integrality condition would get lost
9675  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
9676  * loose the integrality condition for this variable.
9677  */
9678  if( bestslackpos >= 0
9679  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
9680  || (coefsintegral && varsintegral && nimplvars == 0)) )
9681  {
9682  SCIP_VAR* slackvar;
9683  SCIP_Real* scalars;
9684  SCIP_Real slackcoef;
9685  SCIP_Real aggrconst;
9686  SCIP_Real newlhs;
9687  SCIP_Real newrhs;
9688  SCIP_Bool aggregated;
9689 
9690  /* we found a slack variable that only occurs in at most one other constraint:
9691  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
9692  */
9693  assert(bestslackpos < consdata->nvars);
9694 
9695  /* do not multi aggregate binary variables */
9696  if( SCIPvarIsBinary(vars[bestslackpos]) )
9697  return SCIP_OKAY;
9698 
9699  /* convert equality into inequality by deleting the slack variable:
9700  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
9701  */
9702  slackvar = vars[bestslackpos];
9703  slackcoef = vals[bestslackpos];
9704  assert(!SCIPisZero(scip, slackcoef));
9705  aggrconst = consdata->rhs/slackcoef;
9706 
9707  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
9708  assert(SCIPisLE(scip, newlhs, newrhs));
9709  SCIP_CALL( chgLhs(scip, cons, newlhs) );
9710  SCIP_CALL( chgRhs(scip, cons, newrhs) );
9711  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
9712 
9713  /* allocate temporary memory */
9714  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
9715 
9716  /* set up the multi-aggregation */
9717  SCIPdebugMsg(scip, "linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
9718  for( v = 0; v < consdata->nvars; ++v )
9719  {
9720  scalars[v] = -consdata->vals[v]/slackcoef;
9721  SCIPdebugMsgPrint(scip, " %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
9722  }
9723  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
9724  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
9725  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
9726 
9727  /* perform the multi-aggregation */
9728  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
9729  &infeasible, &aggregated) );
9730  assert(aggregated);
9731 
9732  /* free temporary memory */
9733  SCIPfreeBufferArray(scip, &scalars);
9734 
9735  /* check for infeasible aggregation */
9736  if( infeasible )
9737  {
9738  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
9739  *cutoff = TRUE;
9740  return SCIP_OKAY;
9741  }
9742 
9743  (*naggrvars)++;
9744 
9745  /* delete the constraint if it became redundant */
9746  if( bestremovescons )
9747  {
9748  SCIPdebugMsg(scip, "linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
9749  SCIP_CALL( SCIPdelCons(scip, cons) );
9750 
9751  if( !consdata->upgraded )
9752  (*ndelconss)++;
9753  }
9754  }
9755  else if( ncontvars == 1 )
9756  {
9757  SCIP_VAR* var;
9758 
9759  assert(0 <= contvarpos && contvarpos < consdata->nvars);
9760  var = vars[contvarpos];
9761  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
9762 
9763  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
9764  {
9765  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
9766  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
9767  {
9768  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
9769  SCIPdebugMsg(scip, "linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
9770  SCIPconsGetName(cons), SCIPvarGetName(var));
9771  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
9772  if( infeasible )
9773  {
9774  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9775  *cutoff = TRUE;
9776 
9777  return SCIP_OKAY;
9778  }
9779  }
9780  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
9781  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
9782  else if( !SCIPdoNotAggr(scip) )
9783  {
9784  SCIP_VAR* newvar;
9785  SCIP_Real absval;
9786  char newvarname[SCIP_MAXSTRLEN];
9787  SCIP_Bool redundant;
9788  SCIP_Bool aggregated;
9789 
9790  absval = REALABS(vals[contvarpos]);
9791 
9792  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
9793 
9794  /* create new implicit variable for aggregation */
9795  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
9797 
9798  /* add new variable to problem */
9799  SCIP_CALL( SCIPaddVar(scip, newvar) );
9800 
9801 #ifdef SCIP_DEBUG_SOLUTION
9802  if( SCIPdebugIsMainscip(scip) )
9803  {
9804  SCIP_Real varval;
9805  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
9806  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
9807  }
9808 #endif
9809 
9810  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
9811  SCIPdebugMsg(scip, "linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
9812  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
9813 
9814  /* aggregate continuous and implicit variable */
9815  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
9816 
9817  if( infeasible )
9818  {
9819  SCIPdebugMsg(scip, "infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
9820  SCIPvarGetName(var), SCIPvarGetName(newvar));
9821  *cutoff = TRUE;
9822 
9823  /* release implicit variable */
9824  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
9825 
9826  return SCIP_OKAY;
9827  }
9828 
9829  if( aggregated )
9830  (*naggrvars)++;
9831 
9832  /* release implicit variable */
9833  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
9834  }
9835 
9836  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
9837  * again
9838  */
9839  consdata->boundstightened = 0;
9840  consdata->rangedrowpropagated = 0;
9841  consdata->presolved = FALSE;
9842  }
9843  }
9844  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
9845  {
9846  SCIP_VAR* var;
9847 
9848  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
9849  * -> we don't convert integers into implints if the row is a 0/1-row
9850  */
9851  assert(varsintegral);
9852  assert(0 <= intvarpos && intvarpos < consdata->nvars);
9853  var = vars[intvarpos];
9854  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
9855 
9856  if( coefsintegral
9857  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
9858  && SCIPisFeasIntegral(scip, consdata->rhs) )
9859  {
9860  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
9861  SCIPdebugMsg(scip, "linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
9862  SCIPconsGetName(cons), SCIPvarGetName(var));
9863  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
9864  if( infeasible )
9865  {
9866  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
9867  *cutoff = TRUE;
9868 
9869  return SCIP_OKAY;
9870  }
9871  }
9872  }
9873 
9874  return SCIP_OKAY;
9875 }
9876 
9877 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
9878 static
9880  SCIP* scip, /**< SCIP data structure */
9881  SCIP_CONSDATA* consdata, /**< linear constraint data */
9882  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
9883  * objective function */
9884  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
9885  * this constraint */
9886  )
9887 {
9888  SCIP_VAR** vars;
9889  SCIP_VAR* var;
9890  SCIP_Real objval;
9891  SCIP_Bool negated;
9892  int nvars;
9893  int v;
9894 
9895  vars = consdata->vars;
9896  nvars = consdata->nvars;
9897 
9898  assert(vars != NULL);
9899 
9900  for( v = 0; v < nvars; ++v )
9901  {
9902  negated = FALSE;
9903  var = vars[v];
9904  assert(var != NULL);
9905 
9906  if( SCIPvarIsNegated(var) )
9907  {
9908  negated = TRUE;
9909  var = SCIPvarGetNegatedVar(var);
9910  assert(var != NULL);
9911  }
9912 
9913  objval = SCIPvarGetObj(var);
9914 
9915  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
9916  * function
9917  */
9918  if( SCIPisZero(scip, objval) )
9919  return FALSE;
9920  else
9921  {
9922  SCIP_Real val;
9923 
9924  val = consdata->vals[v];
9925 
9926  if( negated )
9927  {
9928  if( v == 0 )
9929  {
9930  /* the first variable defines the scale */
9931  (*scale) = val / -objval;
9932 
9933  (*offset) += val;
9934  }
9935  else if( SCIPisEQ(scip, -objval * (*scale), val) )
9936  (*offset) += val;
9937  else
9938  return FALSE;
9939  }
9940  else if( v == 0 )
9941  {
9942  /* the first variable defines the scale */
9943  (*scale) = val / objval;
9944  }
9945  else if( !SCIPisEQ(scip, objval * (*scale), val) )
9946  return FALSE;
9947  }
9948  }
9949 
9950  return TRUE;
9951 }
9952 
9953 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
9954  * objective coefficients and add an objective offset
9955  */
9956 static
9958  SCIP* scip, /**< SCIP data structure */
9959  SCIP_CONS* cons, /**< linear equation constraint */
9960  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
9961  )
9962 {
9963  SCIP_CONSDATA* consdata;
9964  SCIP_Real offset;
9965  SCIP_Real scale;
9966  SCIP_Bool applicable;
9967  int nobjvars;
9968  int nvars;
9969  int v;
9970 
9971  assert(scip != NULL);
9972  assert(cons != NULL);
9973  assert(conshdlrdata != NULL);
9975  consdata = SCIPconsGetData(cons);
9976  assert(consdata != NULL);
9977  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
9978 
9979  nvars = consdata->nvars;
9980  nobjvars = SCIPgetNObjVars(scip);
9981 
9982  /* check if the linear equality constraints does not have more variables than the objective function */
9983  if( nvars > nobjvars || nvars == 0 )
9984  return SCIP_OKAY;
9985 
9986  /* check for allowance of algorithm */
9987  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
9988  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
9989  return SCIP_OKAY;
9990 
9991  offset = consdata->rhs;
9992  scale = 1.0;
9993 
9994  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
9995  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
9996 
9997  if( applicable )
9998  {
9999  SCIP_VAR** vars;
10000 
10001  vars = consdata->vars;
10002  assert(vars != NULL);
10003 
10004  offset /= scale;
10005 
10006  SCIPdebugMsg(scip, "linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
10007  SCIPconsGetName(cons), consdata->rhs, offset);
10008 
10009  /* set all objective coefficient to zero */
10010  for( v = 0; v < nvars; ++v )
10011  {
10012  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
10013  }
10014 
10015  /* add an objective offset */
10016  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
10017  }
10018 
10019  return SCIP_OKAY;
10020 }
10021 
10022 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
10023 static
10025  SCIP* scip, /**< SCIP data structure */
10026  SCIP_CONS* cons, /**< constraint */
10027  SCIP_Real primalbound /**< feasible primal bound */
10028  )
10029 {
10030  SCIP_Real cutoffbound;
10031 
10032  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
10033  * accepted
10034  */
10035  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
10036 
10037  if( cutoffbound < SCIPgetCutoffbound(scip) )
10038  {
10039  SCIPdebugMsg(scip, "update cutoff bound <%g>\n", cutoffbound);
10040 
10041  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
10042  }
10043  else
10044  {
10045  SCIP_CONSDATA* consdata;
10046 
10047  consdata = SCIPconsGetData(cons);
10048  assert(consdata != NULL);
10049 
10050  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
10051  * resulted from one side
10052  */
10053  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
10054  {
10055  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
10056  * propagation
10057  */
10058  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
10059  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
10060  }
10061  }
10062 
10063  return SCIP_OKAY;
10064 }
10065 
10066 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
10067  * constraint enters the LP by setting the initial and separated flag to FALSE
10068  */
10069 static
10071  SCIP* scip, /**< SCIP data structure */
10072  SCIP_CONS* cons, /**< linear constraint */
10073  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
10074  )
10075 {
10076  SCIP_CONSDATA* consdata;
10077  SCIP_Real offset;
10078  SCIP_Real scale;
10079  SCIP_Bool applicable;
10080  int nobjvars;
10081  int nvars;
10082 
10083  assert(scip != NULL);
10084  assert(cons != NULL);
10085  assert(conshdlrdata != NULL);
10086 
10087  consdata = SCIPconsGetData(cons);
10088  assert(consdata != NULL);
10089 
10090  /* ignore equalities since these are covered by the method checkPartialObjective() */
10091  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10092  return SCIP_OKAY;
10093 
10094  nvars = consdata->nvars;
10095  nobjvars = SCIPgetNObjVars(scip);
10096 
10097  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
10098  * initial and/or separated flag is set to FALSE
10099  */
10100  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
10101  return SCIP_OKAY;
10102 
10103  offset = 0.0;
10104  scale = 1.0;
10105 
10106  /* There are no variables in the ojective function and in the constraint. Thus, the constraint is redundant or proves
10107  * infeasibility. Since we have a pure feasibility problem, we do not want to set a cutoff or lower bound.
10108  */
10109  if( nobjvars == 0 )
10110  return SCIP_OKAY;
10111 
10112  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
10113  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
10114 
10115  if( applicable )
10116  {
10117  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
10118  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
10119 
10120  if( SCIPisPositive(scip, scale) )
10121  {
10122  if( conshdlrdata->detectcutoffbound && rhsfinite )
10123  {
10124  SCIP_Real primalbound;
10125 
10126  primalbound = (consdata->rhs - offset) / scale;
10127 
10128  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10129  SCIPconsGetName(cons), primalbound);
10130 
10131  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10132  }
10133 
10134  if( conshdlrdata->detectlowerbound && lhsfinite )
10135  {
10136  SCIP_Real lowerbound;
10137 
10138  lowerbound = (consdata->lhs - offset) / scale;
10139 
10140  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10141  SCIPconsGetName(cons), lowerbound);
10142 
10143  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10144  }
10145 
10146  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
10147  (conshdlrdata->detectlowerbound && !rhsfinite) )
10148  {
10149  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10150  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10151  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10152  }
10153  }
10154  else
10155  {
10156  if( conshdlrdata->detectlowerbound && rhsfinite )
10157  {
10158  SCIP_Real lowerbound;
10159 
10160  lowerbound = (consdata->rhs - offset) / scale;
10161 
10162  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
10163  SCIPconsGetName(cons), lowerbound);
10164 
10165  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
10166  }
10167 
10168  if( conshdlrdata->detectcutoffbound && lhsfinite )
10169  {
10170  SCIP_Real primalbound;
10171 
10172  primalbound = (consdata->lhs - offset) / scale;
10173 
10174  SCIPdebugMsg(scip, "constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
10175  SCIPconsGetName(cons), primalbound);
10176 
10177  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
10178  }
10179 
10180  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
10181  (conshdlrdata->detectlowerbound && !lhsfinite) )
10182  {
10183  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
10184  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
10185  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
10186  }
10187  }
10188  }
10189 
10190  return SCIP_OKAY;
10191 }
10192 
10193 /** converts special equalities */
10194 static
10196  SCIP* scip, /**< SCIP data structure */
10197  SCIP_CONS* cons, /**< linear constraint */
10198  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
10199  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10200  int* nfixedvars, /**< pointer to count number of fixed variables */
10201  int* naggrvars, /**< pointer to count number of aggregated variables */
10202  int* ndelconss /**< pointer to count number of deleted constraints */
10203  )
10204 {
10205  SCIP_CONSDATA* consdata;
10206 
10207  assert(scip != NULL);
10208  assert(cons != NULL);
10209  assert(conshdlrdata != NULL);
10210  assert(cutoff != NULL);
10211  assert(nfixedvars != NULL);
10212  assert(naggrvars != NULL);
10213  assert(ndelconss != NULL);
10214 
10215  consdata = SCIPconsGetData(cons);
10216  assert(consdata != NULL);
10217  assert(consdata->removedfixings);
10218 
10219  /* do nothing on inequalities */
10220  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
10221  return SCIP_OKAY;
10222 
10223  /* depending on the number of variables, call a special conversion method */
10224  if( consdata->nvars == 1 )
10225  {
10226  /* fix variable */
10227  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
10228  }
10229  else if( consdata->nvars == 2 )
10230  {
10231  /* aggregate one of the variables */
10232  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
10233  }
10234  else
10235  {
10236  /* check if the equality is part of the objective function */
10237  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
10238 
10239  /* try to multi-aggregate one of the variables */
10240  SCIP_CALL( convertLongEquality(scip, conshdlrdata, cons, cutoff, naggrvars, ndelconss) );
10241  }
10242 
10243  return SCIP_OKAY;
10244 }
10245 
10246 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
10247  * integral
10248  */
10249 static
10251  SCIP* scip, /**< SCIP data structure */
10252  SCIP_CONSDATA* consdata, /**< linear constraint */
10253  int pos, /**< position of variable to be left out */
10254  SCIP_Real val /**< value to divide the coefficients by */
10255  )
10256 {
10257  int v;
10258 
10259  assert(scip != NULL);
10260  assert(consdata != NULL);
10261  assert(0 <= pos && pos < consdata->nvars);
10262 
10263  for( v = 0; v < consdata->nvars; ++v )
10264  {
10265  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
10266  return FALSE;
10267  }
10268 
10269  return TRUE;
10270 }
10271 
10272 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
10273  * check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
10274  */
10275 static
10277  SCIP* scip, /**< SCIP data structure */
10278  SCIP_Real side, /**< lhs or rhs */
10279  SCIP_Real val, /**< coefficient */
10280  SCIP_Real minresactivity, /**< minimal residual activity */
10281  SCIP_Real maxresactivity, /**< maximal residual activity */
10282  SCIP_Real* minval, /**< pointer to store calculated minval */
10283  SCIP_Real* maxval /**< pointer to store calculated maxval */
10284  )
10285 {
10286  assert(scip != NULL);
10287  assert(minval != NULL);
10288  assert(maxval != NULL);
10289 
10290  if( val > 0.0 )
10291  {
10292  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10293  *minval = -maxresactivity;
10294  else
10295  *minval = (side - maxresactivity)/val;
10296 
10297  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10298  *maxval = -minresactivity;
10299  else
10300  *maxval = (side - minresactivity)/val;
10301  }
10302  else
10303  {
10304  if( SCIPisInfinity(scip, ABS(minresactivity)) )
10305  *minval = minresactivity;
10306  else
10307  *minval = (side - minresactivity)/val;
10308 
10309  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
10310  *maxval = maxresactivity;
10311  else
10312  *maxval = (side - maxresactivity)/val;
10313  }
10314 }
10315 
10316 
10317 /* applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
10318  * linear inequality
10319  */
10320 static
10322  SCIP* scip, /**< SCIP data structure */
10323  SCIP_CONS* cons, /**< linear constraint */
10324  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10325  int* nfixedvars, /**< pointer to count number of fixed variables */
10326  int* naggrvars, /**< pointer to count number of aggregated variables */
10327  int* ndelconss /**< pointer to count number of deleted constraints */
10328  )
10329 {
10330  SCIP_CONSDATA* consdata;
10331  SCIP_Bool lhsexists;
10332  SCIP_Bool rhsexists;
10333  SCIP_Bool bestisint;
10334  SCIP_Bool bestislhs;
10335  int bestpos;
10336  int i;
10337  int maxotherlocks;
10339  assert(scip != NULL);
10340  assert(cons != NULL);
10341  assert(cutoff != NULL);
10342  assert(nfixedvars != NULL);
10343  assert(naggrvars != NULL);
10344  assert(ndelconss != NULL);
10345 
10346  /* only process checked constraints (for which the locks are increased);
10347  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
10348  * dualfix presolver
10349  */
10350  if( !SCIPconsIsChecked(cons) )
10351  return SCIP_OKAY;
10352 
10353  consdata = SCIPconsGetData(cons);
10354  assert(consdata != NULL);
10355 
10356  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
10357  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
10358 
10359  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
10360  * can use it safely for aggregation and break the search loop
10361  */
10362  bestpos = -1;
10363  bestisint = TRUE;
10364  bestislhs = FALSE;
10365 
10366  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
10367  * everything else would produce fill-in. Exceptions:
10368  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
10369  * produced.
10370  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
10371  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
10372  * six nonzeros (two variables per substitution).
10373  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
10374  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
10375  * six nonzeros (three variables per substitution). God exists!
10376  */
10377  if( consdata->nvars <= 2 )
10378  maxotherlocks = INT_MAX;
10379  else if( consdata->nvars == 3 )
10380  maxotherlocks = 3;
10381  else if( consdata->nvars == 4 )
10382  maxotherlocks = 2;
10383  else
10384  maxotherlocks = 1;
10385 
10386  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
10387  if( lhsexists && rhsexists && maxotherlocks < INT_MAX )
10388  maxotherlocks++;
10389 
10390  for( i = 0; i < consdata->nvars && bestisint; ++i )
10391  {
10392  SCIP_VAR* var;
10393  SCIP_Bool isint;
10394  SCIP_Real val;
10395  SCIP_Real obj;
10396  SCIP_Real lb;
10397  SCIP_Real ub;
10398  SCIP_Bool agglhs;
10399  SCIP_Bool aggrhs;
10400 
10401  var = consdata->vars[i];
10403 
10404  /* if we already found a candidate, skip integers */
10405  if( bestpos >= 0 && isint )
10406  continue;
10407 
10408  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
10409  * active, fixed, or single-aggregated with another binary variable
10410  */
10411  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
10412  continue;
10413 
10414  if ( SCIPdoNotMultaggrVar(scip, var) )
10415  continue;
10416 
10417  val = consdata->vals[i];
10418  obj = SCIPvarGetObj(var);
10419  lb = SCIPvarGetLbGlobal(var);
10420  ub = SCIPvarGetUbGlobal(var);
10421 
10422  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
10423  *
10424  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
10425  * - constraint is the only one that forbids fixing the variable to its lower bound
10426  * - 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
10427  *
10428  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
10429  * - constraint is the only one that forbids fixing the variable to its upper bound
10430  * - 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
10431  *
10432  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
10433  * - constraint is the only one that forbids fixing the variable to its upper bound
10434  * - 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
10435  *
10436  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
10437  * - constraint is the only one that forbids fixing the variable to its lower bound
10438  * - 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
10439  *
10440  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
10441  * of all x_j
10442  * furthermore: we only want to apply this, if no fill-in will be produced
10443  */
10444  agglhs = lhsexists
10445  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDown(var) == 1
10446  && SCIPvarGetNLocksUp(var) <= maxotherlocks)
10447  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUp(var) == 1
10448  && SCIPvarGetNLocksDown(var) <= maxotherlocks));
10449  aggrhs = rhsexists
10450  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUp(var) == 1
10451  && SCIPvarGetNLocksDown(var) <= maxotherlocks)
10452  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDown(var) == 1
10453  && SCIPvarGetNLocksUp(var) <= maxotherlocks));
10454  if( agglhs || aggrhs )
10455  {
10456  SCIP_Real minresactivity;
10457  SCIP_Real maxresactivity;
10458  SCIP_Real minval;
10459  SCIP_Real maxval;
10460  SCIP_Bool minisrelax;
10461  SCIP_Bool maxisrelax;
10462  SCIP_Bool isminsettoinfinity;
10463  SCIP_Bool ismaxsettoinfinity;
10464 
10465  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
10466  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
10467  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
10468  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10469 
10470  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
10471  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
10472  * This is needed, because we do not want to rely on relaxed finite resactivities.
10473  */
10474  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
10475 
10476  if( agglhs )
10477  {
10478  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10479  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10480 
10481  assert(SCIPisLE(scip, minval, maxval));
10482  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10483  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10484  {
10485  SCIP_Real oldmaxresactivity;
10486  SCIP_Real oldminresactivity;
10487  SCIP_Bool recalculated;
10488 
10489  recalculated = FALSE;
10490  oldmaxresactivity = maxresactivity;
10491  oldminresactivity = minresactivity;
10492 
10493  /* check minresactivity for reliability */
10494  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10495  {
10496  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10497  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10498  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
10499  }
10500 
10501  /* check maxresactivity for reliability */
10502  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10503  {
10504  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10505  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10506  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
10507  }
10508 
10509  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10510  if( recalculated )
10511  {
10512  assert(SCIPisLE(scip, minresactivity, maxresactivity));
10513 
10514  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10515  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
10516 
10517  assert(SCIPisLE(scip, minval, maxval));
10518  }
10519 
10520  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10521  {
10522  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10523  * in the multi-aggregation
10524  */
10525  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10526  {
10527  bestpos = i;
10528  bestisint = isint;
10529  bestislhs = TRUE;
10530  continue; /* no need to also look at the right hand side */
10531  }
10532  }
10533  }
10534  }
10535 
10536  if( aggrhs )
10537  {
10538  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10539  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10540 
10541  assert(SCIPisLE(scip,minval,maxval));
10542  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
10543  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
10544  {
10545  SCIP_Real oldmaxresactivity;
10546  SCIP_Real oldminresactivity;
10547  SCIP_Bool recalculated;
10548 
10549  recalculated = FALSE;
10550  oldmaxresactivity = maxresactivity;
10551  oldminresactivity = minresactivity;
10552 
10553  /* check minresactivity for reliability */
10554  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
10555  {
10556  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
10557  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
10558  }
10559 
10560  /* check maxresactivity for reliability */
10561  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
10562  {
10563  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
10564  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
10565  }
10566 
10567  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
10568  if( recalculated )
10569  {
10570  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
10571  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
10572  assert(SCIPisLE(scip,minval,maxval));
10573  }
10574 
10575  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
10576  {
10577  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
10578  * in the multi-aggregation
10579  */
10580  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
10581  {
10582  bestpos = i;
10583  bestisint = isint;
10584  bestislhs = FALSE;
10585  }
10586  }
10587  }
10588  }
10589  }
10590  }
10591 
10592  if( bestpos >= 0 )
10593  {
10594  SCIP_VAR** aggrvars;
10595  SCIP_Real* aggrcoefs;
10596  SCIP_Real aggrconst;
10597  SCIP_VAR* bestvar;
10598  SCIP_Real bestval;
10599  SCIP_Real epsilon;
10600  int naggrs;
10601  int j;
10602  SCIP_Bool infeasible;
10603  SCIP_Bool aggregated;
10604  SCIP_Bool samevar;
10605  int supinf; /* counter for infinite contributions to the supremum of a possible
10606  * multi-aggregation
10607  */
10608  int infinf; /* counter for infinite contributions to the infimum of a possible
10609  * multi-aggregation
10610  */
10611 
10612  assert(!bestislhs || lhsexists);
10613  assert(bestislhs || rhsexists);
10614 
10615  bestvar = consdata->vars[bestpos];
10616  bestval = consdata->vals[bestpos];
10617  assert(bestisint ==
10619 
10620  /* allocate temporary memory */
10621  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
10622  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
10623 
10624  /* set up the multi-aggregation */
10625  SCIPdebugPrintCons(scip, cons, NULL);
10626  SCIPdebugMsg(scip, "linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
10627  naggrs = 0;
10628  supinf = 0;
10629  infinf = 0;
10630  samevar = FALSE;
10631  epsilon = SCIPepsilon(scip);
10632 
10633  for( j = 0; j < consdata->nvars; ++j )
10634  {
10635  if( j != bestpos )
10636  {
10637  SCIP_Real absaggrcoef;
10638 
10639  aggrvars[naggrs] = consdata->vars[j];
10640  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
10641  SCIPdebugMsgPrint(scip, " %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
10642 
10643  absaggrcoef = REALABS(aggrcoefs[naggrs]);
10644 
10645  /* do not try to multi aggregate, when numerical bad */
10646  if( absaggrcoef < epsilon )
10647  {
10648  SCIPdebugMsg(scip, "do not perform multi-aggregation: too large aggregation coefficients\n");
10649 
10650  /* free temporary memory */
10651  SCIPfreeBufferArray(scip, &aggrcoefs);
10652  SCIPfreeBufferArray(scip, &aggrvars);
10653 
10654  return SCIP_OKAY;
10655  }
10656 
10657  if( bestisint )
10658  {
10659  /* coefficient must be integral: round it to exact integral value */
10660  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
10661  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
10662  }
10663 
10664  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
10665  {
10666  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10667  {
10668  ++supinf;
10669  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10670  {
10671  ++infinf;
10672  samevar = TRUE;
10673  }
10674  }
10675  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10676  ++infinf;
10677  }
10678  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
10679  {
10680  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
10681  {
10682  ++supinf;
10683  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10684  {
10685  ++infinf;
10686  samevar = TRUE;
10687  }
10688  }
10689  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
10690  ++infinf;
10691  }
10692 
10693  naggrs++;
10694  }
10695  }
10696  assert(!samevar || (supinf > 0 && infinf > 0));
10697 
10698  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
10699  SCIPdebugMsgPrint(scip, " %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
10700  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
10701  assert(naggrs == consdata->nvars-1);
10702 
10703  /* right hand side must be integral: round it to exact integral value */
10704  if( bestisint )
10705  {
10706  assert(SCIPisIntegral(scip, aggrconst));
10707  aggrconst = SCIPfloor(scip, aggrconst+0.5);
10708  }
10709 
10710  aggregated = FALSE;
10711  infeasible = FALSE;
10712 
10713  /* perform the multi-aggregation */
10714  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
10715  {
10716  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
10717  * also convertLongEquality() early termination due to coefficients
10718  */
10719  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
10720  }
10721  else
10722  {
10723  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
10724  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
10725  SCIPdebugMsg(scip, "do not perform multi-aggregation: infimum and supremum are both infinite\n");
10726  }
10727  /* free temporary memory */
10728  SCIPfreeBufferArray(scip, &aggrcoefs);
10729  SCIPfreeBufferArray(scip, &aggrvars);
10730 
10731  /* check for infeasible aggregation */
10732  if( infeasible )
10733  {
10734  SCIPdebugMsg(scip, "linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
10735  *cutoff = TRUE;
10736  return SCIP_OKAY;
10737  }
10738 
10739  /* delete the constraint, if the aggregation was successful */
10740  if( aggregated )
10741  {
10742  SCIP_CALL( SCIPdelCons(scip, cons) );
10743 
10744  if( !consdata->upgraded )
10745  (*ndelconss)++;
10746  (*naggrvars)++;
10747  }
10748  else
10749  {
10750  SCIPdebugMsg(scip, "aggregation non successful!\n");
10751  }
10752  }
10753 
10754  return SCIP_OKAY;
10755 }
10756 
10757 #define BINWEIGHT 1
10758 #define INTWEIGHT 4
10759 #define CONTWEIGHT 8
10760 
10761 /** gets weight for variable in a "weighted number of variables" sum */
10762 static
10763 int getVarWeight(
10764  SCIP_VAR* var /**< variable to get weight for */
10765  )
10766 {
10767  switch( SCIPvarGetType(var) )
10768  {
10769  case SCIP_VARTYPE_BINARY:
10770  return BINWEIGHT;
10771  case SCIP_VARTYPE_INTEGER:
10772  case SCIP_VARTYPE_IMPLINT:
10773  return INTWEIGHT;
10775  return CONTWEIGHT;
10776  default:
10777  SCIPerrorMessage("invalid variable type\n");
10778  SCIPABORT();
10779  return 0; /*lint !e527*/
10780  }
10781 }
10782 
10783 /** tries to aggregate variables in equations a^Tx = lhs
10784  * in case there are at most two binary variables with an odd coefficient and all other
10785  * variables are not continuous and have an even coefficient then:
10786  * - exactly one odd binary variables
10787  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
10788  * - lhs is odd -> y = 1
10789  * - lhs is even -> y = 0
10790  * - exactly two odd binary variables
10791  * aggregate the two binary variables with odd coefficient
10792  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
10793  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
10794  */
10795 static
10797  SCIP* scip, /**< SCIP data structure */
10798  SCIP_CONS* cons, /**< linear constraint */
10799  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
10800  int* nfixedvars, /**< pointer to count number of fixed variables */
10801  int* naggrvars, /**< pointer to count number of aggregated variables */
10802  int* ndelconss /**< pointer to count number of deleted constraints */
10803  )
10804 { /*lint --e{715}*/
10805  SCIP_CONSDATA* consdata;
10806  SCIP_Bool success;
10807 
10808  assert( scip != NULL );
10809  assert( cons != NULL );
10810 
10811  consdata = SCIPconsGetData(cons);
10812  assert( consdata != NULL );
10814  /* check if the linear constraint is an equation with integral right hand side */
10815  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
10816  return SCIP_OKAY;
10817 
10818  /* try to fix and aggregated variables until nothing is possible anymore */
10819  do
10820  {
10821  int v;
10822  int nvars;
10823  SCIP_VAR** vars;
10824  SCIP_Real* vals;
10825  SCIP_Real lhs;
10826  SCIP_Bool lhsodd;
10827 
10828  SCIP_Bool infeasible;
10829  SCIP_Bool fixed;
10830  SCIP_Bool aggregated;
10831  SCIP_Bool redundant;
10832 
10833  SCIP_VAR* var1;
10834  SCIP_VAR* var2;
10835  int noddvars;
10836 
10837  success = FALSE;
10838 
10839  lhs = consdata->lhs;
10840  vars = consdata->vars;
10841  vals = consdata->vals;
10842  nvars = consdata->nvars;
10843 
10844  assert( !SCIPisInfinity(scip, ABS(lhs)) );
10845 
10846  var1 = NULL;
10847  var2 = NULL;
10848  noddvars = 0;
10849 
10850  /* search for binary variables with an odd coefficient */
10851  for( v = 0; v < nvars && noddvars < 3; ++v )
10852  {
10853  SCIP_Longint val;
10854 
10855  /* all coefficients and variables have to be integral */
10856  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
10857  return SCIP_OKAY;
10858 
10859  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
10860  if( val % 2 != 0 )
10861  {
10862  /* the odd values have to belong to binary variables */
10863  if( !SCIPvarIsBinary(vars[v]) )
10864  return SCIP_OKAY;
10865 
10866  if( noddvars == 0 )
10867  var1 = vars[v];
10868  else
10869  var2 = vars[v];
10870 
10871  noddvars++;
10872  }
10873  }
10874 
10875  /* check lhs is odd or even */
10876  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
10877 
10878  if( noddvars == 1 )
10879  {
10880  assert( var1 != NULL );
10881 
10882  SCIPdebugMsg(scip, "linear constraint <%s>: try fixing variable <%s> to <%g>\n",
10883  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
10884 
10885  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
10886 
10887  /* check for infeasibility of fixing */
10888  if( infeasible )
10889  {
10890  SCIPdebugMsg(scip, " -> infeasible fixing\n");
10891  *cutoff = TRUE;
10892  return SCIP_OKAY;
10893  }
10894 
10895  if( fixed )
10896  {
10897  SCIPdebugMsg(scip, " -> feasible fixing\n");
10898  (*nfixedvars)++;
10899  success = TRUE;
10900  }
10901  }
10902  else if( noddvars == 2 )
10903  {
10904  assert( var1 != NULL );
10905  assert( var2 != NULL );
10906 
10907  /* aggregate the two variables with odd coefficient
10908  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
10909  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
10910  */
10911  SCIPdebugMsg(scip, "linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
10912  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
10913 
10914  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
10915  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
10916 
10917  /* check for infeasibility of aggregation */
10918  if( infeasible )
10919  {
10920  SCIPdebugMsg(scip, " -> infeasible aggregation\n");
10921  *cutoff = TRUE;
10922  return SCIP_OKAY;
10923  }
10924 
10925  /* count the aggregation */
10926  if( aggregated )
10927  {
10928  SCIPdebugMsg(scip, " -> feasible aggregation\n");
10929  (*naggrvars)++;
10930  success = TRUE;
10931  }
10932  }
10933 
10934  if( success )
10935  {
10936  /* apply fixings and aggregation to successfully rerun this presolving step */
10937  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
10938 
10939  if( infeasible )
10940  {
10941  SCIPdebugMsg(scip, " -> infeasible fixing\n");
10942  *cutoff = TRUE;
10943  return SCIP_OKAY;
10944  }
10945 
10946  /* normalize constraint */
10947  SCIP_CALL( normalizeCons(scip, cons) );
10948  }
10949  }
10950  while( success );
10951 
10952  return SCIP_OKAY;
10953 }
10954 
10955 
10956 
10957 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
10958  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
10959  * coefficients
10960  */
10961 static
10962 SCIP_DECL_SORTINDCOMP(consdataCompSim)
10963 { /*lint --e{715}*/
10964  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
10965  SCIP_VARTYPE vartype1;
10966  SCIP_VARTYPE vartype2;
10967  SCIP_Real value;
10968 
10969  assert(consdata != NULL);
10970  assert(0 <= ind1 && ind1 < consdata->nvars);
10971  assert(0 <= ind2 && ind2 < consdata->nvars);
10972 
10973  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
10974  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
10975 
10976  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
10977  {
10978  /* continuous varibles will be sorted to the back */
10979  if( vartype2 != vartype1 )
10980  return +1;
10981  /* both variables are continuous */
10982  else
10983  return 0;
10984  }
10985  /* continuous variables will be sorted to the back */
10986  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
10987  return -1;
10988 
10989  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
10990 
10991  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
10992  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
10993 }
10994 
10995 /** tries to simplify coefficients and delete variables in ranged row of the form lhs <= a^Tx <= rhs, e.g. using the greatest
10996  * common divisor
10997  *
10998  * 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
10999  * constraint to 1^Tx = 1
11000  */
11001 static
11003  SCIP* scip, /**< SCIP data structure */
11004  SCIP_CONS* cons, /**< linear constraint */
11005  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11006  int* nchgsides /**< pointer to store the amount of changed sides */
11007  )
11008 {
11009  SCIP_CONSDATA* consdata;
11010  SCIP_VAR** vars;
11011  SCIP_Real* vals;
11012  SCIP_Real minval;
11013  SCIP_Real secondminval;
11014  SCIP_Real maxval;
11015  SCIP_Real lhs;
11016  SCIP_Real rhs;
11017  int nvars;
11018  int v;
11020  /* we must not change a modifiable constraint in any way */
11021  if( SCIPconsIsModifiable(cons) )
11022  return SCIP_OKAY;
11023 
11024  if( SCIPconsIsDeleted(cons) )
11025  return SCIP_OKAY;
11026 
11027  consdata = SCIPconsGetData(cons);
11028  assert(consdata != NULL);
11029 
11030  nvars = consdata->nvars;
11031 
11032  /* do not check empty or bound-constraints */
11033  if( nvars < 2 )
11034  return SCIP_OKAY;
11035 
11036  vals = consdata->vals;
11037  vars = consdata->vars;
11038  assert(vars != NULL);
11039  assert(vals != NULL);
11040 
11041  lhs = consdata->lhs;
11042  rhs = consdata->rhs;
11043  assert(!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs));
11044  assert(!SCIPisNegative(scip, rhs));
11045 
11046  minval = SCIP_INVALID;
11047  secondminval = SCIP_INVALID;
11048  maxval = -SCIP_INVALID;
11049 
11050  for( v = nvars - 1; v >= 0; --v )
11051  {
11052  if( SCIPvarIsBinary(vars[v]) )
11053  {
11054  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
11055  {
11056  secondminval = minval;
11057  minval = vals[v];
11058  }
11059  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
11060  secondminval = vals[v];
11061 
11062  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
11063  maxval = vals[v];
11064  }
11065  else
11066  break;
11067  }
11068 
11069  /* check if all variables are binary */
11070  if( v == -1 )
11071  {
11072  if( SCIPisEQ(scip, minval, maxval) && SCIPisEQ(scip, lhs, rhs) )
11073  return SCIP_OKAY;
11074 
11075  /* check if we can and need to choose exactly one binary variable */
11076  if( SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) && SCIPisGT(scip, minval + secondminval, rhs) )
11077  {
11078  /* change all coefficients to 1.0 */
11079  for( v = nvars - 1; v >= 0; --v )
11080  {
11081  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
11082  }
11083  (*nchgcoefs) += nvars;
11084 
11085  /* replace old right and left hand side with 1.0 */
11086  SCIP_CALL( chgRhs(scip, cons, 1.0) );
11087  SCIP_CALL( chgLhs(scip, cons, 1.0) );
11088  (*nchgsides) += 2;
11089  }
11090  }
11091 
11092  return SCIP_OKAY;
11093 }
11094 
11095 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
11096  * for equations @see rangedRowSimplify() will be called
11097  *
11098  * there are several different coefficient reduction steps which will be applied
11099  *
11100  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
11101  *
11102  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
11103  *
11104  * 2. We try to remove redundant fractional parts in a constraint
11105  *
11106  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
11107  *
11108  * 3. We are using the greatest common divisor for further reductions
11109  *
11110  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
11111  * integral
11112  */
11113 static
11115  SCIP* scip, /**< SCIP data structure */
11116  SCIP_CONS* cons, /**< linear constraint */
11117  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
11118  int* nchgsides /**< pointer to store the amount of changed sides */
11119  )
11120 {
11121  SCIP_CONSDATA* consdata;
11122  SCIP_VAR** vars;
11123  SCIP_Real* vals;
11124  int* perm;
11125  SCIP_Real minactsub;
11126  SCIP_Real maxactsub;
11127  SCIP_Real siderest;
11128  SCIP_Real feastol;
11129  SCIP_Real newcoef;
11130  SCIP_Real absval;
11132  SCIP_Real lhs;
11133  SCIP_Real rhs;
11134  SCIP_Real lb;
11135  SCIP_Real ub;
11136  SCIP_Longint restcoef;
11137  SCIP_Longint oldgcd;
11138  SCIP_Longint rest;
11139  SCIP_Longint gcd;
11140  SCIP_Bool isminsettoinfinity;
11141  SCIP_Bool ismaxsettoinfinity;
11142  SCIP_Bool isminrelax;
11143  SCIP_Bool ismaxrelax;
11144  SCIP_Bool allcoefintegral;
11145  SCIP_Bool onlybin;
11146  SCIP_Bool hasrhs;
11147  SCIP_Bool haslhs;
11148  int oldnchgcoefs;
11149  int oldnchgsides;
11150  int foundbin;
11151  int candpos;
11152  int candpos2;
11153  int offsetv;
11154  int nvars;
11155  int v;
11156  int w;
11157 
11158  assert(scip != NULL);
11159  assert(cons != NULL);
11160  assert(nchgcoefs != NULL);
11161  assert(nchgsides != NULL);
11162 
11163  /* we must not change a modifiable constraint in any way */
11164  if( SCIPconsIsModifiable(cons) )
11165  return SCIP_OKAY;
11166 
11167  if( SCIPconsIsDeleted(cons) )
11168  return SCIP_OKAY;
11169 
11170  consdata = SCIPconsGetData(cons);
11171  assert(consdata != NULL);
11172 
11173  nvars = consdata->nvars;
11174 
11175  /* do not check empty or bound-constraints */
11176  if( nvars <= 2 )
11177  return SCIP_OKAY;
11178 
11179  /* update maximal activity delta if necessary */
11180  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
11181  consdataRecomputeMaxActivityDelta(scip, consdata);
11182 
11183  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
11184  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
11185  checkMaxActivityDelta(scip, consdata);
11186 
11187  /* @todo the following might be too hard, check which steps can be applied and what code must be corrected
11188  * accordingly
11189  */
11190  /* can only work with valid non-infinity activities per variable */
11191  if( SCIPisInfinity(scip, consdata->maxactdelta) )
11192  return SCIP_OKAY;
11193 
11194  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
11195  * but the eventsystem seems to be full
11196  */
11197  consdata->normalized = FALSE;
11198 
11199  /* normalize constraint */
11200  SCIP_CALL( normalizeCons(scip, cons) );
11201  assert(nvars == consdata->nvars);
11202 
11203  if( !consdata->normalized )
11204  return SCIP_OKAY;
11205 
11206  lhs = consdata->lhs;
11207  rhs = consdata->rhs;
11208  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
11209  assert(!SCIPisNegative(scip, rhs));
11210 
11211  if( !SCIPisInfinity(scip, -lhs) )
11212  haslhs = TRUE;
11213  else
11214  haslhs = FALSE;
11215 
11216  if( !SCIPisInfinity(scip, rhs) )
11217  hasrhs = TRUE;
11218  else
11219  hasrhs = FALSE;
11220 
11221  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
11222  SCIPdebug( oldnchgsides = *nchgsides; )
11223 
11224  /* @todo also work on ranged rows */
11225  if( haslhs && hasrhs )
11226  {
11227  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
11228 
11229  return SCIP_OKAY;
11230  }
11231  assert(haslhs != hasrhs);
11232 
11233  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
11234  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11235  assert(!haslhs || !SCIPisNegative(scip, lhs));
11236 
11237  /* get temporary memory to store the sorted permutation */
11238  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
11239 
11240  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
11241  * value of their coefficients
11242  */
11243  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
11244 
11245  /* perform sorting after permutation array */
11246  permSortConsdata(consdata, perm, nvars);
11247  consdata->sorted = FALSE;
11248  consdata->binvarssorted = FALSE;
11249 
11250  vars = consdata->vars;
11251  vals = consdata->vals;
11252  assert(vars != NULL);
11253  assert(vals != NULL);
11254  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
11255 
11256  /* free temporary memory */
11257  SCIPfreeBufferArray(scip, &perm);
11258 
11259  /* only check constraints with at least two non continuous variables */
11260  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
11261  return SCIP_OKAY;
11262 
11263  /* do not process constraints when all coefficients are 1.0 */
11264  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
11265  return SCIP_OKAY;
11266 
11267  feastol = SCIPfeastol(scip);
11268 
11269  SCIPdebugMsg(scip, "starting simplification of coefficients\n");
11270  SCIPdebugPrintCons(scip, cons, NULL);
11271 
11272  /* get global activities */
11273  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minactsub, &maxactsub,
11274  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11275 
11276  /* cannot work with infinite activities */
11277  if( isminsettoinfinity || ismaxsettoinfinity )
11278  return SCIP_OKAY;
11279 
11280  assert(!isminrelax);
11281  assert(!ismaxrelax);
11282  assert(maxactsub > minactsub);
11283  assert(!SCIPisInfinity(scip, -minactsub));
11284  assert(!SCIPisInfinity(scip, maxactsub));
11285 
11286  v = 0;
11287  offsetv = -1;
11288  side = haslhs ? lhs : rhs;
11289 
11290  /* we now determine coefficients as large as the side of the constraint to retrieve a better reduction where we
11291  * do not need to look at the large coefficients
11292  *
11293  * e.g. all x are binary, z are positive integer
11294  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
11295  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
11296  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
11297  *
11298  * can be changed to
11299  *
11300  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
11301  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
11302  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
11303  */
11304 
11305  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
11306  * hand side, we cannot apply the extra reduction step and need to reset v
11307  *
11308  * 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
11309  * coefficients due to the gcd on the "small" coefficients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
11310  * for all i is a solution
11311  *
11312  * also redundancy of variables would not be correctly determined in such a case
11313  */
11314  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
11315  {
11316  v = 1;
11317 
11318  while( v < nvars && SCIPisEQ(scip, side, vals[v]) )
11319  {
11320  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
11321  * extra step, which might have worked
11322  */
11323  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
11324  {
11325  v = 0;
11326  break;
11327  }
11328 
11329  ++v;
11330  }
11331 
11332  /* easy and quick fix: if all coefficients were equal to the side, we cannot apply further simplifications */
11333  /* todo find numerically stable normalization conditions to scale this cons to have coefficients almost equal to 1 */
11334  if( v == nvars )
11335  return SCIP_OKAY;
11336 
11337  /* cannot work with continuous variables which have a big coefficient */
11338  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
11339  return SCIP_OKAY;
11340 
11341  /* big negative coefficient, do not try to use the extra coefficient reduction step */
11342  if( SCIPisEQ(scip, side, -vals[v]) )
11343  v = 0;
11344 
11345  /* all but one variable are processed or the next variable is continuous we cannot perform the extra coefficient
11346  * reduction
11347  */
11348  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11349  v = 0;
11350 
11351  if( v > 0 )
11352  {
11353  assert(v < nvars);
11354 
11355  offsetv = v - 1;
11356 
11357  for( w = 0; w < v; ++w )
11358  {
11359  lb = SCIPvarGetLbGlobal(vars[w]);
11360  ub = SCIPvarGetUbGlobal(vars[w]);
11361 
11362  assert(vals[w] > 0);
11363 
11364  /* update residual activities */
11365  maxactsub -= ub * vals[w];
11366  minactsub -= lb * vals[w];
11367  assert(maxactsub > minactsub);
11368  }
11369  }
11370  }
11371 
11372  /* find and remove redundant variables which do not interact with the (in-)feasibility of this constraint
11373  *
11374  * e.g. let all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
11375  *
11376  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
11377  * to
11378  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
11379  */
11380  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
11381  {
11382  SCIP_Bool redundant = FALSE;
11383 
11384  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11385  assert(gcd >= 1);
11386 
11387  if( v == 0 )
11388  {
11389  lb = SCIPvarGetLbGlobal(vars[0]);
11390  ub = SCIPvarGetUbGlobal(vars[0]);
11391 
11392  /* update residual activities */
11393  if( vals[0] > 0 )
11394  {
11395  maxactsub -= ub * vals[0];
11396  minactsub -= lb * vals[0];
11397  }
11398  else
11399  {
11400  maxactsub -= lb * vals[0];
11401  minactsub -= ub * vals[0];
11402  }
11403  assert(maxactsub > minactsub);
11404  ++v;
11405  }
11406 
11407  siderest = -SCIP_INVALID;
11408  allcoefintegral = TRUE;
11409 
11410  /* check if some variables always fit into the given constraint */
11411  for( ; v < nvars - 1; ++v )
11412  {
11413  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11414  break;
11415 
11416  if( !SCIPisIntegral(scip, vals[v]) )
11417  {
11418  allcoefintegral = FALSE;
11419  break;
11420  }
11421 
11422  /* calculate greatest common divisor for all general and binary variables */
11423  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11424 
11425  if( gcd == 1 )
11426  break;
11427 
11428  lb = SCIPvarGetLbGlobal(vars[v]);
11429  ub = SCIPvarGetUbGlobal(vars[v]);
11430 
11431  assert(!SCIPisInfinity(scip, -lb));
11432  assert(!SCIPisInfinity(scip, ub));
11433 
11434  /* update residual activities */
11435  if( vals[v] > 0 )
11436  {
11437  maxactsub -= ub * vals[v];
11438  minactsub -= lb * vals[v];
11439  }
11440  else
11441  {
11442  maxactsub -= lb * vals[v];
11443  minactsub -= ub * vals[v];
11444  }
11445  assert(SCIPisGE(scip, maxactsub, minactsub));
11446 
11447  if( hasrhs )
11448  {
11449  /* determine the remainder of the right hand side and the gcd */
11450  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11451  }
11452  else
11453  {
11454  /* determine the remainder of the left hand side and the gcd */
11455  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11456  if( SCIPisZero(scip, siderest) )
11457  siderest = gcd;
11458  }
11459 
11460  /* early termination if the activities deceed the gcd */
11461  if( (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) || (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd) )
11462  {
11463  redundant = TRUE;
11464  break;
11465  }
11466  }
11467  assert(v < nvars || (offsetv >= 0 && gcd > 1));
11468 
11469  if( !redundant )
11470  {
11471  if( hasrhs )
11472  {
11473  /* determine the remainder of the right hand side and the gcd */
11474  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11475  }
11476  else
11477  {
11478  /* determine the remainder of the left hand side and the gcd */
11479  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11480  if( SCIPisZero(scip, siderest) )
11481  siderest = gcd;
11482  }
11483  }
11484  else
11485  ++v;
11486 
11487  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",
11488  v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
11489 
11490  /* check if we can remove redundant variables */
11491  if( v < nvars && (redundant ||
11492  (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) ||
11493  (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd)) )
11494  {
11495  SCIP_Real oldcoef;
11496 
11497  /* double check the redundancy */
11498 #ifndef NDEBUG
11499  SCIP_Real tmpminactsub = 0.0;
11500  SCIP_Real tmpmaxactsub = 0.0;
11501 
11502  /* recompute residual activities */
11503  for( w = v; w < nvars; ++w )
11504  {
11505  lb = SCIPvarGetLbGlobal(vars[w]);
11506  ub = SCIPvarGetUbGlobal(vars[w]);
11507 
11508  assert(!SCIPisInfinity(scip, -lb));
11509  assert(!SCIPisInfinity(scip, ub));
11510 
11511  /* update residual activities */
11512  if( vals[w] > 0 )
11513  {
11514  tmpmaxactsub += ub * vals[w];
11515  tmpminactsub += lb * vals[w];
11516  }
11517  else
11518  {
11519  tmpmaxactsub += lb * vals[w];
11520  tmpminactsub += ub * vals[w];
11521  }
11522  assert(tmpmaxactsub >= tmpminactsub);
11523  }
11524 
11525  if( hasrhs )
11526  {
11527  assert(offsetv == -1);
11528 
11529  /* determine the remainder of the right hand side and the gcd */
11530  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
11531  }
11532  else
11533  {
11534  /* determine the remainder of the left hand side and the gcd */
11535  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
11536  if( SCIPisZero(scip, siderest) )
11537  siderest = gcd;
11538  }
11539 
11540  /* does the redundancy really is fulfilled */
11541  assert((hasrhs && SCIPisLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) || (haslhs && tmpmaxactsub < siderest && SCIPisGE(scip, tmpminactsub, siderest - gcd)));
11542 #endif
11543 
11544  SCIPdebugMsg(scip, "removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n",
11545  nvars - v, SCIPconsGetName(cons));
11546 
11547  /* remove redundant variables */
11548  for( w = nvars - 1; w >= v; --w )
11549  {
11550  SCIP_CALL( delCoefPos(scip, cons, w) );
11551  }
11552  (*nchgcoefs) += (nvars - v);
11553 
11554  assert(w >= 0);
11555 
11556  oldcoef = vals[w];
11557 
11558  /* normalize constraint */
11559  SCIP_CALL( normalizeCons(scip, cons) );
11560  assert(vars == consdata->vars);
11561  assert(vals == consdata->vals);
11562  assert(w < consdata->nvars);
11563 
11564  /* compute new greatest common divisor due to normalization */
11565  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
11566  assert(gcd >= 1);
11567 
11568  /* update side */
11569  if( hasrhs )
11570  {
11571  /* replace old with new right hand side */
11572  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
11573  rhs = consdata->rhs;
11574  }
11575  else
11576  {
11577  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
11578  {
11579  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
11580  lhs = consdata->lhs;
11581  }
11582  else
11583  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
11584  }
11585  ++(*nchgsides);
11586 
11587  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11588  assert(!haslhs || !SCIPisNegative(scip, lhs));
11589 
11590  /* get new constraint data */
11591  nvars = consdata->nvars;
11592  assert(nvars >= 2);
11593 
11594  allcoefintegral = TRUE;
11595 
11596 #ifndef NDEBUG
11597  /* check integrality */
11598  for( w = offsetv + 1; w < nvars; ++w )
11599  {
11600  assert(SCIPisIntegral(scip, vals[w]));
11601  }
11602 #endif
11603  SCIPdebugPrintCons(scip, cons, NULL);
11604  }
11605 
11606  /* try to find a better gcd, when having large coefficients */
11607  if( offsetv >= 0 && gcd == 1 )
11608  {
11609  /* calculate greatest common divisor for all general variables */
11610  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
11611 
11612  if( gcd > 1 )
11613  {
11614  gcd = -1;
11615  candpos = -1;
11616 
11617  for( v = nvars - 1; v > offsetv; --v )
11618  {
11619  assert(!SCIPisZero(scip, vals[v]));
11620  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
11621  break;
11622 
11623  if( !SCIPisIntegral(scip, vals[v]) )
11624  {
11625  allcoefintegral = FALSE;
11626  break;
11627  }
11628 
11629  oldgcd = gcd;
11630 
11631  if( gcd == -1 )
11632  {
11633  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
11634  assert(gcd >= 1);
11635  }
11636  else
11637  {
11638  /* calculate greatest common divisor for all general and binary variables */
11639  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
11640  }
11641 
11642  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
11643  * can stop searching
11644  */
11645  if( gcd == 1 )
11646  {
11647  if( !SCIPvarIsBinary(vars[v]) )
11648  break;
11649 
11650  /* found candidate */
11651  if( candpos == -1 )
11652  {
11653  gcd = oldgcd;
11654  candpos = v;
11655  }
11656  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
11657  else
11658  break;
11659  }
11660  }
11661  assert(v > offsetv || candpos > offsetv);
11662  }
11663  else
11664  candpos = -1;
11665  }
11666  else
11667  candpos = nvars - 1;
11668 
11669  /* check last coefficient for integrality */
11670  if( gcd > 1 && allcoefintegral && !redundant )
11671  {
11672  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
11673  allcoefintegral = FALSE;
11674  }
11675 
11676  /* check for further necessary coefficient adjustments */
11677  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
11678  {
11679  assert(offsetv + 1 < nvars);
11680  assert(0 <= candpos && candpos < nvars);
11681 
11682  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
11683  {
11684  SCIP_Bool notchangable = FALSE;
11685 
11686 #ifndef NDEBUG
11687  /* check integrality */
11688  for( w = offsetv + 1; w < nvars; ++w )
11689  {
11690  assert(SCIPisIntegral(scip, vals[w]));
11691  }
11692 #endif
11693 
11694  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
11695  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
11696  {
11697  /* determine the remainder of the side and the gcd */
11698  if( hasrhs )
11699  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
11700  else
11701  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
11702  assert(rest >= 0);
11703  assert(rest < gcd);
11704 
11705  /* determine the remainder of the coefficient candidate and the gcd */
11706  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
11707  assert(restcoef >= 1);
11708  assert(restcoef < gcd);
11709 
11710  if( hasrhs )
11711  {
11712  /* calculate new coefficient */
11713  if( restcoef > rest )
11714  newcoef = vals[candpos] - restcoef + gcd;
11715  else
11716  newcoef = vals[candpos] - restcoef;
11717  }
11718  else
11719  {
11720  /* calculate new coefficient */
11721  if( rest == 0 || restcoef < rest )
11722  newcoef = vals[candpos] - restcoef;
11723  else
11724  newcoef = vals[candpos] - restcoef + gcd;
11725  }
11726 
11727 
11728  /* done */
11729 
11730  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
11731  * another with the big coefficient was set to 1
11732  */
11733  if( hasrhs && SCIPisZero(scip, newcoef) )
11734  {
11735  notchangable = TRUE;
11736  }
11737  else if( SCIPisZero(scip, newcoef) )
11738  {
11739  /* delete old redundant coefficient */
11740  SCIP_CALL( delCoefPos(scip, cons, candpos) );
11741  ++(*nchgcoefs);
11742  }
11743  else
11744  {
11745  /* replace old with new coefficient */
11746  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
11747  ++(*nchgcoefs);
11748  }
11749  }
11750  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
11751  {
11752  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
11753  }
11754 
11755  /* correct side and big coefficients */
11756  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
11757  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
11758  {
11759  if( haslhs )
11760  {
11761  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
11762 
11763  SCIP_CALL( chgLhs(scip, cons, newcoef) );
11764  ++(*nchgsides);
11765  }
11766  else
11767  {
11768  assert(hasrhs);
11769  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
11770 
11771  SCIP_CALL( chgRhs(scip, cons, newcoef) );
11772  ++(*nchgsides);
11773  }
11774 
11775  /* correct coefficients up front */
11776  for( w = offsetv; w >= 0; --w )
11777  {
11778  assert(vals[w] > 0);
11779 
11780  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
11781  }
11782  (*nchgcoefs) += (offsetv + 1);
11783  }
11784 
11785  if( !notchangable )
11786  {
11787  /* normalize constraint */
11788  SCIP_CALL( normalizeCons(scip, cons) );
11789  assert(vars == consdata->vars);
11790  assert(vals == consdata->vals);
11791 
11792  /* get new constraint data */
11793  nvars = consdata->nvars;
11794  assert(nvars >= 2);
11795 
11796  SCIPdebugPrintCons(scip, cons, NULL);
11797 
11798  lhs = consdata->lhs;
11799  rhs = consdata->rhs;
11800  assert(!hasrhs || !SCIPisNegative(scip, rhs));
11801  assert(!haslhs || !SCIPisNegative(scip, lhs));
11802  }
11803  }
11804  }
11805  }
11806 
11807  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
11808  /* no continuous variables are left over */
11809  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
11810  return SCIP_OKAY;
11811 
11812  onlybin = TRUE;
11813  allcoefintegral = TRUE;
11814  /* check if all variables are of binary type */
11815  for( v = nvars - 1; v >= 0; --v )
11816  {
11817  if( !SCIPvarIsBinary(vars[v]) )
11818  onlybin = FALSE;
11819  if( !SCIPisIntegral(scip, vals[v]) )
11820  allcoefintegral = FALSE;
11821  }
11822 
11823  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
11824  * hand side or bigger than the left hand side respectively, so we can make all of them integral
11825  *
11826  * @todo there are some steps missing ....
11827  */
11828  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
11829  {
11830  SCIP_Real val;
11831  SCIP_Real newval;
11832  SCIP_Real frac = 0.0;
11833  SCIP_Bool found = FALSE;
11834 
11835  if( hasrhs )
11836  {
11837  if( allcoefintegral )
11838  {
11839  /* replace old with new right hand side */
11840  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
11841  ++(*nchgsides);
11842  }
11843  else
11844  {
11845  siderest = rhs - SCIPfloor(scip, rhs);
11846 
11847  /* try to round down all non-integral coefficients */
11848  for( v = nvars - 1; v >= 0; --v )
11849  {
11850  val = vals[v];
11851 
11852  /* add up all possible fractional parts */
11853  if( !SCIPisIntegral(scip, val) )
11854  {
11855  lb = SCIPvarGetLbGlobal(vars[v]);
11856  ub = SCIPvarGetUbGlobal(vars[v]);
11857 
11858  /* at least one bound need to be at zero */
11859  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
11860  return SCIP_OKAY;
11861 
11862  /* swap bounds for 'standard' form */
11863  if( !SCIPisFeasZero(scip, lb) )
11864  {
11865  ub = lb;
11866  val *= -1;
11867  }
11868 
11869  found = TRUE;
11870 
11871  frac += (val - SCIPfloor(scip, val)) * ub;
11872 
11873  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
11874  *
11875  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
11876  * x3, x4 set to 1 would be infeasible but feasible after flooring
11877  */
11878  if( SCIPisGT(scip, frac, siderest) )
11879  return SCIP_OKAY;
11880  }
11881  }
11882  assert(v == -1);
11883 
11884  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the right hand side down\n");
11885 
11886  /* round rhs and coefficients to integral values */
11887  if( found )
11888  {
11889  for( v = nvars - 1; v >= 0; --v )
11890  {
11891  val = vals[v];
11892 
11893  /* add the whole fractional part */
11894  if( !SCIPisIntegral(scip, val) )
11895  {
11896  lb = SCIPvarGetLbGlobal(vars[v]);
11897 
11898  if( SCIPisFeasZero(scip, lb) )
11899  newval = SCIPfloor(scip, val);
11900  else
11901  newval = SCIPceil(scip, val);
11902 
11903  if( SCIPisZero(scip, newval) )
11904  {
11905  /* delete old redundant coefficient */
11906  SCIP_CALL( delCoefPos(scip, cons, v) );
11907  ++(*nchgcoefs);
11908  }
11909  else
11910  {
11911  /* replace old with new coefficient */
11912  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
11913  ++(*nchgcoefs);
11914  }
11915  }
11916  }
11917  }
11918 
11919  /* replace old with new right hand side */
11920  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
11921  ++(*nchgsides);
11922  }
11923  }
11924  else
11925  {
11926  if( allcoefintegral )
11927  {
11928  /* replace old with new left hand side */
11929  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
11930  ++(*nchgsides);
11931  }
11932  else
11933  {
11934  /* cannot floor left hand side to zero */
11935  if( SCIPisLT(scip, lhs, 1.0) )
11936  return SCIP_OKAY;
11937 
11938  siderest = lhs - SCIPfloor(scip, lhs);
11939 
11940  /* try to round down all non-integral coefficients */
11941  for( v = nvars - 1; v >= 0; --v )
11942  {
11943  val = vals[v];
11944 
11945  /* add up all possible fractional parts */
11946  if( !SCIPisIntegral(scip, val) )
11947  {
11948  lb = SCIPvarGetLbGlobal(vars[v]);
11949  ub = SCIPvarGetUbGlobal(vars[v]);
11950 
11951  /* at least one bound need to be at zero */
11952  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
11953  return SCIP_OKAY;
11954 
11955  /* swap bounds for 'standard' form */
11956  if( !SCIPisFeasZero(scip, lb) )
11957  {
11958  ub = lb;
11959  val *= -1;
11960  }
11961 
11962  /* cannot floor to zero */
11963  if( SCIPisLT(scip, val, 1.0) )
11964  return SCIP_OKAY;
11965 
11966  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
11967  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
11968  return SCIP_OKAY;
11969 
11970  found = TRUE;
11971 
11972  frac += (val - SCIPfloor(scip, val)) * ub;
11973 
11974  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
11975  * fractional parts of the variables, we cannot tighten the coefficients
11976  *
11977  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
11978  * x2-x4 set to 1 would be feasible but not after flooring
11979  */
11980  if( SCIPisGE(scip, frac, 1 + siderest) )
11981  return SCIP_OKAY;
11982  }
11983  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
11984  else
11985  return SCIP_OKAY;
11986  }
11987  assert(v == -1);
11988 
11989  SCIPdebugMsg(scip, "rounding all non-integral coefficients and the left hand side down\n");
11990 
11991  /* round lhs and coefficients to integral values */
11992  if( found )
11993  {
11994  for( v = nvars - 1; v >= 0; --v )
11995  {
11996  val = vals[v];
11997 
11998  /* add the whole fractional part */
11999  if( !SCIPisIntegral(scip, val) )
12000  {
12001  lb = SCIPvarGetLbGlobal(vars[v]);
12002 
12003  if( SCIPisFeasZero(scip, lb) )
12004  newval = SCIPfloor(scip, val);
12005  else
12006  newval = SCIPceil(scip, val);
12007 
12008  if( SCIPisZero(scip, newval) )
12009  {
12010  /* delete old redundant coefficient */
12011  SCIP_CALL( delCoefPos(scip, cons, v) );
12012  ++(*nchgcoefs);
12013  }
12014  else
12015  {
12016  /* replace old with new coefficient */
12017  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
12018  ++(*nchgcoefs);
12019  }
12020  }
12021  }
12022  }
12023 
12024  /* replace old with new left hand side */
12025  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
12026  ++(*nchgsides);
12027  }
12028  }
12029 
12030  /* normalize constraint */
12031  SCIP_CALL( normalizeCons(scip, cons) );
12032  assert(vars == consdata->vars);
12033  assert(vals == consdata->vals);
12034 
12035  rhs = consdata->rhs;
12036  lhs = consdata->lhs;
12037 
12038  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12039  assert(!haslhs || !SCIPisNegative(scip, lhs));
12040 
12041  SCIPdebugPrintCons(scip, cons, NULL);
12042 
12043  nvars = consdata->nvars;
12044  if( nvars < 2 )
12045  return SCIP_OKAY;
12046 
12047  allcoefintegral = TRUE;
12048 #ifndef NDEBUG
12049  /* debug check if all coefficients are really integral */
12050  for( v = nvars - 1; v >= 0; --v )
12051  assert(SCIPisIntegral(scip, vals[v]));
12052 #endif
12053  }
12054 
12055  /* @todo following can also work on non integral coefficients, need more investigation */
12056  /* only check constraints with integral coefficients on all integral variables */
12057  if( !allcoefintegral )
12058  return SCIP_OKAY;
12059 
12060  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
12061  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
12062  return SCIP_OKAY;
12063 
12064  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
12065  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
12066  return SCIP_OKAY;
12067 
12068  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
12069  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
12070  return SCIP_OKAY;
12071 
12072  assert(nvars >= 2);
12073 
12074  /* start gcd procedure for all variables */
12075  do
12076  {
12077  SCIPdebug( oldnchgcoefs = *nchgcoefs; )
12078  SCIPdebug( oldnchgsides = *nchgsides; )
12079 
12080  /* stop if we have two coeffcients which are one in absolute value */
12081  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
12082  return SCIP_OKAY;
12083 
12084  gcd = -1;
12085 
12086  /* calculate greatest common divisor over all integer variables */
12087  if( !onlybin )
12088  {
12089  foundbin = -1;
12090 
12091  for( v = nvars - 1; v >= 0; --v )
12092  {
12093  assert(!SCIPisZero(scip, vals[v]));
12094  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
12095 
12096  if( SCIPvarIsBinary(vars[v]) )
12097  {
12098  if( foundbin == -1 )
12099  foundbin = v;
12100  continue;
12101  }
12102 
12103  absval = REALABS(vals[v]);
12104  assert(SCIPisIntegral(scip, absval));
12105 
12106  if( gcd == -1 )
12107  {
12108  gcd = (SCIP_Longint)(absval + feastol);
12109  assert(gcd >= 1);
12110  }
12111  else
12112  {
12113  /* calculate greatest common divisor for all general variables */
12114  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
12115  }
12116  if( gcd == 1 )
12117  break;
12118  }
12119  }
12120  else
12121  foundbin = nvars - 1;
12122 
12123  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
12124  if( gcd == 1 || foundbin == -1)
12125  return SCIP_OKAY;
12126 
12127  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
12128 
12129  candpos = -1;
12130  candpos2 = -1;
12131 
12132  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
12133  * change the coefficient
12134  */
12135  for( v = foundbin; v >= 0; --v )
12136  {
12137  if( onlybin || SCIPvarIsBinary(vars[v]) )
12138  {
12139  absval = REALABS(vals[v]);
12140  assert(SCIPisIntegral(scip, absval));
12141 
12142  oldgcd = gcd;
12143 
12144  if( gcd == -1 )
12145  {
12146  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
12147  assert(gcd >= 1);
12148  }
12149  else
12150  {
12151  /* calculate greatest common divisor for all general and binary variables */
12152  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12153  }
12154 
12155  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
12156  * can terminate
12157  */
12158  if( gcd == 1 )
12159  {
12160  /* found candidate */
12161  if( candpos == -1 )
12162  {
12163  gcd = oldgcd;
12164  candpos = v;
12165 
12166  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
12167  * the coefficient change
12168  */
12169  if( onlybin && v == foundbin - 1 )
12170  candpos2 = foundbin;
12171  }
12172  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
12173  else
12174  {
12175  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
12176  {
12177  assert(candpos2 == nvars - 1);
12178 
12179  /* take new candidates */
12180  candpos = candpos2;
12181 
12182  /* recalculate gcd from scratch */
12183  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
12184  assert(gcd >= 1);
12185 
12186  /* calculate greatest common divisor for all general and binary variables */
12187  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
12188  if( gcd == 1 )
12189  return SCIP_OKAY;
12190  }
12191  else
12192  /* cannot determine a possible coefficient for reduction */
12193  return SCIP_OKAY;
12194  }
12195  }
12196  }
12197  }
12198  assert(gcd >= 2);
12199 
12200  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
12201  * further
12202  */
12203  assert(candpos >= 0 && candpos < nvars);
12204 
12205  /* all variables and all coefficients are integral, so the side should be too */
12206  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
12207 
12208  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
12209  * @see normalizeCons()
12210  */
12211  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12212  assert(!haslhs || !SCIPisNegative(scip, lhs));
12213 
12214  /* determine the remainder of the side and the gcd */
12215  if( hasrhs )
12216  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
12217  else
12218  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
12219  assert(rest >= 0);
12220  assert(rest < gcd);
12221 
12222  /* determine the remainder of the coefficient candidate and the gcd */
12223  if( vals[candpos] < 0 )
12224  {
12225  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
12226  assert(restcoef <= -1);
12227  restcoef += gcd;
12228  }
12229  else
12230  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
12231  assert(restcoef >= 1);
12232  assert(restcoef < gcd);
12233 
12234  if( hasrhs )
12235  {
12236  if( rest > 0 )
12237  {
12238  /* replace old with new right hand side */
12239  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
12240  ++(*nchgsides);
12241  }
12242 
12243  /* calculate new coefficient */
12244  if( restcoef > rest )
12245  newcoef = vals[candpos] - restcoef + gcd;
12246  else
12247  newcoef = vals[candpos] - restcoef;
12248  }
12249  else
12250  {
12251  if( rest > 0 )
12252  {
12253  /* replace old with new left hand side */
12254  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
12255  ++(*nchgsides);
12256  }
12257 
12258  /* calculate new coefficient */
12259  if( rest == 0 || restcoef < rest )
12260  newcoef = vals[candpos] - restcoef;
12261  else
12262  newcoef = vals[candpos] - restcoef + gcd;
12263  }
12264  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
12265 
12266  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));
12267 
12268  if( SCIPisZero(scip, newcoef) )
12269  {
12270  /* delete redundant coefficient */
12271  SCIP_CALL( delCoefPos(scip, cons, candpos) );
12272  }
12273  else
12274  {
12275  /* replace old with new coefficient */
12276  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
12277  }
12278  ++(*nchgcoefs);
12279 
12280  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
12281  SCIP_CALL( normalizeCons(scip, cons) );
12282  assert(vars == consdata->vars);
12283  assert(vals == consdata->vals);
12284 
12285  SCIPdebugPrintCons(scip, cons, NULL);
12286 
12287  rhs = consdata->rhs;
12288  lhs = consdata->lhs;
12289  assert(!hasrhs || !SCIPisNegative(scip, rhs));
12290  assert(!haslhs || !SCIPisNegative(scip, lhs));
12291 
12292  nvars = consdata->nvars;
12293 
12294  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));
12295  }
12296  while( nvars >= 2 );
12297 
12298  return SCIP_OKAY;
12299 }
12300 
12301 
12302 /* tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
12303  * cons0 := a * cons0 + b * cons1,
12304  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
12305  * for numerical stability, we will only accept integral a and b;
12306  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
12307  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
12308  */
12309 static
12311  SCIP* scip, /**< SCIP data structure */
12312  SCIP_CONS* cons0, /**< (in)equality to modify */
12313  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
12314  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
12315  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
12316  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
12317  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
12318  int nvarscommon, /**< number of variables, that appear in both constraints */
12319  int commonidxweight, /**< variable weight sum of common variables */
12320  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
12321  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
12322  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12323  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
12324  SCIP_Bool* aggregated /**< pointer to store whether an aggregation was made */
12325  )
12326 {
12327  SCIP_CONSDATA* consdata0;
12328  SCIP_CONSDATA* consdata1;
12329  SCIP_Real a;
12330  SCIP_Real b;
12331  SCIP_Real aggrcoef;
12332  SCIP_Real scalarsum;
12333  SCIP_Real bestscalarsum;
12334  SCIP_Bool betterscalarsum;
12335  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
12336  int varweight;
12337  int nvars;
12338  int bestvarweight;
12339  int bestnvars;
12340  int bestv;
12341  int v;
12342  int i;
12343 
12344  assert(scip != NULL);
12345  assert(cons0 != NULL);
12346  assert(cons1 != NULL);
12347  assert(commonidx0 != NULL);
12348  assert(commonidx1 != NULL);
12349  assert(diffidx0minus1 != NULL);
12350  assert(diffidx1minus0 != NULL);
12351  assert(nvarscommon >= 1);
12352  assert(commonidxweight >= nvarscommon);
12353  assert(nchgcoefs != NULL);
12354  assert(aggregated != NULL);
12355 
12356  assert(SCIPconsIsActive(cons0));
12357  assert(SCIPconsIsActive(cons1));
12358 
12359  SCIPdebugMsg(scip, "try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12360 
12361  /* cons0 is an (in)equality */
12362  consdata0 = SCIPconsGetData(cons0);
12363  assert(consdata0 != NULL);
12364  assert(consdata0->nvars >= 1);
12365  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
12366  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
12367 
12368  /* cons1 is an equality */
12369  consdata1 = SCIPconsGetData(cons1);
12370  assert(consdata1 != NULL);
12371  assert(consdata1->nvars >= 1);
12372  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
12373  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
12374 
12375  *aggregated = FALSE;
12376 
12377  /* search for the best common variable such that
12378  * val1[var] * consdata0 - val0[var] * consdata1
12379  * has least weighted number of variables
12380  */
12381  bestvarweight = commonidxweight + diffidx0minus1weight;
12382  bestnvars = consdata0->nvars;
12383  bestv = -1;
12384  bestscalarsum = 0.0;
12385  commonvarlindependent = TRUE;
12386  for( v = 0; v < nvarscommon; ++v )
12387  {
12388  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
12389  a = consdata1->vals[commonidx1[v]];
12390  b = -consdata0->vals[commonidx0[v]];
12391 
12392  /* only try aggregation, if coefficients are integral (numerical stability) */
12393  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
12394  {
12395  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
12396  varweight = diffidx0minus1weight + diffidx1minus0weight;
12397  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12398  scalarsum = REALABS(a) + REALABS(b);
12399  betterscalarsum = (scalarsum < bestscalarsum);
12400  for( i = 0; i < nvarscommon
12401  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
12402  {
12403  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12404  if( !SCIPisZero(scip, aggrcoef) )
12405  {
12406  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
12407  nvars++;
12408  }
12409  }
12410  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
12411  {
12412  bestv = v;
12413  bestvarweight = varweight;
12414  bestnvars = nvars;
12415  bestscalarsum = scalarsum;
12416  }
12417  }
12418 
12419  /* update commonvarlindependent flag, if still TRUE:
12420  * 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
12421  */
12422  if( commonvarlindependent && v > 0 )
12423  commonvarlindependent = SCIPisEQ(scip,
12424  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
12425  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
12426  }
12427 
12428  /* if better aggregation was found, create new constraint and delete old one */
12429  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
12430  {
12431  SCIP_CONS* newcons;
12432  SCIP_CONSDATA* newconsdata;
12433  SCIP_VAR** newvars;
12434  SCIP_Real* newvals;
12435  SCIP_Real newlhs;
12436  SCIP_Real newrhs;
12437  int newnvars;
12438 
12439  if( bestv != -1 )
12440  {
12441  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
12442  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
12443  {
12444  a = consdata1->vals[commonidx1[bestv]];
12445  b = -consdata0->vals[commonidx0[bestv]];
12446  }
12447  else
12448  {
12449  a = -consdata1->vals[commonidx1[bestv]];
12450  b = consdata0->vals[commonidx0[bestv]];
12451  }
12452  assert(SCIPisIntegral(scip, a));
12453  assert(SCIPisPositive(scip, a));
12454  assert(SCIPisIntegral(scip, b));
12455  assert(!SCIPisZero(scip, b));
12456  }
12457  else
12458  {
12459  assert(commonvarlindependent);
12460  if( consdata1->vals[commonidx1[0]] > 0.0 )
12461  {
12462  a = consdata1->vals[commonidx1[0]];
12463  b = -consdata0->vals[commonidx0[0]];
12464  }
12465  else
12466  {
12467  a = -consdata1->vals[commonidx1[0]];
12468  b = consdata0->vals[commonidx0[0]];
12469  }
12470  assert(SCIPisPositive(scip, a));
12471  assert(!SCIPisZero(scip, b));
12472 
12473  /* if a/b is integral, then we can easily choose integer multipliers */
12474  if( SCIPisIntegral(scip, a/b) )
12475  {
12476  if( a/b > 0 )
12477  {
12478  a /= b;
12479  b = 1.0;
12480  }
12481  else
12482  {
12483  a /= -b;
12484  b = -1.0;
12485  }
12486  }
12487 
12488  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
12489  SCIPdebug( bestvarweight = diffidx0minus1weight + diffidx1minus0weight; )
12490  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
12491  }
12492 
12493  SCIPdebugMsg(scip, "aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
12494  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
12495  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
12496  SCIPdebugPrintCons(scip, cons0, NULL);
12497  SCIPdebugPrintCons(scip, cons1, NULL);
12498 
12499  /* get temporary memory for creating the new linear constraint */
12500  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
12501  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
12502 
12503  /* calculate the common coefficients, if we have not recognized linear dependency */
12504  newnvars = 0;
12505  if( !commonvarlindependent )
12506  {
12507  for( i = 0; i < nvarscommon; ++i )
12508  {
12509  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12510  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12511 
12512  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12513  if( !SCIPisZero(scip, aggrcoef) )
12514  {
12515  assert(newnvars < bestnvars);
12516  newvars[newnvars] = consdata0->vars[commonidx0[i]];
12517  newvals[newnvars] = aggrcoef;
12518  newnvars++;
12519  }
12520  }
12521  }
12522  else
12523  {
12524  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
12525 #ifndef NDEBUG
12526  for( i = 0; i < nvarscommon; ++i )
12527  {
12528  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
12529  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
12530 
12531  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
12532  assert(SCIPisZero(scip, aggrcoef));
12533  }
12534 #endif
12535  }
12536 
12537  /* calculate the coefficients appearing in cons0 but not in cons1 */
12538  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
12539  {
12540  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
12541 
12542  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
12543  assert(!SCIPisZero(scip, aggrcoef));
12544  assert(newnvars < bestnvars);
12545  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
12546  newvals[newnvars] = aggrcoef;
12547  newnvars++;
12548  }
12549 
12550  /* calculate the coefficients appearing in cons1 but not in cons0 */
12551  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
12552  {
12553  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
12554 
12555  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
12556  assert(!SCIPisZero(scip, aggrcoef));
12557  assert(newnvars < bestnvars);
12558  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
12559  newvals[newnvars] = aggrcoef;
12560  newnvars++;
12561  }
12562  assert(newnvars == bestnvars);
12563 
12564  /* calculate the new left and right hand side of the (in)equality */
12565  assert(!SCIPisInfinity(scip, -consdata1->lhs));
12566  assert(!SCIPisInfinity(scip, consdata1->rhs));
12567  if( SCIPisInfinity(scip, -consdata0->lhs) )
12568  newlhs = -SCIPinfinity(scip);
12569  else
12570  newlhs = a * consdata0->lhs + b * consdata1->lhs;
12571  if( SCIPisInfinity(scip, consdata0->rhs) )
12572  newrhs = SCIPinfinity(scip);
12573  else
12574  newrhs = a * consdata0->rhs + b * consdata1->rhs;
12575 
12576  /* create the new linear constraint */
12577  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
12579  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
12580  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
12582 
12583  newconsdata = SCIPconsGetData(newcons);
12584  assert(newconsdata != NULL);
12585 
12586  /* copy the upgraded flag from the old cons0 to the new constraint */
12587  newconsdata->upgraded = consdata0->upgraded;
12588 
12589  /* normalize the new constraint */
12590  SCIP_CALL( normalizeCons(scip, newcons) );
12591 
12592  /* check, if we really want to use the new constraint instead of the old one:
12593  * use the new one, if the maximum norm doesn't grow too much
12594  */
12595  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
12596  {
12597  SCIPdebugMsg(scip, " -> aggregated to <%s>\n", SCIPconsGetName(newcons));
12598  SCIPdebugPrintCons(scip, newcons, NULL);
12599 
12600  /* update the statistics: we changed all coefficients */
12601  if( !consdata0->upgraded )
12602  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
12603  *aggregated = TRUE;
12604 
12605  /* delete the old constraint, and add the new linear constraint to the problem */
12606  SCIP_CALL( SCIPdelCons(scip, cons0) );
12607  SCIP_CALL( SCIPaddCons(scip, newcons) );
12608  }
12609 
12610  /* release the new constraint */
12611  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
12612 
12613  /* free temporary memory */
12614  SCIPfreeBufferArray(scip, &newvals);
12615  SCIPfreeBufferArray(scip, &newvars);
12616  }
12617 
12618  return SCIP_OKAY;
12619 }
12620 
12621 /** gets the key of the given element */
12622 static
12623 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
12624 { /*lint --e{715}*/
12625  /* the key is the element itself */
12626  return elem;
12627 }
12628 
12629 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
12630  * coefficients are either equal or negated
12631  */
12632 static
12633 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
12634 {
12635  SCIP* scip;
12636  SCIP_CONSDATA* consdata1;
12637  SCIP_CONSDATA* consdata2;
12638  SCIP_Bool coefsequal;
12639  SCIP_Bool coefsnegated;
12640  int i;
12641 
12642  assert(key1 != NULL);
12643  assert(key2 != NULL);
12644  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
12645  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
12646  assert(consdata1->sorted);
12647  assert(consdata2->sorted);
12648 
12649  scip = (SCIP*)userptr;
12650  assert(scip != NULL);
12651 
12652  /* checks trivial case */
12653  if( consdata1->nvars != consdata2->nvars )
12654  return FALSE;
12655 
12656  coefsequal = TRUE;
12657  coefsnegated = TRUE;
12658 
12659  for( i = 0; i < consdata1->nvars && (coefsequal || coefsnegated); ++i )
12660  {
12661  SCIP_Real val1;
12662  SCIP_Real val2;
12663 
12664  /* tests if variables are equal */
12665  if( consdata1->vars[i] != consdata2->vars[i] )
12666  {
12667  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
12668  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
12669  coefsequal = FALSE;
12670  coefsnegated = FALSE;
12671  break;
12672  }
12673  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
12674 
12675  /* tests if coefficients are either equal or negated */
12676  val1 = consdata1->vals[i];
12677  val2 = consdata2->vals[i];
12678  coefsequal = coefsequal && SCIPisEQ(scip, val1, val2);
12679  coefsnegated = coefsnegated && SCIPisEQ(scip, val1, -val2);
12680  }
12681 
12682  return (coefsequal || coefsnegated);
12683 }
12684 
12685 /** returns the hash value of the key */
12686 static
12687 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
12688 {
12689  SCIP_CONSDATA* consdata;
12690  int minidx;
12691  int mididx;
12692  int maxidx;
12693 #ifndef NDEBUG
12694  SCIP* scip;
12695 
12696  scip = (SCIP*)userptr;
12697  assert(scip != NULL);
12698 #endif
12699 
12700  assert(key != NULL);
12701  consdata = SCIPconsGetData((SCIP_CONS*)key);
12702  assert(consdata != NULL);
12703  assert(consdata->nvars > 0);
12705  assert(consdata->sorted);
12706 
12707  minidx = SCIPvarGetIndex(consdata->vars[0]);
12708  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
12709  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
12710  assert(minidx >= 0 && minidx <= maxidx);
12711 
12712  /* using only the variable indices as hash, since the values are compared by epsilon */
12713  return SCIPhashFour(SCIPcombineFourInt(consdata->nvars, minidx, mididx, maxidx),
12714  SCIPrealHashCode(consdata->vals[0], 8),
12715  SCIPrealHashCode(consdata->vals[consdata->nvars / 2], 8),
12716  SCIPrealHashCode(consdata->vals[consdata->nvars - 1], 8));
12717 }
12718 
12719 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
12720  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
12721  */
12722 static
12724  SCIP* scip, /**< SCIP data structure */
12725  BMS_BLKMEM* blkmem, /**< block memory */
12726  SCIP_CONS** conss, /**< constraint set */
12727  int nconss, /**< number of constraints in constraint set */
12728  int* firstchange, /**< pointer to store first changed constraint */
12729  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
12730  int* ndelconss, /**< pointer to count number of deleted constraints */
12731  int* nchgsides /**< pointer to count number of changed left/right hand sides */
12732  )
12733 {
12734  SCIP_HASHTABLE* hashtable;
12735  int hashtablesize;
12736  int c;
12737 
12738  assert(scip != NULL);
12739  assert(blkmem != NULL);
12740  assert(conss != NULL);
12741  assert(firstchange != NULL);
12742  assert(cutoff != NULL);
12743  assert(ndelconss != NULL);
12744  assert(nchgsides != NULL);
12745 
12746  /* create a hash table for the constraint set */
12747  hashtablesize = nconss;
12748  hashtablesize = MAX(hashtablesize, HASHSIZE_LINEARCONS);
12749  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
12750  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
12751 
12752  /* check all constraints in the given set for redundancy */
12753  for( c = 0; c < nconss; ++c )
12754  {
12755  SCIP_CONS* cons0;
12756  SCIP_CONS* cons1;
12757  SCIP_CONSDATA* consdata0;
12758 
12759  cons0 = conss[c];
12760 
12761  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
12762  continue;
12763 
12764  /* check for interuption */
12765  if( c % 1000 == 0 && SCIPisStopped(scip) )
12766  break;
12767 
12768  /* sorts the constraint */
12769  consdata0 = SCIPconsGetData(cons0);
12770  assert(consdata0 != NULL);
12771  SCIP_CALL( consdataSort(scip, consdata0) );
12772  assert(consdata0->sorted);
12773 
12774  /* get constraint from current hash table with same variables as cons0 and with coefficients either equal or negated
12775  * to the ones of cons0 */
12776  cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
12777 
12778  if( cons1 != NULL )
12779  {
12780  SCIP_CONS* consstay;
12781  SCIP_CONS* consdel;
12782  SCIP_CONSDATA* consdatastay;
12783  SCIP_CONSDATA* consdatadel;
12784  SCIP_CONSDATA* consdata1;
12785 
12786  SCIP_Real lhs;
12787  SCIP_Real rhs;
12788 
12789  assert(SCIPconsIsActive(cons1));
12790  assert(!SCIPconsIsModifiable(cons1));
12791 
12792  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
12793  * delete old constraints afterwards
12794  */
12795  consdata1 = SCIPconsGetData(cons1);
12796 
12797  assert(consdata1 != NULL);
12798  assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
12799 
12800  assert(consdata1->sorted);
12801  assert(consdata0->vars[0] == consdata1->vars[0]);
12802 
12803  if( SCIPisEQ(scip, consdata0->vals[0], consdata1->vals[0]) )
12804  {
12805  /* the coefficients of both constraints are equal */
12806  assert(consdata0->nvars < 2 || SCIPisEQ(scip, consdata0->vals[1], consdata1->vals[1]));
12807  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
12808  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12809  SCIPdebugPrintCons(scip, cons0, NULL);
12810  SCIPdebugPrintCons(scip, cons1, NULL);
12811 
12812  lhs = MAX(consdata1->lhs, consdata0->lhs);
12813  rhs = MIN(consdata1->rhs, consdata0->rhs);
12814  }
12815  else
12816  {
12817  /* the coefficients of both rows are negations */
12818  assert(SCIPisEQ(scip, consdata0->vals[0], -(consdata1->vals[0])));
12819  assert(consdata0->nvars < 2 || SCIPisEQ(scip, consdata0->vals[1], -(consdata1->vals[1])));
12820  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
12821  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
12822  SCIPdebugPrintCons(scip, cons0, NULL);
12823  SCIPdebugPrintCons(scip, cons1, NULL);
12824 
12825  lhs = MAX(consdata1->lhs, -consdata0->rhs);
12826  rhs = MIN(consdata1->rhs, -consdata0->lhs);
12827  }
12828 
12829  if( SCIPisFeasLT(scip, rhs, lhs) )
12830  {
12831  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons1));
12832  *cutoff = TRUE;
12833  break;
12834  }
12835 
12836  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
12837  if( lhs > rhs )
12838  {
12839  rhs = (lhs + rhs)/2;
12840  lhs = rhs;
12841  }
12842 
12843  /* check which constraint has to stay;
12844  * changes applied to an upgraded constraint will not be considered in the instance */
12845  if( consdata1->upgraded && !consdata0->upgraded )
12846  {
12847  /* the coefficients of both rows are negations, we need to switch lhs and rhs and multiply them with -1 */
12848  if( !SCIPisEQ(scip, consdata0->vals[0], consdata1->vals[0]) )
12849  {
12850  SCIP_Real tmp = lhs;
12851  lhs = -rhs;
12852  rhs = -tmp;
12853  }
12854 
12855  consstay = cons0;
12856  consdatastay = consdata0;
12857  consdel = cons1;
12858  consdatadel = consdata1;
12859 
12860  /* exchange consdel with consstay in hashtable */
12861  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) consdel) );
12862  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) consstay) );
12863  }
12864  else
12865  {
12866  consstay = cons1;
12867  consdatastay = consdata1;
12868  consdel = cons0;
12869  consdatadel = consdata0;
12870  }
12871 
12872  /* update lhs and rhs of consstay */
12873  SCIP_CALL( chgLhs(scip, consstay, lhs) );
12874  SCIP_CALL( chgRhs(scip, consstay, rhs) );
12875 
12876  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
12877  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
12878 
12879  /* delete consdel */
12880  assert( ! consdatastay->upgraded || consdatadel->upgraded );
12881  SCIP_CALL( SCIPdelCons(scip, consdel) );
12882  if( !consdatadel->upgraded )
12883  (*ndelconss)++;
12884 
12885  /* update the first changed constraint to begin the next aggregation round with */
12886  if( consdatastay->changed && SCIPconsGetPos(consstay) < *firstchange )
12887  *firstchange = SCIPconsGetPos(consstay);
12888 
12889  assert(SCIPconsIsActive(consstay));
12890  }
12891  else
12892  {
12893  /* no such constraint in current hash table: insert cons0 into hash table */
12894  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
12895  }
12896  }
12897 #ifdef SCIP_MORE_DEBUG
12898  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
12900 #endif
12901 
12902  /* free hash table */
12903  SCIPhashtableFree(&hashtable);
12904 
12905  return SCIP_OKAY;
12906 }
12907 
12908 /** compares constraint with all prior constraints for possible redundancy or aggregation,
12909  * and removes or changes constraint accordingly
12910  */
12911 static
12913  SCIP* scip, /**< SCIP data structure */
12914  SCIP_CONS** conss, /**< constraint set */
12915  int firstchange, /**< first constraint that changed since last pair preprocessing round */
12916  int chkind, /**< index of constraint to check against all prior indices upto startind */
12917  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
12918  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
12919  int* ndelconss, /**< pointer to count number of deleted constraints */
12920  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
12921  int* nchgcoefs /**< pointer to count number of changed coefficients */
12922  )
12923 {
12924  SCIP_CONS* cons0;
12925  SCIP_CONSDATA* consdata0;
12926  int* commonidx0;
12927  int* commonidx1;
12928  int* diffidx0minus1;
12929  int* diffidx1minus0;
12930  uint64_t possignature0;
12931  uint64_t negsignature0;
12932  SCIP_Bool cons0changed;
12933  SCIP_Bool cons0isequality;
12934  int diffidx1minus0size;
12935  int c;
12936  SCIP_Real cons0lhs;
12937  SCIP_Real cons0rhs;
12938  SCIP_Bool cons0upgraded;
12939 
12940  assert(scip != NULL);
12941  assert(conss != NULL);
12942  assert(firstchange <= chkind);
12943  assert(cutoff != NULL);
12944  assert(ndelconss != NULL);
12945  assert(nchgsides != NULL);
12946  assert(nchgcoefs != NULL);
12947 
12948  /* get the constraint to be checked against all prior constraints */
12949  cons0 = conss[chkind];
12950  assert(cons0 != NULL);
12951  assert(SCIPconsIsActive(cons0));
12952  assert(!SCIPconsIsModifiable(cons0));
12953 
12954  consdata0 = SCIPconsGetData(cons0);
12955  assert(consdata0 != NULL);
12956  assert(consdata0->nvars >= 1);
12957  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
12958 
12959  /* sort the constraint */
12960  SCIP_CALL( consdataSort(scip, consdata0) );
12961 
12962  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
12963  consdataCalcSignatures(consdata0);
12964  possignature0 = consdata0->possignature;
12965  negsignature0 = consdata0->negsignature;
12966 
12967  /* get temporary memory for indices of common variables */
12968  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
12969  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
12970  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
12971  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
12972  diffidx1minus0size = consdata0->nvars;
12973 
12974  cons0lhs = consdata0->lhs;
12975  cons0rhs = consdata0->rhs;
12976  cons0upgraded = consdata0->upgraded;
12977 
12978  /* check constraint against all prior constraints */
12979  cons0changed = consdata0->changed;
12980  consdata0->changed = FALSE;
12981  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
12982  {
12983  SCIP_CONS* cons1;
12984  SCIP_CONSDATA* consdata1;
12985  uint64_t possignature1;
12986  uint64_t negsignature1;
12987  SCIP_Bool cons0dominateslhs;
12988  SCIP_Bool cons1dominateslhs;
12989  SCIP_Bool cons0dominatesrhs;
12990  SCIP_Bool cons1dominatesrhs;
12991  SCIP_Bool cons1isequality;
12992  SCIP_Bool coefsequal;
12993  SCIP_Bool coefsnegated;
12994  SCIP_Bool tryaggregation;
12995  int nvarscommon;
12996  int nvars0minus1;
12997  int nvars1minus0;
12998  int commonidxweight;
12999  int diffidx0minus1weight;
13000  int diffidx1minus0weight;
13001  int v0;
13002  int v1;
13003 
13004  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
13005  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
13006  assert(cons0upgraded == consdata0->upgraded);
13007 
13008  cons1 = conss[c];
13009 
13010  /* cons1 has become inactive during presolving of constraint pairs */
13011  if( cons1 == NULL )
13012  continue;
13013 
13014  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
13015  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
13016 
13017  consdata1 = SCIPconsGetData(cons1);
13018  assert(consdata1 != NULL);
13019 
13020  /* SCIPdebugMsg(scip, "preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
13021  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
13022  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
13023 
13024  /* if both constraints didn't change since last pair processing, we can ignore the pair */
13025  if( !cons0changed && !consdata1->changed )
13026  continue;
13027 
13028  /* if both constraints are already upgraded, skip the pair;
13029  * because changes on these constraints cannot be applied to the instance anymore */
13030  if( cons0upgraded && consdata1->upgraded )
13031  continue;
13032 
13033  assert(consdata1->nvars >= 1);
13034 
13035  /* sort the constraint */
13036  SCIP_CALL( consdataSort(scip, consdata1) );
13037 
13038  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
13039  consdataCalcSignatures(consdata1);
13040  possignature1 = consdata1->possignature;
13041  negsignature1 = consdata1->negsignature;
13042 
13043  /* the signatures give a quick test to check for domination and equality of coefficients */
13044  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
13045  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
13046  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
13047  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13048  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13049  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
13050  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13051  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13052  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
13053  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
13054  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
13055  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
13056  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
13057  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
13058  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
13059  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
13060  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
13061  && !coefsequal && !coefsnegated && !tryaggregation )
13062  continue;
13063 
13064  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
13065  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
13066  {
13067  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
13068  diffidx1minus0size = consdata1->nvars;
13069  }
13070 
13071  /* check consdata0 against consdata1:
13072  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
13073  * consdata0 dominates consdata1 w.r.t. left hand side
13074  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
13075  * consdata0 dominates consdata1 w.r.t. right hand side
13076  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
13077  * ranged row (or equality)
13078  * - if at least one constraint is an equality, count the weighted number of common variables W_c
13079  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
13080  * where the weight of each variable depends on its type, such that aggregations in order to remove the
13081  * number of continuous and integer variables are preferred:
13082  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
13083  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
13084  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13085  * to be positive to not switch the sense of the (in)equality cons0
13086  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
13087  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
13088  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
13089  * to be positive to not switch the sense of the (in)equality cons1
13090  */
13091 
13092  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
13093  nvarscommon = 0;
13094  commonidxweight = 0;
13095  nvars0minus1 = 0;
13096  diffidx0minus1weight = 0;
13097  nvars1minus0 = 0;
13098  diffidx1minus0weight = 0;
13099  v0 = 0;
13100  v1 = 0;
13101  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
13102  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
13103  || coefsequal || coefsnegated || tryaggregation) )
13104  {
13105  SCIP_VAR* var;
13106  SCIP_Real val0;
13107  SCIP_Real val1;
13108  int varcmp;
13109 
13110  /* test, if variable appears in only one or in both constraints */
13111  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
13112  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
13113  else if( v0 < consdata0->nvars )
13114  varcmp = -1;
13115  else
13116  varcmp = +1;
13117 
13118  switch( varcmp )
13119  {
13120  case -1:
13121  /* variable doesn't appear in consdata1 */
13122  var = consdata0->vars[v0];
13123  val0 = consdata0->vals[v0];
13124  val1 = 0.0;
13125  if( tryaggregation )
13126  {
13127  diffidx0minus1[nvars0minus1] = v0;
13128  nvars0minus1++;
13129  diffidx0minus1weight += getVarWeight(var);
13130  }
13131  v0++;
13132  coefsequal = FALSE;
13133  coefsnegated = FALSE;
13134  break;
13135 
13136  case +1:
13137  /* variable doesn't appear in consdata0 */
13138  var = consdata1->vars[v1];
13139  val0 = 0.0;
13140  val1 = consdata1->vals[v1];
13141  if( tryaggregation )
13142  {
13143  diffidx1minus0[nvars1minus0] = v1;
13144  nvars1minus0++;
13145  diffidx1minus0weight += getVarWeight(var);
13146  }
13147  v1++;
13148  coefsequal = FALSE;
13149  coefsnegated = FALSE;
13150  break;
13151 
13152  case 0:
13153  /* variable appears in both constraints */
13154  assert(consdata0->vars[v0] == consdata1->vars[v1]);
13155  var = consdata0->vars[v0];
13156  val0 = consdata0->vals[v0];
13157  val1 = consdata1->vals[v1];
13158  if( tryaggregation )
13159  {
13160  commonidx0[nvarscommon] = v0;
13161  commonidx1[nvarscommon] = v1;
13162  nvarscommon++;
13163  commonidxweight += getVarWeight(var);
13164  }
13165  v0++;
13166  v1++;
13167  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
13168  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
13169  break;
13170 
13171  default:
13172  SCIPerrorMessage("invalid comparison result\n");
13173  SCIPABORT();
13174  var = NULL;
13175  val0 = 0.0;
13176  val1 = 0.0;
13177  }
13178  assert(var != NULL);
13179 
13180  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
13181  if( SCIPisGT(scip, val0, val1) )
13182  {
13183  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13184  {
13185  cons0dominatesrhs = FALSE;
13186  cons1dominateslhs = FALSE;
13187  }
13188  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13189  {
13190  cons0dominateslhs = FALSE;
13191  cons1dominatesrhs = FALSE;
13192  }
13193  }
13194  else if( SCIPisLT(scip, val0, val1) )
13195  {
13196  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
13197  {
13198  cons0dominateslhs = FALSE;
13199  cons1dominatesrhs = FALSE;
13200  }
13201  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
13202  {
13203  cons0dominatesrhs = FALSE;
13204  cons1dominateslhs = FALSE;
13205  }
13206  }
13207  }
13208 
13209  /* check for disaggregated ranged rows */
13210  if( coefsequal || coefsnegated )
13211  {
13212  SCIP_CONS* consstay;
13213  SCIP_CONS* consdel;
13214 #ifndef NDEBUG
13215  SCIP_CONSDATA* consdatastay;
13216 #endif
13217  SCIP_CONSDATA* consdatadel;
13218  SCIP_Real lhs;
13219  SCIP_Real rhs;
13220  int consinddel;
13221 
13222  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
13223  * best left and right hand sides; delete the old constraints afterwards
13224  */
13225  SCIPdebugMsg(scip, "aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
13226  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
13227  SCIPdebugPrintCons(scip, cons0, NULL);
13228  SCIPdebugPrintCons(scip, cons1, NULL);
13229 
13230  if( coefsequal )
13231  {
13232  /* the coefficients of both rows are equal */
13233  lhs = MAX(consdata0->lhs, consdata1->lhs);
13234  rhs = MIN(consdata0->rhs, consdata1->rhs);
13235  }
13236  else
13237  {
13238  /* the coefficients of both rows are negations */
13239  lhs = MAX(consdata0->lhs, -consdata1->rhs);
13240  rhs = MIN(consdata0->rhs, -consdata1->lhs);
13241  }
13242  if( SCIPisFeasLT(scip, rhs, lhs) )
13243  {
13244  SCIPdebugMsg(scip, "aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
13245  *cutoff = TRUE;
13246  break;
13247  }
13248 
13249  /* check which constraint has to stay;
13250  * changes applied to an upgraded constraint will not be considered in the instance */
13251  if( consdata0->upgraded )
13252  {
13253  assert(!consdata1->upgraded);
13254  consstay = cons1;
13255 #ifndef NDEBUG
13256  consdatastay = consdata1;
13257 #endif
13258 
13259  consdel = cons0;
13260  consdatadel = consdata0;
13261  consinddel = chkind;
13262  }
13263  else
13264  {
13265  consstay = cons0;
13266 #ifndef NDEBUG
13267  consdatastay = consdata0;
13268 #endif
13269 
13270  consdel = cons1;
13271  consdatadel = consdata1;
13272  consinddel = c;
13273  }
13274 
13275  /* update the sides of consstay */
13276  SCIP_CALL( chgLhs(scip, consstay, lhs) );
13277  SCIP_CALL( chgRhs(scip, consstay, rhs) );
13278  if( !consdata0->upgraded )
13279  {
13280  assert(consstay == cons0);
13281  cons0lhs = consdata0->lhs;
13282  cons0rhs = consdata0->rhs;
13283  }
13284 
13285  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13286  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
13287 
13288  assert( !consdatastay->upgraded );
13289  /* delete consdel */
13290  SCIP_CALL( SCIPdelCons(scip, consdel) );
13291  conss[consinddel] = NULL;
13292  if( !consdatadel->upgraded )
13293  (*ndelconss)++;
13294  continue;
13295  }
13296 
13297  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
13298  * redundant
13299  */
13300  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
13301  {
13302  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
13303  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13304  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13305  SCIPdebugPrintCons(scip, cons0, NULL);
13306  SCIPdebugPrintCons(scip, cons1, NULL);
13307 
13308  /* check for infeasibility */
13309  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
13310  {
13311  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13312  *cutoff = TRUE;
13313  break;
13314  }
13315 
13316  /* remove redundant left hand side */
13317  if( !SCIPisInfinity(scip, -consdata0->lhs) )
13318  {
13319  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
13320  cons0lhs = consdata0->lhs;
13321  cons0isequality = FALSE;
13322  if( !consdata0->upgraded )
13323  {
13324  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13325  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13326 
13327  (*nchgsides)++;
13328  }
13329  }
13330  }
13331  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
13332  {
13333  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
13334  SCIPdebugMsg(scip, "left hand side of linear constraint <%s> is dominated by <%s>:\n",
13335  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13336  SCIPdebugPrintCons(scip, cons1, NULL);
13337  SCIPdebugPrintCons(scip, cons0, NULL);
13338 
13339  /* check for infeasibility */
13340  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
13341  {
13342  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13343  *cutoff = TRUE;
13344  break;
13345  }
13346 
13347  /* remove redundant left hand side */
13348  if( !SCIPisInfinity(scip, -consdata1->lhs) )
13349  {
13350  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
13351  cons1isequality = FALSE;
13352  if( !consdata1->upgraded )
13353  {
13354  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13355  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13356 
13357  (*nchgsides)++;
13358  }
13359  }
13360  }
13361  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
13362  {
13363  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
13364  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13365  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13366  SCIPdebugPrintCons(scip, cons0, NULL);
13367  SCIPdebugPrintCons(scip, cons1, NULL);
13368 
13369  /* check for infeasibility */
13370  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
13371  {
13372  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13373  *cutoff = TRUE;
13374  break;
13375  }
13376 
13377  /* remove redundant right hand side */
13378  if( !SCIPisInfinity(scip, consdata0->rhs) )
13379  {
13380  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
13381  cons0rhs = consdata0->rhs;
13382  cons0isequality = FALSE;
13383  if( !consdata0->upgraded )
13384  {
13385  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13386  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13387 
13388  (*nchgsides)++;
13389  }
13390  }
13391  }
13392  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
13393  {
13394  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
13395  SCIPdebugMsg(scip, "right hand side of linear constraint <%s> is dominated by <%s>:\n",
13396  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
13397  SCIPdebugPrintCons(scip, cons1, NULL);
13398  SCIPdebugPrintCons(scip, cons0, NULL);
13399 
13400  /* check for infeasibility */
13401  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
13402  {
13403  SCIPdebugMsg(scip, "linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
13404  *cutoff = TRUE;
13405  break;
13406  }
13407 
13408  /* remove redundant right hand side */
13409  if( !SCIPisInfinity(scip, consdata1->rhs) )
13410  {
13411  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
13412  cons1isequality = FALSE;
13413  if( !consdata1->upgraded )
13414  {
13415  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13416  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13417 
13418  (*nchgsides)++;
13419  }
13420  }
13421  }
13422 
13423  /* check for now redundant constraints */
13424  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
13425  {
13426  /* consdata0 became redundant */
13427  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
13428  SCIP_CALL( SCIPdelCons(scip, cons0) );
13429  conss[chkind] = NULL;
13430  if( !consdata0->upgraded )
13431  {
13432  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13433  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
13434 
13435  (*ndelconss)++;
13436  }
13437  continue;
13438  }
13439  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
13440  {
13441  /* consdata1 became redundant */
13442  SCIPdebugMsg(scip, "linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
13443  SCIP_CALL( SCIPdelCons(scip, cons1) );
13444  conss[c] = NULL;
13445  if( !consdata1->upgraded )
13446  {
13447  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
13448  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
13449 
13450  (*ndelconss)++;
13451  }
13452  continue;
13453  }
13454 
13455  /* check, if we want to aggregate an (in)equality with an equality:
13456  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
13457  */
13458  if( tryaggregation )
13459  {
13460  SCIP_Bool aggregated;
13461 
13462  assert(consdata0->nvars == nvarscommon + nvars0minus1);
13463  assert(consdata1->nvars == nvarscommon + nvars1minus0);
13464 
13465  aggregated = FALSE;
13466  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
13467  {
13468  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
13469  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
13470  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
13471  nchgcoefs, &aggregated) );
13472 
13473  /* update array of active constraints */
13474  if( aggregated )
13475  {
13476  assert(!SCIPconsIsActive(cons0));
13477  assert(SCIPconsIsActive(cons1));
13478  conss[chkind] = NULL;
13479  }
13480  }
13481  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
13482  {
13483  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
13484  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
13485  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
13486  nchgcoefs, &aggregated) );
13487 
13488  /* update array of active constraints */
13489  if( aggregated )
13490  {
13491  assert(!SCIPconsIsActive(cons1));
13492  assert(SCIPconsIsActive(cons0));
13493  conss[c] = NULL;
13494  }
13495  }
13496  }
13497  }
13498 
13499  /* free temporary memory */
13500  SCIPfreeBufferArray(scip, &diffidx1minus0);
13501  SCIPfreeBufferArray(scip, &diffidx0minus1);
13502  SCIPfreeBufferArray(scip, &commonidx1);
13503  SCIPfreeBufferArray(scip, &commonidx0);
13504 
13505  return SCIP_OKAY;
13506 }
13507 
13508 /** do stuffing presolving on a single constraint */
13509 static
13511  SCIP* scip, /**< SCIP data structure */
13512  SCIP_CONS* cons, /**< linear constraint */
13513  SCIP_Bool singletonstuffing, /**< should stuffing of singleton continuous variables be performed? */
13514  SCIP_Bool singlevarstuffing, /**< should single variable stuffing be performed, which tries to fulfill
13515  * constraints using the cheapest variable? */
13516  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
13517  int* nfixedvars, /**< pointer to count the total number of fixed variables */
13518  int* nchgbds /**< pointer to count the total number of tightened bounds */
13519  )
13520 {
13521  SCIP_CONSDATA* consdata;
13522  SCIP_Real* ratios;
13523  int* varpos;
13524  SCIP_Bool* swapped;
13525  SCIP_VAR** vars;
13526  SCIP_Real* vals;
13527  SCIP_VAR* var;
13528  SCIP_Real lb;
13529  SCIP_Real ub;
13530  SCIP_Real minactivity;
13531  SCIP_Real maxactivity;
13532  SCIP_Real maxcondactivity;
13533  SCIP_Real mincondactivity;
13534  SCIP_Real rhs;
13535  SCIP_Real val;
13536  SCIP_Real obj;
13537  SCIP_Real factor;
13538  SCIP_Bool minactisrelax;
13539  SCIP_Bool maxactisrelax;
13540  SCIP_Bool tryfixing;
13541  int nsingletons;
13542  int idx;
13543  int v;
13544  int nvars;
13545 
13546  assert(scip != NULL);
13547  assert(cons != NULL);
13548  assert(nfixedvars != NULL);
13549 
13550  consdata = SCIPconsGetData(cons);
13551 
13552  /* we only want to run for inequalities */
13553  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->lhs) )
13554  return SCIP_OKAY;
13555 
13556  if( singlevarstuffing )
13557  {
13558  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
13559  }
13560  else
13561  {
13562  minactivity = SCIP_INVALID;
13563  maxactivity = SCIP_INVALID;
13564  }
13565 
13566  /* we want to have a <= constraint, if the rhs is infinite, we implicitly multiply the constraint by -1,
13567  * the new maxactivity is minus the old minactivity then
13568  */
13569  if( SCIPisInfinity(scip, consdata->rhs) )
13570  {
13571  SCIP_Real tmp;
13572  rhs = -consdata->lhs;
13573  factor = -1.0;
13574  tmp = maxactivity;
13575  maxactivity = -minactivity;
13576  minactivity = -tmp;
13577  }
13578  else
13579  {
13580  assert(SCIPisInfinity(scip, -consdata->lhs));
13581  rhs = consdata->rhs;
13582  factor = 1.0;
13583  }
13584 
13585  nvars = consdata->nvars;
13586  vars = consdata->vars;
13587  vals = consdata->vals;
13588 
13589  /* check for continuous singletons */
13590  if( singletonstuffing )
13591  {
13592  for( v = 0; v < nvars; ++v )
13593  {
13594  var = vars[v];
13595 
13596  if( (SCIPvarGetNLocksUp(var) + SCIPvarGetNLocksDown(var)) == 1 &&
13598  break;
13599  }
13600  }
13601  else
13602  /* we don't want to go into the next block */
13603  v = nvars;
13604 
13605  /* a singleton was found -> perform singleton variable stuffing */
13606  if( v < nvars )
13607  {
13608  assert(singletonstuffing);
13609 
13610  SCIP_CALL( SCIPallocBufferArray(scip, &varpos, nvars) );
13611  SCIP_CALL( SCIPallocBufferArray(scip, &ratios, nvars) );
13612  SCIP_CALL( SCIPallocBufferArray(scip, &swapped, nvars) );
13613 
13614  tryfixing = TRUE;
13615  nsingletons = 0;
13616  mincondactivity = 0.0;
13617  maxcondactivity = 0.0;
13618 
13619  for( v = 0; v < nvars; ++v )
13620  {
13621  var = vars[v];
13622  lb = SCIPvarGetLbGlobal(var);
13623  ub = SCIPvarGetUbGlobal(var);
13624  obj = SCIPvarGetObj(var);
13625  val = factor * vals[v];
13626 
13627  assert(!SCIPisZero(scip, val));
13628 
13629  /* the variable is a singleton and continuous */
13630  if( (SCIPvarGetNLocksUp(var) + SCIPvarGetNLocksDown(var)) == 1 &&
13632  {
13633  if( SCIPisNegative(scip, obj) && val > 0 )
13634  {
13635  /* case 1: obj < 0 and coef > 0 */
13636  if( SCIPisInfinity(scip, -lb) )
13637  {
13638  tryfixing = FALSE;
13639  break;
13640  }
13641 
13642  maxcondactivity += val * lb;
13643  mincondactivity += val * lb;
13644  swapped[v] = FALSE;
13645  ratios[nsingletons] = obj / val;
13646  varpos[nsingletons] = v;
13647  nsingletons++;
13648  }
13649  else if( SCIPisPositive(scip, obj) && val < 0 )
13650  {
13651  /* case 2: obj > 0 and coef < 0 */
13652  if( SCIPisInfinity(scip, ub) )
13653  {
13654  tryfixing = FALSE;
13655  break;
13656  }
13657  /* multiply column by (-1) to become case 1.
13658  * now bounds are swapped: ub := -lb, lb := -ub
13659  */
13660 
13661  maxcondactivity += val * ub;
13662  mincondactivity += val * ub;
13663  swapped[v] = TRUE;
13664  ratios[nsingletons] = obj / val;
13665  varpos[nsingletons] = v;
13666  nsingletons++;
13667  }
13668  else if( val > 0 )
13669  {
13670  /* case 3: obj >= 0 and coef >= 0 is handled by duality fixing.
13671  * we only consider the lower bound for the constants
13672  */
13673  assert(!SCIPisNegative(scip, obj));
13674 
13675  if( SCIPisInfinity(scip, -lb) )
13676  {
13677  /* maybe unbounded */
13678  tryfixing = FALSE;
13679  break;
13680  }
13681 
13682  maxcondactivity += val * lb;
13683  mincondactivity += val * lb;
13684  }
13685  else
13686  {
13687  /* case 4: obj <= 0 and coef <= 0 is also handled by duality fixing.
13688  * we only consider the upper bound for the constants
13689  */
13690  assert(!SCIPisPositive(scip, obj));
13691  assert(val < 0);
13692 
13693  if( SCIPisInfinity(scip, ub) )
13694  {
13695  /* maybe unbounded */
13696  tryfixing = FALSE;
13697  break;
13698  }
13699 
13700  maxcondactivity += val * ub;
13701  mincondactivity += val * ub;
13702  }
13703  }
13704  else
13705  {
13706  /* consider contribution of discrete variables, non-singleton
13707  * continuous variables and variables with more than one lock
13708  */
13709  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
13710  {
13711  tryfixing = FALSE;
13712  break;
13713  }
13714 
13715  if( val > 0 )
13716  {
13717  maxcondactivity += val * ub;
13718  mincondactivity += val * lb;
13719  }
13720  else
13721  {
13722  maxcondactivity += val * lb;
13723  mincondactivity += val * ub;
13724  }
13725  }
13726  }
13727  if( tryfixing && nsingletons > 0 && (SCIPisGT(scip, rhs, maxcondactivity) || SCIPisLE(scip, rhs, mincondactivity)) )
13728  {
13729  SCIP_Real delta;
13730  SCIP_Bool tightened;
13731 #ifdef SCIP_DEBUG
13732  int oldnfixedvars = *nfixedvars;
13733  int oldnchgbds = *nchgbds;
13734 #endif
13735 
13736  SCIPsortRealInt(ratios, varpos, nsingletons);
13737 
13738  /* verify which singleton continuous variables can be fixed */
13739  for( v = 0; v < nsingletons; ++v )
13740  {
13741  idx = varpos[v];
13742  var = vars[idx];
13743  val = factor * vals[idx];
13744  lb = SCIPvarGetLbGlobal(var);
13745  ub = SCIPvarGetUbGlobal(var);
13746 
13747  assert(val > 0 || SCIPisPositive(scip, SCIPvarGetObj(var)));
13748  assert((val < 0) == swapped[idx]);
13749  val = REALABS(val);
13750 
13751  /* stop fixing if variable bounds are not finite */
13752  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
13753  break;
13754 
13755  assert((SCIPvarGetNLocksUp(var) + SCIPvarGetNLocksDown(var)) == 1);
13756  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
13757 
13758  /* calculate the change in the row activities if this variable changes
13759  * its value from its worst to its best bound
13760  */
13761  if( swapped[idx] )
13762  delta = -(lb - ub) * val;
13763  else
13764  delta = (ub - lb) * val;
13765 
13766  assert(!SCIPisNegative(scip, delta));
13767 
13768  if( SCIPisLE(scip, delta, rhs - maxcondactivity) )
13769  {
13770  if( swapped[idx] )
13771  {
13772  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
13773  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
13774 
13775  }
13776  else
13777  {
13778  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
13779  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
13780  }
13781 
13782  if( *cutoff )
13783  break;
13784  if( tightened )
13785  {
13786  (*nfixedvars)++;
13787  }
13788  }
13789  /* @note: we could in theory tighten the bound of the first singleton variable which does not fall into the above case,
13790  * since it cannot be fully fixed. However, this is not needed and should be done by activity-based bound tightening
13791  * anyway after all other continuous singleton columns were fixed; doing it here may introduce numerical
13792  * troubles in case of large bounds.
13793  */
13794  else if( SCIPisLE(scip, rhs, mincondactivity) )
13795  {
13796  if( swapped[idx] )
13797  {
13798  SCIPdebugMsg(scip, "fix <%s> to its upper bound %g\n", SCIPvarGetName(var), ub);
13799  SCIP_CALL( SCIPfixVar(scip, var, ub, cutoff, &tightened) );
13800  }
13801  else
13802  {
13803  SCIPdebugMsg(scip, "fix <%s> to its lower bound %g\n", SCIPvarGetName(var), lb);
13804  SCIP_CALL( SCIPfixVar(scip, var, lb, cutoff, &tightened) );
13805  }
13806 
13807  if( *cutoff )
13808  break;
13809  if( tightened )
13810  {
13811  (*nfixedvars)++;
13812  }
13813  }
13814 
13815  maxcondactivity += delta;
13816  mincondactivity += delta;
13817  }
13818 
13819 #ifdef SCIP_DEBUG
13820  if( *nfixedvars - oldnfixedvars > 0 || *nchgbds - oldnchgbds > 0 )
13821  {
13822  SCIPdebugMsg(scip, "### stuffing fixed %d variables and changed %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
13823  }
13824 #endif
13825  }
13826 
13827  SCIPfreeBufferArray(scip, &swapped);
13828  SCIPfreeBufferArray(scip, &ratios);
13829  SCIPfreeBufferArray(scip, &varpos);
13830  }
13831 
13832  /* perform single-variable stuffing:
13833  * for a linear inequality
13834  * a_1 x_1 + a_2 x_2 + ... + a_n x_n <= b
13835  * with a_i > 0 and objective coefficients c_i < 0,
13836  * setting all variables to their upper bound (giving us the maximal activity of the constraint) is worst w.r.t.
13837  * feasibility of the constraint. On the other hand, this gives the best objective function contribution of the
13838  * variables contained in the constraint. The maximal activity should be larger than the rhs, otherwise the constraint
13839  * is redundant.
13840  * Now we are searching for a variable x_k with maximal ratio c_k / a_k (note that all these ratios are negative), so
13841  * that by reducing the value of this variable we reduce the activity of the constraint while having the smallest
13842  * objective deterioration per activity unit. If x_k has no downlocks, is continuous, and can be reduced enough to
13843  * render the constraint feasible, and ALL other variables have only the one uplock installed by the current constraint,
13844  * we can reduce the upper bound of x_k such that the maxactivity equals the rhs and fix all other variables to their
13845  * upper bound.
13846  * Note that the others variables may have downlocks from other constraints, which we do not need to care
13847  * about since we are setting them to the highest possible value. Also, they may be integer or binary, because the
13848  * computed ratio is still a lower bound on the change in the objective caused by reducing those variable to reach
13849  * constraint feasibility. On the other hand, uplocks on x_k from other constraint do no interfer with the method.
13850  * With a slight adjustment, the procedure even works for integral x_k. If (maxactivity - rhs)/val is integral,
13851  * the variable gets an integral value in order to fulfill the constraint tightly, and we can just apply the procedure.
13852  * If (maxactivity - rhs)/val is fractional, we need to check, if overfulfilling the constraint by setting x_k to
13853  * ceil((maxactivity - rhs)/val) is still better than setting x_k to ceil((maxactivity - rhs)/val) - 1 and
13854  * filling the remaining gap in the constraint with the next-best variable. For this, we check that
13855  * c_k * ceil((maxactivity - rhs)/val) is still better than
13856  * c_k * floor((maxactivity - rhs)/val) + c_j * ((maxactivity - rhs) - (floor((maxactivity - rhs)/val) * val))/a_j.
13857  * In this case, the upper bound of x_k is decreased to ub_k - ceil(maxactivity - rhs).
13858  * If there are variables with a_i < 0 and c_i > 0, they are negated to obtain the above form, variables with same
13859  * sign of coefficients in constraint and objective prevent the use of this method.
13860  */
13861  if( singlevarstuffing && !SCIPisInfinity(scip, -minactivity) )
13862  {
13863  SCIP_Real bestratio = -SCIPinfinity(scip);
13864  SCIP_Real secondbestratio = -SCIPinfinity(scip);
13865  SCIP_Real ratio;
13866  int bestindex = -1;
13867  int bestuplocks = 0;
13868  int bestdownlocks = 1;
13869  int downlocks;
13870  int uplocks;
13871  int oldnfixedvars;
13872  int oldnchgbds;
13873 
13874  SCIPdebug( oldnfixedvars = *nfixedvars; )
13875  SCIPdebug( oldnchgbds = *nchgbds; )
13876  /* loop over all variables to identify the best and second-best ratio */
13877  for( v = 0; v < nvars; ++v )
13878  {
13879  var = vars[v];
13880  obj = SCIPvarGetObj(var);
13881  val = factor * vals[v];
13882 
13883  assert(!SCIPisZero(scip, val));
13884 
13885  ratio = obj / val;
13886 
13887  /* if both objective and constraint push the variable to the same direction, we can do nothing here */
13888  if( !SCIPisNegative(scip, ratio) )
13889  {
13890  bestindex = -1;
13891  break;
13892  }
13893 
13894  if( val > 0 )
13895  {
13896  downlocks = SCIPvarGetNLocksDown(var);
13897  uplocks = SCIPvarGetNLocksUp(var);
13898  }
13899  else
13900  {
13901  downlocks = SCIPvarGetNLocksUp(var);
13902  uplocks = SCIPvarGetNLocksDown(var);
13903  }
13904 
13905  /* better ratio, update best candidate
13906  * @todo use some tolerance
13907  * @todo check size of domain and updated ratio for integer variables already?
13908  */
13909  if( ratio > bestratio || ((ratio == bestratio) && downlocks == 0 && (bestdownlocks > 0 /*lint !e777*/
13910  || (SCIPvarGetType(vars[bestindex]) != SCIP_VARTYPE_CONTINUOUS
13911  && SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS))) )
13912  {
13913  /* best index becomes second-best*/
13914  if( bestindex != -1 )
13915  {
13916  /* second-best index must not have more than 1 uplock */
13917  if( bestuplocks > 1 )
13918  {
13919  bestindex = -1;
13920  break;
13921  }
13922  else
13923  {
13924  secondbestratio = bestratio;
13925  }
13926  }
13927  bestdownlocks = downlocks;
13928  bestuplocks = uplocks;
13929  bestratio = ratio;
13930  bestindex = v;
13931 
13932  /* if this variable is the best in the end, we cannot do reductions since it has a downlocks,
13933  * if it is not the best, it has too many uplocks -> not applicable
13934  */
13935  if( bestdownlocks > 0 && bestuplocks > 1 )
13936  {
13937  bestindex = -1;
13938  break;
13939  }
13940  }
13941  else
13942  {
13943  /* non-best index must not have more than 1 uplock */
13944  if( uplocks > 1 )
13945  {
13946  bestindex = -1;
13947  break;
13948  }
13949  /* update second-best ratio */
13950  if( ratio > secondbestratio )
13951  {
13952  secondbestratio = ratio;
13953  }
13954  }
13955  }
13956 
13957  /* check if we can apply single variable stuffing */
13958  if( bestindex != -1 && bestdownlocks == 0 )
13959  {
13960  SCIP_Bool tightened = FALSE;
13961  SCIP_Real bounddelta;
13962 
13963  var = vars[bestindex];
13964  obj = SCIPvarGetObj(var);
13965  val = factor * vals[bestindex];
13966  lb = SCIPvarGetLbGlobal(var);
13967  ub = SCIPvarGetUbGlobal(var);
13968  tryfixing = TRUE;
13969 
13970  if( val < 0 )
13971  {
13972  assert(!SCIPisNegative(scip, obj));
13973 
13974  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
13975  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/-val) )
13976  {
13977  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/-val);
13978  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * -val);
13979  assert(SCIPisPositive(scip, activitydelta));
13980 
13981  tryfixing = SCIPisLE(scip, obj, -activitydelta * secondbestratio);
13982 
13983  bounddelta = SCIPceil(scip, (maxactivity - rhs)/-val);
13984  assert(SCIPisPositive(scip, bounddelta));
13985  }
13986  else
13987  bounddelta = (maxactivity - rhs)/-val;
13988 
13989  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
13990 
13991  if( tryfixing )
13992  {
13993  assert(SCIPvarGetNLocksUp(var) == 0);
13994 
13995  if( SCIPisEQ(scip, lb + bounddelta, ub) )
13996  {
13997  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), lb + bounddelta);
13998  SCIP_CALL( SCIPfixVar(scip, var, lb + bounddelta, cutoff, &tightened) );
13999  }
14000  else
14001  {
14002  SCIPdebugMsg(scip, "tighten the lower bound of <%s> from %g to %g (ub=%g)\n", SCIPvarGetName(var), lb, lb + bounddelta, ub);
14003  SCIP_CALL( SCIPtightenVarLb(scip, var, lb + bounddelta, FALSE, cutoff, &tightened) );
14004  }
14005  }
14006  }
14007  else
14008  {
14009  assert(!SCIPisPositive(scip, obj));
14010 
14011  /* the best variable is integer, and we need to overfulfill the constraint when using just the variable */
14012  if( SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPisIntegral(scip, (maxactivity - rhs)/val))
14013  {
14014  SCIP_Real bestvarfloor = SCIPfloor(scip, (maxactivity - rhs)/val);
14015  SCIP_Real activitydelta = (maxactivity - rhs) - (bestvarfloor * val);
14016  assert(SCIPisPositive(scip, activitydelta));
14017 
14018  tryfixing = SCIPisLE(scip, -obj, activitydelta * secondbestratio);
14019 
14020  bounddelta = SCIPceil(scip, (maxactivity - rhs)/val);
14021  assert(SCIPisPositive(scip, bounddelta));
14022  }
14023  else
14024  bounddelta = (maxactivity - rhs)/val;
14025 
14026  tryfixing = tryfixing && SCIPisLE(scip, bounddelta, ub - lb);
14027 
14028  if( tryfixing )
14029  {
14030  assert(SCIPvarGetNLocksDown(var) == 0);
14031 
14032  if( SCIPisEQ(scip, ub - bounddelta, lb) )
14033  {
14034  SCIPdebugMsg(scip, "fix var <%s> to %g\n", SCIPvarGetName(var), ub - bounddelta);
14035  SCIP_CALL( SCIPfixVar(scip, var, ub - bounddelta, cutoff, &tightened) );
14036  }
14037  else
14038  {
14039  SCIPdebugMsg(scip, "tighten the upper bound of <%s> from %g to %g (lb=%g)\n", SCIPvarGetName(var), ub, ub - bounddelta, lb);
14040  SCIP_CALL( SCIPtightenVarUb(scip, var, ub - bounddelta, FALSE, cutoff, &tightened) );
14041  }
14042  }
14043  }
14044 
14045  if( *cutoff )
14046  return SCIP_OKAY;
14047  if( tightened )
14048  {
14049  if( SCIPisEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)) )
14050  ++(*nfixedvars);
14051  else
14052  ++(*nchgbds);
14053 
14054  SCIPdebugMsg(scip, "cons <%s>: %g <=\n", SCIPconsGetName(cons), factor > 0 ? consdata->lhs : -consdata->rhs);
14055  for( v = 0; v < nvars; ++v )
14056  {
14057  SCIPdebugMsg(scip, "%+g <%s>([%g,%g],%g,[%d,%d],%s)\n", factor * vals[v], SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]),
14058  SCIPvarGetUbGlobal(vars[v]), SCIPvarGetObj(vars[v]), SCIPvarGetNLocksDown(vars[v]), SCIPvarGetNLocksUp(vars[v]),
14059  SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS ? "C" : "I");
14060  }
14061  SCIPdebugMsg(scip, "<= %g\n", factor > 0 ? consdata->rhs : -consdata->lhs);
14062 
14063  for( v = 0; v < nvars; ++v )
14064  {
14065  if( v == bestindex )
14066  continue;
14067 
14068  if( factor * vals[v] < 0 )
14069  {
14070  assert(SCIPvarGetNLocksDown(vars[v]) == 1);
14071  SCIPdebugMsg(scip, "fix <%s> to its lower bound (%g)\n", SCIPvarGetName(vars[v]), SCIPvarGetLbGlobal(vars[v]));
14072  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetLbGlobal(vars[v]), cutoff, &tightened) );
14073  }
14074  else
14075  {
14076  assert(SCIPvarGetNLocksUp(vars[v]) == 1);
14077  SCIPdebugMsg(scip, "fix <%s> to its upper bound (%g)\n", SCIPvarGetName(vars[v]), SCIPvarGetUbGlobal(vars[v]));
14078  SCIP_CALL( SCIPfixVar(scip, vars[v], SCIPvarGetUbGlobal(vars[v]), cutoff, &tightened) );
14079  }
14080 
14081  if( *cutoff )
14082  return SCIP_OKAY;
14083  if( tightened )
14084  ++(*nfixedvars);
14085  }
14086  SCIPdebugMsg(scip, "### new stuffing fixed %d vars, tightened %d bounds\n", *nfixedvars - oldnfixedvars, *nchgbds - oldnchgbds);
14087  }
14088  }
14089  }
14090 
14091  return SCIP_OKAY;
14092 }
14093 
14094 /** applies full dual presolving on variables that only appear in linear constraints */
14095 static
14097  SCIP* scip, /**< SCIP data structure */
14098  SCIP_CONS** conss, /**< constraint set */
14099  int nconss, /**< number of constraints */
14100  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
14101  int* nchgbds /**< pointer to count the number of bound changes */
14102  )
14103 {
14104  SCIP_Real* redlb;
14105  SCIP_Real* redub;
14106  int* nlocksdown;
14107  int* nlocksup;
14108  SCIP_Bool* isimplint;
14109  SCIP_VAR** origvars;
14110  SCIP_VAR** vars;
14111  SCIP_VAR** conscontvars;
14112  int nvars;
14113  int nbinvars;
14114  int nintvars;
14115  int ncontvars;
14116  int v;
14117  int c;
14118 
14119  /* we calculate redundancy bounds with the following meaning:
14120  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
14121  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
14122  * then:
14123  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
14124  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
14125  */
14126 
14127  /* Additionally, we detect continuous variables that are implicitly integral.
14128  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
14129  * and all constraints (including the bounds as trivial constraints) in which:
14130  * c_j > 0: the variable is down-locked,
14131  * c_j < 0: the variable is up-locked,
14132  * c_j = 0: the variable appears
14133  * have, apart from j, only integer variables with integral coefficients and integral sides.
14134  * This is because then, the value of the variable is either determined by one of its bounds or
14135  * by one of these constraints, and in all cases, the value of the variable is integral.
14136  */
14137 
14138  assert(scip != NULL);
14139  assert(nconss == 0 || conss != NULL);
14140  assert(nchgbds != NULL);
14141  assert(!SCIPinProbing(scip));
14142 
14143  /* get active variables */
14144  nvars = SCIPgetNVars(scip);
14145  origvars = SCIPgetVars(scip);
14146 
14147  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
14148  nbinvars = SCIPgetNBinVars(scip);
14149  if( nbinvars == nvars )
14150  return SCIP_OKAY;
14151 
14152  /* get number of continuous variables */
14153  ncontvars = SCIPgetNContVars(scip);
14154  nintvars = nvars - ncontvars;
14155 
14156  /* copy the variable array since this array might change during the curse of this algorithm */
14157  nvars = nvars - nbinvars;
14158  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
14159 
14160  /* allocate temporary memory */
14161  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
14162  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
14163  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
14164  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
14165  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
14166  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
14167 
14168  /* initialize redundancy bounds */
14169  for( v = 0; v < nvars; ++v )
14170  {
14171  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14172  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
14173  redub[v] = SCIPvarGetUbGlobal(vars[v]);
14174  }
14175  BMSclearMemoryArray(nlocksdown, nvars);
14176  BMSclearMemoryArray(nlocksup, nvars);
14177 
14178  /* Initialize isimplint array: variable may be implied integer if rounded to their best bound they are integral.
14179  * We better not use SCIPisFeasIntegral() in these checks.
14180  */
14181  for( v = 0; v < ncontvars; v++ )
14182  {
14183  SCIP_VAR* var;
14184  SCIP_Real obj;
14185  SCIP_Real lb;
14186  SCIP_Real ub;
14187 
14188  var = vars[v + nintvars - nbinvars];
14189  lb = SCIPvarGetLbGlobal(var);
14190  ub = SCIPvarGetUbGlobal(var);
14191 
14192  obj = SCIPvarGetObj(var);
14193  if( SCIPisZero(scip, obj) )
14194  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb)) && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14195  else
14196  {
14197  if( SCIPisPositive(scip, obj) )
14198  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb));
14199  else
14200  {
14201  assert(SCIPisNegative(scip, obj));
14202  isimplint[v] = (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
14203  }
14204  }
14205  }
14206 
14207  /* scan all constraints */
14208  for( c = 0; c < nconss; ++c )
14209  {
14210  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
14211  * part of checked disjunctions)
14212  */
14213  if( SCIPconsIsLocked(conss[c]) )
14214  {
14215  SCIP_CONSDATA* consdata;
14216  SCIP_Bool lhsexists;
14217  SCIP_Bool rhsexists;
14218  SCIP_Bool hasimpliedpotential;
14219  SCIP_Bool integralcoefs;
14220  int nlockspos;
14221  int contvarpos;
14222  int nconscontvars;
14223  int i;
14224 
14225  consdata = SCIPconsGetData(conss[c]);
14226  assert(consdata != NULL);
14227 
14228  /* get number of times the constraint was locked */
14229  nlockspos = SCIPconsGetNLocksPos(conss[c]);
14230 
14231  /* we do not want to include constraints with locked negation (this would be too weird) */
14232  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
14233  {
14234  /* mark all continuous variables as not being implicit integral */
14235  for( i = 0; i < consdata->nvars; ++i )
14236  {
14237  SCIP_VAR* var;
14238 
14239  var = consdata->vars[i];
14241  {
14242  int contv;
14243  contv = SCIPvarGetProbindex(var) - nintvars;
14244  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
14245  isimplint[contv] = FALSE;
14246  }
14247  }
14248  continue;
14249  }
14250 
14251  /* check for existing sides */
14252  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
14253  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
14254 
14255  /* count locks and update redundancy bounds */
14256  contvarpos = -1;
14257  nconscontvars = 0;
14258  hasimpliedpotential = FALSE;
14259  integralcoefs = !SCIPconsIsModifiable(conss[c]);
14260 
14261  for( i = 0; i < consdata->nvars; ++i )
14262  {
14263  SCIP_VAR* var;
14264  SCIP_Real val;
14265  SCIP_Real minresactivity;
14266  SCIP_Real maxresactivity;
14267  SCIP_Real newredlb;
14268  SCIP_Real newredub;
14269  SCIP_Bool minisrelax;
14270  SCIP_Bool maxisrelax;
14271  SCIP_Bool isminsettoinfinity;
14272  SCIP_Bool ismaxsettoinfinity;
14273  int arrayindex;
14274 
14275  var = consdata->vars[i];
14276  val = consdata->vals[i];
14277 
14278  /* check if still all integer variables have integral coefficients */
14279  if( SCIPvarIsIntegral(var) )
14280  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
14281 
14282  /* we do not need to process binary variables */
14283  if( SCIPvarIsBinary(var) )
14284  continue;
14285 
14286  if( SCIPconsIsModifiable(conss[c]) )
14287  {
14288  minresactivity = -SCIPinfinity(scip);
14289  maxresactivity = SCIPinfinity(scip);
14290  isminsettoinfinity = TRUE;
14291  ismaxsettoinfinity = TRUE;
14292  }
14293  else
14294  {
14295  /* calculate residual activity bounds if variable would be fixed to zero */
14296  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
14297  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
14298 
14299  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
14300  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
14301  * This is needed, because we do not want to rely on relaxed finite resactivities.
14302  */
14303  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
14304 
14305  /* check minresactivity for reliability */
14306  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
14307  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
14308 
14309  /* check maxresactivity for reliability */
14310  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
14311  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
14312  }
14313 
14314  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
14315 
14316  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
14317 
14318  newredlb = redlb[arrayindex];
14319  newredub = redub[arrayindex];
14320  if( val > 0.0 )
14321  {
14322  if( lhsexists )
14323  {
14324  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
14325  nlocksdown[arrayindex] += nlockspos;
14326  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14327  }
14328  if( rhsexists )
14329  {
14330  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
14331  nlocksup[arrayindex] += nlockspos;
14332  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14333  }
14334  }
14335  else
14336  {
14337  if( lhsexists )
14338  {
14339  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
14340  nlocksup[arrayindex] += nlockspos;
14341  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
14342  }
14343  if( rhsexists )
14344  {
14345  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
14346  nlocksdown[arrayindex] += nlockspos;
14347  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
14348  }
14349  }
14350 
14351  /* if the variable is integer, we have to round the value to the next integral value */
14352  if( SCIPvarIsIntegral(var) )
14353  {
14354  if( !SCIPisInfinity(scip, newredlb) )
14355  newredlb = SCIPceil(scip, newredlb);
14356  if( !SCIPisInfinity(scip, -newredub) )
14357  newredub = SCIPfloor(scip, newredub);
14358  }
14359 
14360  /* update redundancy bounds */
14361  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
14362  redub[arrayindex] = MIN(redub[arrayindex], newredub);
14363 
14364  /* collect the continuous variables of the constraint */
14366  {
14367  int contv;
14368 
14369  assert(nconscontvars < ncontvars);
14370  contvarpos = i;
14371  conscontvars[nconscontvars] = var;
14372  nconscontvars++;
14373 
14374  contv = SCIPvarGetProbindex(var) - nintvars;
14375  assert(0 <= contv && contv < ncontvars);
14376  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
14377  }
14378  }
14379 
14380  /* update implied integer status of continuous variables */
14381  if( hasimpliedpotential )
14382  {
14383  if( nconscontvars > 1 || !integralcoefs )
14384  {
14385  /* there is more than one continuous variable or the integer variables have fractional coefficients:
14386  * none of the continuous variables is implied integer
14387  */
14388  for( i = 0; i < nconscontvars; i++ )
14389  {
14390  int contv;
14391  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
14392  assert(0 <= contv && contv < ncontvars);
14393  isimplint[contv] = FALSE;
14394  }
14395  }
14396  else
14397  {
14398  SCIP_VAR* var;
14399  SCIP_Real val;
14400  SCIP_Real absval;
14401  int contv;
14402 
14403  /* there is exactly one continuous variable and the integer variables have integral coefficients:
14404  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
14405  * side(s) of the constraint is integral
14406  */
14407  assert(nconscontvars == 1);
14408  assert(0 <= contvarpos && contvarpos < consdata->nvars);
14409  var = consdata->vars[contvarpos];
14410  val = consdata->vals[contvarpos];
14411  contv = SCIPvarGetProbindex(var) - nintvars;
14412  assert(0 <= contv && contv < ncontvars);
14413  assert(isimplint[contv]);
14414 
14415  absval = REALABS(val);
14416  if( !SCIPisEQ(scip, absval, 1.0) )
14417  isimplint[contv] = FALSE;
14418  else
14419  {
14420  SCIP_Real obj;
14421 
14422  obj = SCIPvarGetObj(var);
14423  if( obj * val >= 0.0 && lhsexists )
14424  {
14425  /* the variable may be blocked by the constraint's left hand side */
14426  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
14427  }
14428  if( obj * val <= 0.0 && rhsexists )
14429  {
14430  /* the variable may be blocked by the constraint's left hand side */
14431  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
14432  }
14433  }
14434  }
14435  }
14436  }
14437  }
14438 
14439  /* check if any bounds can be tightened due to optimality */
14440  for( v = 0; v < nvars; ++v )
14441  {
14442  SCIP_VAR* var;
14443  SCIP_Real obj;
14444  SCIP_Bool infeasible;
14445  SCIP_Bool tightened;
14446 
14447  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
14448  assert(SCIPvarGetNLocksDown(vars[v]) >= nlocksdown[v]);
14449  assert(SCIPvarGetNLocksUp(vars[v]) >= nlocksup[v]);
14450 
14451  var = vars[v];
14452  obj = SCIPvarGetObj(var);
14453  if( obj >= 0.0 )
14454  {
14455  /* making the variable as small as possible does not increase the objective:
14456  * check if all down locks of the variables are due to linear constraints;
14457  * if largest bound to make constraints redundant is -infinity, we better do nothing for numerical reasons
14458  */
14459  if( SCIPvarGetNLocksDown(var) == nlocksdown[v]
14460  && !SCIPisInfinity(scip, -redlb[v])
14461  && redlb[v] < SCIPvarGetUbGlobal(var) )
14462  {
14463  SCIP_Real ub;
14464 
14465  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
14466  * -> tighten upper bound to x_v <= redlb[v]
14467  */
14468  SCIPdebugMsg(scip, "variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
14470  redlb[v]);
14471  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
14472  assert(!infeasible);
14473 
14474  ub = SCIPvarGetUbGlobal(var);
14475  redub[v] = MIN(redub[v], ub);
14476  if( tightened )
14477  (*nchgbds)++;
14478  }
14479  }
14480  if( obj <= 0.0 )
14481  {
14482  /* making the variable as large as possible does not increase the objective:
14483  * check if all up locks of the variables are due to linear constraints;
14484  * if smallest bound to make constraints redundant is +infinity, we better do nothing for numerical reasons
14485  */
14486  if( SCIPvarGetNLocksUp(var) == nlocksup[v]
14487  && !SCIPisInfinity(scip, redub[v])
14488  && redub[v] > SCIPvarGetLbGlobal(var) )
14489  {
14490  SCIP_Real lb;
14491 
14492  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
14493  * -> tighten lower bound to x_v >= redub[v]
14494  */
14495  SCIPdebugMsg(scip, "variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
14497  redub[v]);
14498  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
14499  assert(!infeasible);
14500 
14501  lb = SCIPvarGetLbGlobal(var);
14502  redlb[v] = MAX(redlb[v], lb);
14503  if( tightened )
14504  (*nchgbds)++;
14505  }
14506  }
14507  }
14508 
14509  /* upgrade continuous variables to implied integers */
14510  for( v = nintvars - nbinvars; v < nvars; ++v )
14511  {
14512  SCIP_VAR* var;
14513  SCIP_Bool infeasible;
14514 
14515  var = vars[v];
14516  assert(var != NULL);
14517 
14518  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
14519  assert(SCIPvarGetNLocksDown(var) >= nlocksdown[v]);
14520  assert(SCIPvarGetNLocksUp(var) >= nlocksup[v]);
14521  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
14522 
14523  /* we can only conclude implied integrality if the variable appears in no other constraint */
14524  if( isimplint[v - nintvars + nbinvars]
14525  && SCIPvarGetNLocksDown(var) == nlocksdown[v]
14526  && SCIPvarGetNLocksUp(var) == nlocksup[v] )
14527  {
14528 
14529  /* since we locally copied the variable array we can change the variable type immediately */
14530  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
14531 
14532  if( infeasible )
14533  {
14534  SCIPdebugMsg(scip, "infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
14535  *cutoff = TRUE;
14536 
14537  break;
14538  }
14539 
14540  SCIPdebugMsg(scip, "dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
14542  }
14543  }
14544 
14545  /* free temporary memory */
14546  SCIPfreeBufferArray(scip, &conscontvars);
14547  SCIPfreeBufferArray(scip, &isimplint);
14548  SCIPfreeBufferArray(scip, &nlocksup);
14549  SCIPfreeBufferArray(scip, &nlocksdown);
14550  SCIPfreeBufferArray(scip, &redub);
14551  SCIPfreeBufferArray(scip, &redlb);
14552 
14553  SCIPfreeBufferArray(scip, &vars);
14554 
14555  return SCIP_OKAY;
14556 }
14557 
14558 /** helper function to enforce constraints */
14559 static
14561  SCIP* scip, /**< SCIP data structure */
14562  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
14563  SCIP_CONS** conss, /**< constraints to process */
14564  int nconss, /**< number of constraints */
14565  int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
14566  SCIP_SOL* sol, /**< solution to enforce (NULL for the LP solution) */
14567  SCIP_RESULT* result /**< pointer to store the result of the enforcing call */
14568  )
14569 {
14570  SCIP_CONSHDLRDATA* conshdlrdata;
14571  SCIP_Bool checkrelmaxabs;
14572  SCIP_Bool violated;
14573  SCIP_Bool cutoff = FALSE;
14574  int c;
14575 
14576  assert(scip != NULL);
14577  assert(conshdlr != NULL);
14578  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14579  assert(result != NULL);
14580 
14581  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14582  assert(conshdlrdata != NULL);
14583 
14584  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
14585 
14586  SCIPdebugMsg(scip, "Enforcement method of linear constraints for %s solution\n", sol == NULL ? "LP" : "relaxation");
14587 
14588  /* check for violated constraints
14589  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
14590  */
14591  *result = SCIP_FEASIBLE;
14592 
14593  /* check all useful linear constraints for feasibility */
14594  for( c = 0; c < nusefulconss; ++c )
14595  {
14596  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14597 
14598  if( violated )
14599  {
14600  /* insert LP row as cut */
14601  SCIP_CALL( addRelaxation(scip, conss[c], sol, &cutoff) );
14602  if ( cutoff )
14603  *result = SCIP_CUTOFF;
14604  else
14605  *result = SCIP_SEPARATED;
14606  }
14607  }
14608 
14609  /* check all obsolete linear constraints for feasibility */
14610  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
14611  {
14612  SCIP_CALL( checkCons(scip, conss[c], sol, FALSE, checkrelmaxabs, &violated) );
14613 
14614  if( violated )
14615  {
14616  /* insert LP row as cut */
14617  SCIP_CALL( addRelaxation(scip, conss[c], sol, &cutoff) );
14618  if ( cutoff )
14619  *result = SCIP_CUTOFF;
14620  else
14621  *result = SCIP_SEPARATED;
14622  }
14623  }
14624 
14625  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
14626 
14627  return SCIP_OKAY;
14628 }
14629 
14630 /*
14631  * Callback methods of constraint handler
14632  */
14633 
14634 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
14635 static
14636 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
14637 { /*lint --e{715}*/
14638  assert(scip != NULL);
14639  assert(conshdlr != NULL);
14640  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14641 
14642  /* call inclusion method of constraint handler */
14644 
14645  *valid = TRUE;
14646 
14647  return SCIP_OKAY;
14648 }
14649 
14650 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
14651 static
14652 SCIP_DECL_CONSFREE(consFreeLinear)
14653 { /*lint --e{715}*/
14654  SCIP_CONSHDLRDATA* conshdlrdata;
14655 
14656  assert(scip != NULL);
14657  assert(conshdlr != NULL);
14658  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
14659 
14660  /* free constraint handler data */
14661  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14662  assert(conshdlrdata != NULL);
14663 
14664  conshdlrdataFree(scip, &conshdlrdata);
14665 
14666  SCIPconshdlrSetData(conshdlr, NULL);
14667 
14668  return SCIP_OKAY;
14670 
14671 
14672 /** initialization method of constraint handler (called after problem was transformed) */
14673 static
14674 SCIP_DECL_CONSINIT(consInitLinear)
14675 {
14676  SCIP_CONSHDLRDATA* conshdlrdata;
14677  int c;
14678 
14679  assert(scip != NULL);
14680 
14681  /* check for event handler */
14682  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14683  assert(conshdlrdata != NULL);
14684  assert(conshdlrdata->eventhdlr != NULL);
14685  assert(nconss == 0 || conss != NULL);
14686 
14687  /* catch events for the constraints */
14688  for( c = 0; c < nconss; ++c )
14689  {
14690  /* catch all events */
14691  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
14692  }
14693 
14694  return SCIP_OKAY;
14695 }
14696 
14697 
14698 /** deinitialization method of constraint handler (called before transformed problem is freed) */
14699 static
14700 SCIP_DECL_CONSEXIT(consExitLinear)
14701 {
14702  SCIP_CONSHDLRDATA* conshdlrdata;
14703  int c;
14704 
14705  assert(scip != NULL);
14706 
14707  /* check for event handler */
14708  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14709  assert(conshdlrdata != NULL);
14710  assert(conshdlrdata->eventhdlr != NULL);
14711 
14712  /* drop events for the constraints */
14713  for( c = nconss - 1; c >= 0; --c )
14714  {
14715  SCIP_CONSDATA* consdata;
14716 
14717  consdata = SCIPconsGetData(conss[c]);
14718  assert(consdata != NULL);
14719 
14720  if( consdata->eventdata != NULL )
14721  {
14722  /* drop all events */
14723  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
14724  assert(consdata->eventdata == NULL);
14725  }
14726  }
14727 
14728  return SCIP_OKAY;
14729 
14730 }
14731 
14732 #ifdef WITH_PRINTORIGCONSTYPES
14733 
14734 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
14735 static
14736 SCIP_Bool isRangedRow(
14737  SCIP* scip, /**< SCIP data structure */
14738  SCIP_CONS* cons /**< constraint */
14739  )
14740 {
14741  assert(scip != NULL);
14742  assert(cons != NULL);
14743  assert(SCIPconsGetData(cons) != NULL);
14744 
14745  return !(SCIPisEQ(scip, SCIPconsGetData(cons)->lhs, SCIPconsGetData(cons)->rhs)
14746  || SCIPisInfinity(scip, -SCIPconsGetData(cons)->lhs) || SCIPisInfinity(scip, SCIPconsGetData(cons)->rhs) );
14747 }
14748 
14749 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
14750 static
14751 SCIP_Bool isFiniteNonnegativeIntegral(
14752  SCIP* scip, /**< SCIP data structure */
14753  SCIP_Real x /**< value */
14754  )
14755 {
14756  assert(scip != NULL);
14757 
14758  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
14759 }
14760 
14761 /** presolving initialization method of constraint handler (called when presolving is about to begin) */
14762 static
14763 SCIP_DECL_CONSINITPRE(consInitpreLinear)
14764 { /*lint --e{715}*/
14765  int counter[(int)SCIP_CONSTYPE_GENERAL + 1];
14766  int c;
14767 
14768  assert(scip != NULL);
14769 
14770  /* initialize counter for constraint types to zero */
14771  BMSclearMemoryArray(counter, (int)SCIP_CONSTYPE_GENERAL + 1);
14772 
14773  /* loop through all constraints */
14774  for( c = 0; c < nconss; c++ )
14775  {
14776  SCIP_CONS* cons;
14777  SCIP_CONSDATA* consdata;
14778  int i;
14779 
14780  /* get constraint */
14781  cons = conss[c];
14782  assert(cons != NULL);
14783 
14784  /* get constraint data */
14785  consdata = SCIPconsGetData(cons);
14786  assert(consdata != NULL);
14787 
14788  /* merge multiples and delete variables with zero coefficient */
14789  SCIP_CALL( mergeMultiples(scip, cons) );
14790  for( i = 0; i < consdata->nvars; i++ )
14791  {
14792  assert(!SCIPisZero(scip, consdata->vals[i]));
14793  }
14794 
14795  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
14796  if( consdata->nvars == 0 )
14797  {
14798  SCIPdebugMsg(scip, "classified as EMPTY: ");
14799  SCIPdebugPrintCons(scip, cons, NULL);
14800  counter[SCIP_CONSTYPE_EMPTY]++;
14801  continue;
14802  }
14803 
14804  /* is constraint of type SCIP_CONSTYPE_FREE? */
14805  if( SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, -consdata->lhs) )
14806  {
14807  SCIPdebugMsg(scip, "classified as FREE: ");
14808  SCIPdebugPrintCons(scip, cons, NULL);
14809  counter[SCIP_CONSTYPE_FREE]++;
14810  continue;
14811  }
14812 
14813  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
14814  if( consdata->nvars == 1 )
14815  {
14816  SCIPdebugMsg(scip, "classified as SINGLETON: ");
14817  SCIPdebugPrintCons(scip, cons, NULL);
14818  counter[SCIP_CONSTYPE_SINGLETON] += isRangedRow(scip, cons) ? 2 : 1;
14819  continue;
14820  }
14821 
14822  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
14823  if( consdata->nvars == 2 && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
14824  {
14825  SCIPdebugMsg(scip, "classified as AGGREGATION: ");
14826  SCIPdebugPrintCons(scip, cons, NULL);
14827  counter[SCIP_CONSTYPE_AGGREGATION]++;
14828  continue;
14829  }
14830 
14831  /* is constraint of type SCIP_CONSTYPE_{VARBOUND}? */
14832  if( consdata->nvars == 2 )
14833  {
14834  SCIPdebugMsg(scip, "classified as VARBOUND: ");
14835  SCIPdebugPrintCons(scip, cons, NULL);
14836  counter[SCIP_CONSTYPE_VARBOUND] += isRangedRow(scip, cons) ? 2 : 1;
14837  continue;
14838  }
14839 
14840  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
14841  {
14842  SCIP_Real scale;
14843  SCIP_Real b;
14844  SCIP_Bool unmatched;
14845  int nnegbinvars;
14846 
14847  unmatched = FALSE;
14848  nnegbinvars = 0;
14849 
14850  scale = REALABS(consdata->vals[0]);
14851  for( i = 0; i < consdata->nvars && !unmatched; i++ )
14852  {
14853  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
14854  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
14855  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
14856  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
14857 
14858  if( consdata->vals[i] < 0.0 )
14859  nnegbinvars++;
14860  }
14861 
14862  if( !unmatched )
14863  {
14864  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
14865  {
14866  b = consdata->rhs/scale + nnegbinvars;
14867  if( SCIPisEQ(scip, 1.0, b) )
14868  {
14869  SCIPdebugMsg(scip, "classified as SETPARTITION: ");
14870  SCIPdebugPrintCons(scip, cons, NULL);
14871  counter[SCIP_CONSTYPE_SETPARTITION]++;
14872  continue;
14873  }
14874  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
14875  {
14876  SCIPdebugMsg(scip, "classified as CARDINALITY: ");
14877  SCIPdebugPrintCons(scip, cons, NULL);
14878  counter[SCIP_CONSTYPE_CARDINALITY]++;
14879  continue;
14880  }
14881  }
14882 
14883  b = consdata->rhs/scale + nnegbinvars;
14884  if( SCIPisEQ(scip, 1.0, b) )
14885  {
14886  SCIPdebugMsg(scip, "classified as SETPACKING: ");
14887  SCIPdebugPrintCons(scip, cons, NULL);
14888  counter[SCIP_CONSTYPE_SETPACKING]++;
14889  consdata->rhs = SCIPinfinity(scip);
14890  }
14891  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
14892  {
14893  SCIPdebugMsg(scip, "classified as INVKNAPSACK: ");
14894  SCIPdebugPrintCons(scip, cons, NULL);
14895  counter[SCIP_CONSTYPE_INVKNAPSACK]++;
14896  consdata->rhs = SCIPinfinity(scip);
14897  }
14898 
14899  b = consdata->lhs/scale + nnegbinvars;
14900  if( SCIPisEQ(scip, 1.0, b) )
14901  {
14902  SCIPdebugMsg(scip, "classified as SETCOVERING: ");
14903  SCIPdebugPrintCons(scip, cons, NULL);
14904  counter[SCIP_CONSTYPE_SETCOVERING]++;
14905  consdata->lhs = -SCIPinfinity(scip);
14906  }
14907 
14908  if( SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, consdata->rhs) )
14909  continue;
14910  }
14911  }
14912 
14913  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
14914  /* @todo If coefficients or rhs are not integral, we currently do not check
14915  * if the constraint could be scaled (finitely), such that they are.
14916  */
14917  {
14918  SCIP_Real b;
14919  SCIP_Bool unmatched;
14920 
14921  b = consdata->rhs;
14922  unmatched = FALSE;
14923  for( i = 0; i < consdata->nvars && !unmatched; i++ )
14924  {
14925  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
14926  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
14927  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
14928  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
14929 
14930  if( SCIPisNegative(scip, consdata->vals[i]) )
14931  b -= consdata->vals[i];
14932  }
14933  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
14934 
14935  if( !unmatched )
14936  {
14937  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
14938  {
14939  SCIPdebugMsg(scip, "classified as EQKNAPSACK: ");
14940  SCIPdebugPrintCons(scip, cons, NULL);
14941  counter[SCIP_CONSTYPE_EQKNAPSACK]++;
14942  continue;
14943  }
14944  else
14945  {
14946  SCIP_Bool matched;
14947 
14948  matched = FALSE;
14949  for( i = 0; i < consdata->nvars && !matched; i++ )
14950  {
14951  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
14952  }
14953 
14954  SCIPdebugMsg(scip, "classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
14955  SCIPdebugPrintCons(scip, cons, NULL);
14956  counter[matched ? SCIP_CONSTYPE_BINPACKING : SCIP_CONSTYPE_KNAPSACK]++;
14957  }
14958 
14959  if( SCIPisInfinity(scip, -consdata->lhs) )
14960  continue;
14961  else
14962  consdata->rhs = SCIPinfinity(scip);
14963  }
14964  }
14965 
14966  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
14967  {
14968  SCIP_Real b;
14969  SCIP_Bool unmatched;
14970 
14971  unmatched = FALSE;
14972 
14973  b = consdata->rhs;
14974  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
14975 
14976  for( i = 0; i < consdata->nvars && !unmatched; i++ )
14977  {
14978  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
14979  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
14980  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
14981  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
14982  }
14983 
14984  if( !unmatched )
14985  {
14986  SCIPdebugMsg(scip, "classified as INTKNAPSACK: ");
14987  SCIPdebugPrintCons(scip, cons, NULL);
14988  counter[SCIP_CONSTYPE_INTKNAPSACK]++;
14989 
14990  if( SCIPisInfinity(scip, -consdata->lhs) )
14991  continue;
14992  else
14993  consdata->rhs = SCIPinfinity(scip);
14994  }
14995  }
14996 
14997  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
14998  {
14999  SCIP_Bool unmatched;
15000 
15001  unmatched = FALSE;
15002  for( i = 0; i < consdata->nvars && !unmatched; i++ )
15003  {
15004  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
15005  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
15006  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
15007  unmatched = TRUE;
15008  }
15009 
15010  if( !unmatched )
15011  {
15012  SCIPdebugMsg(scip, "classified as MIXEDBINARY (%d): ", isRangedRow(scip, cons) ? 2 : 1);
15013  SCIPdebugPrintCons(scip, cons, NULL);
15014  counter[SCIP_CONSTYPE_MIXEDBINARY] += isRangedRow(scip, cons) ? 2 : 1;
15015  continue;
15016  }
15017  }
15018 
15019  /* no special structure detected */
15020  SCIPdebugMsg(scip, "classified as GENERAL: ");
15021  SCIPdebugPrintCons(scip, cons, NULL);
15022  counter[SCIP_CONSTYPE_GENERAL] += isRangedRow(scip, cons) ? 2 : 1;
15023  }
15024 
15025  /* print statistics */
15026  SCIPinfoMessage(scip, NULL, "\n");
15027  SCIPinfoMessage(scip, NULL, "Number of constraints according to type:\n");
15028  SCIPinfoMessage(scip, NULL, "----------------------------------------\n");
15029  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_EMPTY %6d\n", 0, counter[ 0]);
15030  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_FREE %6d\n", 1, counter[ 1]);
15031  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SINGLETON %6d\n", 2, counter[ 2]);
15032  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_AGGREGATION %6d\n", 3, counter[ 3]);
15033  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_VARBOUND %6d\n", 4, counter[ 4]);
15034  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SETPARTITION %6d\n", 5, counter[ 5]);
15035  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SETPACKING %6d\n", 6, counter[ 6]);
15036  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SETCOVERING %6d\n", 7, counter[ 7]);
15037  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_CARDINALITY %6d\n", 8, counter[ 8]);
15038  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_INVKNAPSACK %6d\n", 9, counter[ 9]);
15039  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_EQKNAPSACK %6d\n", 10, counter[10]);
15040  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_BINPACKING %6d\n", 11, counter[11]);
15041  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_KNAPSACK %6d\n", 12, counter[12]);
15042  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_INTKNAPSACK %6d\n", 13, counter[13]);
15043  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_MIXEDBINARY %6d\n", 14, counter[14]);
15044  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_GENERAL %6d\n", 15, counter[15]);
15045  SCIPinfoMessage(scip, NULL, "----------------------------------------\n\n");
15046 
15047  SCIPinfoMessage(scip, NULL, " EMPTY");
15048  SCIPinfoMessage(scip, NULL, " FREE");
15049  SCIPinfoMessage(scip, NULL, " SING");
15050  SCIPinfoMessage(scip, NULL, " AGGR");
15051  SCIPinfoMessage(scip, NULL, " VARBD");
15052  SCIPinfoMessage(scip, NULL, " SETPART");
15053  SCIPinfoMessage(scip, NULL, " SETPACK");
15054  SCIPinfoMessage(scip, NULL, " SETCOV");
15055  SCIPinfoMessage(scip, NULL, " CARD");
15056  SCIPinfoMessage(scip, NULL, " INVKNAP");
15057  SCIPinfoMessage(scip, NULL, " EQKNAP");
15058  SCIPinfoMessage(scip, NULL, " BINPACK");
15059  SCIPinfoMessage(scip, NULL, " KNAP");
15060  SCIPinfoMessage(scip, NULL, " INTKNAP");
15061  SCIPinfoMessage(scip, NULL, " MIXBIN");
15062  SCIPinfoMessage(scip, NULL, " GEN\n");
15063  for( c = 0; c <= (int)SCIP_CONSTYPE_GENERAL; c++ )
15064  {
15065  SCIPinfoMessage(scip, NULL, "%9d", counter[c]);
15066  }
15067 
15068  SCIPinfoMessage(scip, NULL, "\n\n");
15069  SCIPinfoMessage(scip, NULL, "----------------------------------------\n\n");
15070 
15071  return SCIP_OKAY;
15072 }
15073 #endif
15074 
15075 
15076 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
15077 static
15078 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
15079 { /*lint --e{715}*/
15080  int c;
15081 #ifdef SCIP_STATISTIC
15082  SCIP_CONSHDLRDATA* conshdlrdata;
15083  int ngoodconss;
15084  int nallconss;
15085 #endif
15086 
15087  /* delete all linear constraints that were upgraded to a more specific constraint type;
15088  * make sure, only active variables remain in the remaining constraints
15089  */
15090  assert(scip != NULL);
15091 
15092 #ifdef SCIP_STATISTIC
15093  /* count number of well behaved linear constraints */
15094  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15095  assert(conshdlrdata != NULL);
15096 
15097  ngoodconss = 0;
15098  nallconss = 0;
15099 
15100  for( c = 0; c < nconss; ++c )
15101  {
15102  SCIP_CONSDATA* consdata;
15103 
15104  if( SCIPconsIsDeleted(conss[c]) )
15105  continue;
15106 
15107  consdata = SCIPconsGetData(conss[c]);
15108  assert(consdata != NULL);
15109 
15110  if( consdata->upgraded )
15111  continue;
15112 
15113  nallconss++;
15114 
15115  consdataRecomputeMaxActivityDelta(scip, consdata);
15116 
15117  if( SCIPisLT(scip, consdata->maxactdelta, conshdlrdata->maxeasyactivitydelta) )
15118  ngoodconss++;
15119  }
15120  if( nallconss )
15121  {
15122  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
15123  }
15124 #endif
15125 
15126  for( c = 0; c < nconss; ++c )
15127  {
15128  SCIP_CONSDATA* consdata;
15129 
15130  if( SCIPconsIsDeleted(conss[c]) )
15131  continue;
15132 
15133  consdata = SCIPconsGetData(conss[c]);
15134  assert(consdata != NULL);
15135 
15136  if( consdata->upgraded )
15137  {
15138  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
15139  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
15140  */
15141  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
15142  }
15143  else
15144  {
15145  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
15146  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
15147  }
15148  }
15149 
15150  return SCIP_OKAY;
15151 }
15152 
15153 
15154 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
15155 static
15156 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
15157 { /*lint --e{715}*/
15158  int c;
15159 
15160  assert(scip != NULL);
15161 
15162  /* release the rows of all constraints */
15163  for( c = 0; c < nconss; ++c )
15164  {
15165  SCIP_CONSDATA* consdata;
15166 
15167  consdata = SCIPconsGetData(conss[c]);
15168  assert(consdata != NULL);
15169 
15170  if( consdata->row != NULL )
15171  {
15172  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15173  }
15174  }
15175 
15176  /* if this is a restart, convert cutpool rows into linear constraints */
15177  if( restart )
15178  {
15179  int ncutsadded;
15180 
15181  ncutsadded = 0;
15182 
15183  /* create out of all active cuts in cutpool linear constraints */
15184  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
15185 
15186  if( ncutsadded > 0 )
15187  {
15189  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
15190  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
15191  * line correctly
15192  */
15194  }
15195  }
15196 
15197  return SCIP_OKAY;
15198 }
15199 
15200 
15201 /** frees specific constraint data */
15202 static
15203 SCIP_DECL_CONSDELETE(consDeleteLinear)
15204 { /*lint --e{715}*/
15205  SCIP_CONSHDLRDATA* conshdlrdata;
15206 
15207  assert(scip != NULL);
15208  assert(conshdlr != NULL);
15209  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15210 
15211  /* check for event handler */
15212  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15213  assert(conshdlrdata != NULL);
15214  assert(conshdlrdata->eventhdlr != NULL);
15215 
15216  /* free event datas */
15217  if( (*consdata)->eventdata != NULL )
15218  {
15219  /* drop bound change events of variables */
15220  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
15221  }
15222  assert((*consdata)->eventdata == NULL);
15223 
15224  /* free linear constraint */
15225  SCIP_CALL( consdataFree(scip, consdata) );
15226 
15227  return SCIP_OKAY;
15228 }
15229 
15230 
15231 /** transforms constraint data into data belonging to the transformed problem */
15232 static
15233 SCIP_DECL_CONSTRANS(consTransLinear)
15234 { /*lint --e{715}*/
15235  SCIP_CONSDATA* sourcedata;
15236  SCIP_CONSDATA* targetdata;
15237 
15238  /*debugMsg(scip, "Trans method of linear constraints\n");*/
15239 
15240  assert(scip != NULL);
15241  assert(conshdlr != NULL);
15242  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15243  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
15244  assert(sourcecons != NULL);
15245  assert(targetcons != NULL);
15246 
15247  sourcedata = SCIPconsGetData(sourcecons);
15248  assert(sourcedata != NULL);
15249  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
15251  /* create linear constraint data for target constraint */
15252  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
15253 
15254  /* create target constraint */
15255  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
15256  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
15257  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
15258  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
15259  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
15260 
15261  return SCIP_OKAY;
15262 }
15263 
15264 
15265 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
15266 static
15267 SCIP_DECL_CONSINITLP(consInitlpLinear)
15268 { /*lint --e{715}*/
15269  int c;
15270 
15271  assert(scip != NULL);
15272  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15273 
15274  *infeasible = FALSE;
15275 
15276  for( c = 0; c < nconss && !(*infeasible); ++c )
15277  {
15278  assert(SCIPconsIsInitial(conss[c]));
15279  SCIP_CALL( addRelaxation(scip, conss[c], NULL, infeasible) );
15280  }
15281 
15282  return SCIP_OKAY;
15283 }
15285 
15286 /** separation method of constraint handler for LP solutions */
15287 static
15288 SCIP_DECL_CONSSEPALP(consSepalpLinear)
15289 { /*lint --e{715}*/
15290  SCIP_CONSHDLRDATA* conshdlrdata;
15291  SCIP_Real loclowerbound;
15292  SCIP_Real glblowerbound;
15293  SCIP_Real cutoffbound;
15294  SCIP_Real maxbound;
15295  SCIP_Bool separatecards;
15296  SCIP_Bool cutoff;
15297  int c;
15298  int depth;
15299  int nrounds;
15300  int maxsepacuts;
15301  int ncuts;
15302 
15303  assert(scip != NULL);
15304  assert(conshdlr != NULL);
15305  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15306  assert(result != NULL);
15307 
15308  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15309  assert(conshdlrdata != NULL);
15310  depth = SCIPgetDepth(scip);
15311  nrounds = SCIPgetNSepaRounds(scip);
15312 
15313  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15314 
15315  *result = SCIP_DIDNOTRUN;
15316 
15317  /* only call the separator a given number of times at each node */
15318  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15319  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15320  return SCIP_OKAY;
15321 
15322  /* get the maximal number of cuts allowed in a separation round */
15323  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15324 
15325  /* check if we want to produce knapsack cardinality cuts at this node */
15326  loclowerbound = SCIPgetLocalLowerbound(scip);
15327  glblowerbound = SCIPgetLowerbound(scip);
15328  cutoffbound = SCIPgetCutoffbound(scip);
15329  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
15330  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
15331  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
15332 
15333  *result = SCIP_DIDNOTFIND;
15334  ncuts = 0;
15335  cutoff = FALSE;
15336 
15337  /* check all useful linear constraints for feasibility */
15338  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15339  {
15340  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15341  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
15342  }
15343 
15344  /* adjust return value */
15345  if( cutoff )
15346  *result = SCIP_CUTOFF;
15347  else if( ncuts > 0 )
15348  *result = SCIP_SEPARATED;
15349 
15350  /* combine linear constraints to get more cuts */
15351  /**@todo further cuts of linear constraints */
15352 
15353  return SCIP_OKAY;
15354 }
15355 
15356 
15357 /** separation method of constraint handler for arbitrary primal solutions */
15358 static
15359 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
15360 { /*lint --e{715}*/
15361  SCIP_CONSHDLRDATA* conshdlrdata;
15362  int c;
15363  int depth;
15364  int nrounds;
15365  int maxsepacuts;
15366  int ncuts;
15367  SCIP_Bool cutoff;
15368 
15369  assert(scip != NULL);
15370  assert(conshdlr != NULL);
15371  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15372  assert(result != NULL);
15373 
15374  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15375  assert(conshdlrdata != NULL);
15376  depth = SCIPgetDepth(scip);
15377  nrounds = SCIPgetNSepaRounds(scip);
15378 
15379  /*debugMsg(scip, "Sepa method of linear constraints\n");*/
15380 
15381  *result = SCIP_DIDNOTRUN;
15382 
15383  /* only call the separator a given number of times at each node */
15384  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
15385  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
15386  return SCIP_OKAY;
15387 
15388  /* get the maximal number of cuts allowed in a separation round */
15389  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
15390 
15391  *result = SCIP_DIDNOTFIND;
15392  ncuts = 0;
15393  cutoff = FALSE;
15394 
15395  /* check all useful linear constraints for feasibility */
15396  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
15397  {
15398  /*debugMsg(scip, "separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
15399  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
15400  }
15401 
15402  /* adjust return value */
15403  if( cutoff )
15404  *result = SCIP_CUTOFF;
15405  else if( ncuts > 0 )
15406  *result = SCIP_SEPARATED;
15407 
15408  /* combine linear constraints to get more cuts */
15409  /**@todo further cuts of linear constraints */
15410 
15411  return SCIP_OKAY;
15412 }
15413 
15414 
15415 /** constraint enforcing method of constraint handler for LP solutions */
15416 static
15417 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
15418 { /*lint --e{715}*/
15419  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, NULL, result) );
15420 
15421  return SCIP_OKAY;
15422 }
15423 
15424 /** constraint enforcing method of constraint handler for relaxation solutions */
15425 static
15426 SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
15427 { /*lint --e{715}*/
15428  SCIP_CALL( enforceConstraint(scip, conshdlr, conss, nconss, nusefulconss, sol, result) );
15429 
15430  return SCIP_OKAY;
15431 }
15432 
15433 /** constraint enforcing method of constraint handler for pseudo solutions */
15434 static
15435 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
15436 { /*lint --e{715}*/
15437  SCIP_CONSHDLRDATA* conshdlrdata;
15438  SCIP_Bool checkrelmaxabs;
15439  SCIP_Bool violated;
15440  int c;
15441 
15442  assert(scip != NULL);
15443  assert(conshdlr != NULL);
15444  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15445  assert(result != NULL);
15446 
15447  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15448  assert(conshdlrdata != NULL);
15449 
15450  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15451 
15452  SCIPdebugMsg(scip, "Enfops method of linear constraints\n");
15453 
15454  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
15455  if( objinfeasible )
15456  {
15457  SCIPdebugMsg(scip, "-> pseudo solution is objective infeasible, return.\n");
15458 
15459  *result = SCIP_DIDNOTRUN;
15460  return SCIP_OKAY;
15461  }
15462 
15463  /* check all linear constraints for feasibility */
15464  violated = FALSE;
15465  for( c = 0; c < nconss && !violated; ++c )
15466  {
15467  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
15468  }
15469 
15470  if( violated )
15471  *result = SCIP_INFEASIBLE;
15472  else
15473  *result = SCIP_FEASIBLE;
15474 
15475  SCIPdebugMsg(scip, "-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
15476 
15477  return SCIP_OKAY;
15478 }
15479 
15480 
15481 /** feasibility check method of constraint handler for integral solutions */
15482 static
15483 SCIP_DECL_CONSCHECK(consCheckLinear)
15484 { /*lint --e{715}*/
15485  SCIP_CONSHDLRDATA* conshdlrdata;
15486  SCIP_Bool checkrelmaxabs;
15487  int c;
15488 
15489  assert(scip != NULL);
15490  assert(conshdlr != NULL);
15491  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15492  assert(result != NULL);
15493 
15494  *result = SCIP_FEASIBLE;
15495 
15496  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15497  assert(conshdlrdata != NULL);
15498 
15499  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
15501  /*debugMsg(scip, "Check method of linear constraints\n");*/
15502 
15503  /* check all linear constraints for feasibility */
15504  for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
15505  {
15506  SCIP_Bool violated = FALSE;
15507  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
15508 
15509  if( violated )
15510  {
15511  *result = SCIP_INFEASIBLE;
15512 
15513  if( printreason )
15514  {
15515  SCIP_CONSDATA* consdata;
15516  SCIP_Real activity;
15517 
15518  consdata = SCIPconsGetData(conss[c]);
15519  assert( consdata != NULL);
15520 
15521  activity = consdataGetActivity(scip, consdata, sol);
15522 
15523  SCIP_CALL( SCIPprintCons(scip, conss[c], NULL ) );
15524  SCIPinfoMessage(scip, NULL, ";\n");
15525 
15526  if( activity == SCIP_INVALID ) /*lint !e777*/
15527  SCIPinfoMessage(scip, NULL, "activity invalid due to positive and negative infinity contributions\n");
15528  else if( SCIPisFeasLT(scip, activity, consdata->lhs) )
15529  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
15530  else if( SCIPisFeasGT(scip, activity, consdata->rhs) )
15531  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
15532  }
15533  }
15534  }
15535 
15536  return SCIP_OKAY;
15537 }
15538 
15539 
15540 /** domain propagation method of constraint handler */
15541 static
15542 SCIP_DECL_CONSPROP(consPropLinear)
15543 { /*lint --e{715}*/
15544  SCIP_CONSHDLRDATA* conshdlrdata;
15545  SCIP_Bool rangedrowpropagation = FALSE;
15546  SCIP_Bool tightenbounds;
15547  SCIP_Bool cutoff;
15548 
15549  int nchgbds;
15550  int i;
15551 
15552  assert(scip != NULL);
15553  assert(conshdlr != NULL);
15554  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15555  assert(result != NULL);
15556 
15557  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15558  assert(conshdlrdata != NULL);
15560  /*debugMsg(scip, "Prop method of linear constraints\n");*/
15561 
15562  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
15563  if( SCIPinProbing(scip) )
15564  tightenbounds = TRUE;
15565  else
15566  {
15567  int depth;
15568  int propfreq;
15569  int tightenboundsfreq;
15570  int rangedrowfreq;
15571 
15572  depth = SCIPgetDepth(scip);
15573  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
15574  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
15575  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
15576  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
15577 
15578  /* check if we want to do ranged row propagation */
15579  rangedrowpropagation = conshdlrdata->rangedrowpropagation;
15580  rangedrowpropagation = rangedrowpropagation && !SCIPinRepropagation(scip);
15581  rangedrowpropagation = rangedrowpropagation && (depth <= conshdlrdata->rangedrowmaxdepth);
15582  rangedrowfreq = propfreq * conshdlrdata->rangedrowfreq;
15583  rangedrowpropagation = rangedrowpropagation && (depth % rangedrowfreq == 0);
15584  }
15585 
15586  cutoff = FALSE;
15587  nchgbds = 0;
15588 
15589  /* process constraints marked for propagation */
15590  for( i = 0; i < nmarkedconss && !cutoff; i++ )
15591  {
15592  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
15593  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, rangedrowpropagation,
15594  conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, &nchgbds) );
15595  }
15596 
15597  /* adjust result code */
15598  if( cutoff )
15599  *result = SCIP_CUTOFF;
15600  else if( nchgbds > 0 )
15601  *result = SCIP_REDUCEDDOM;
15602  else
15603  *result = SCIP_DIDNOTFIND;
15604 
15605  return SCIP_OKAY;
15606 }
15607 
15608 
15609 #define MAXCONSPRESOLROUNDS 10
15610 /** presolving method of constraint handler */
15611 static
15612 SCIP_DECL_CONSPRESOL(consPresolLinear)
15613 { /*lint --e{715}*/
15614  SCIP_CONSHDLRDATA* conshdlrdata;
15615  SCIP_CONS* cons;
15616  SCIP_CONSDATA* consdata;
15617  SCIP_Real minactivity;
15618  SCIP_Real maxactivity;
15619  SCIP_Bool minactisrelax;
15620  SCIP_Bool maxactisrelax;
15621  SCIP_Bool cutoff;
15622  int oldnfixedvars;
15623  int oldnaggrvars;
15624  int oldnchgbds;
15625  int oldndelconss;
15626  int oldnupgdconss;
15627  int oldnchgcoefs;
15628  int oldnchgsides;
15629  int firstchange;
15630  int firstupgradetry;
15631  int c;
15632 
15633  assert(scip != NULL);
15634  assert(conshdlr != NULL);
15635  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
15636  assert(result != NULL);
15637 
15638  /*debugMsg(scip, "Presol method of linear constraints\n");*/
15639 
15640  /* remember old preprocessing counters */
15641  cutoff = FALSE;
15642  oldnfixedvars = *nfixedvars;
15643  oldnaggrvars = *naggrvars;
15644  oldnchgbds = *nchgbds;
15645  oldndelconss = *ndelconss;
15646  oldnupgdconss = *nupgdconss;
15647  oldnchgcoefs = *nchgcoefs;
15648  oldnchgsides = *nchgsides;
15649 
15650  /* get constraint handler data */
15651  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15652  assert(conshdlrdata != NULL);
15653 
15654  /* process single constraints */
15655  firstchange = INT_MAX;
15656  firstupgradetry = INT_MAX;
15657  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
15658  {
15659  int npresolrounds;
15660  SCIP_Bool infeasible;
15661 
15662  infeasible = FALSE;
15663 
15664  cons = conss[c];
15665  assert(SCIPconsIsActive(cons));
15666  consdata = SCIPconsGetData(cons);
15667  assert(consdata != NULL);
15668 
15669  /* constraint should not be already presolved in the initial round */
15670  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || SCIPconsIsMarkedPropagate(cons));
15671  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || consdata->boundstightened == 0);
15672  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
15673  assert(!SCIPconsIsMarkedPropagate(cons) || !consdata->presolved);
15674 
15675  /* incorporate fixings and aggregations in constraint */
15676  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
15677 
15678  if( infeasible )
15679  {
15680  SCIPdebugMsg(scip, " -> infeasible fixing\n");
15681  cutoff = TRUE;
15682  break;
15683  }
15684 
15685  assert(consdata->removedfixings);
15686 
15687  /* we can only presolve linear constraints, that are not modifiable */
15688  if( SCIPconsIsModifiable(cons) )
15689  continue;
15690 
15691  /* remember the first changed constraint to begin the next aggregation round with */
15692  if( firstchange == INT_MAX && consdata->changed )
15693  firstchange = c;
15694 
15695  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
15696  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
15697  firstupgradetry = c;
15698 
15699  /* check, if constraint is already preprocessed */
15700  if( consdata->presolved )
15701  continue;
15702 
15703  assert(SCIPconsIsActive(cons));
15704 
15705  SCIPdebugMsg(scip, "presolving linear constraint <%s>\n", SCIPconsGetName(cons));
15706  SCIPdebugPrintCons(scip, cons, NULL);
15707 
15708  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
15709  * to avoid nearly infinite cycling due to very small bound changes)
15710  */
15711  npresolrounds = 0;
15712  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
15713  {
15714  assert(!cutoff);
15715  npresolrounds++;
15716 
15717  /* mark constraint being presolved and propagated */
15718  consdata->presolved = TRUE;
15719  SCIP_CALL( SCIPunmarkConsPropagate(scip, cons) );
15720 
15721  /* normalize constraint */
15722  SCIP_CALL( normalizeCons(scip, cons) );
15723 
15724  /* tighten left and right hand side due to integrality */
15725  SCIP_CALL( tightenSides(scip, cons, nchgsides) );
15726 
15727  /* check bounds */
15728  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
15729  {
15730  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
15731  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
15732  cutoff = TRUE;
15733  break;
15734  }
15735 
15736  /* tighten variable's bounds */
15737  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars, &cutoff, nchgbds) );
15738  if( cutoff )
15739  break;
15740 
15741  /* check for fixed variables */
15742  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
15743  if( cutoff )
15744  break;
15745 
15746  /* check constraint for infeasibility and redundancy */
15747  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
15748  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
15749  {
15750  SCIPdebugMsg(scip, "linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
15751  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
15752  cutoff = TRUE;
15753  break;
15754  }
15755  else if( SCIPisFeasGE(scip, minactivity, consdata->lhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
15756  {
15757  SCIPdebugMsg(scip, "linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
15758  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
15759  SCIP_CALL( SCIPdelCons(scip, cons) );
15760  assert(!SCIPconsIsActive(cons));
15761 
15762  if( !consdata->upgraded )
15763  (*ndelconss)++;
15764  break;
15765  }
15766  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasGE(scip, minactivity, consdata->lhs) )
15767  {
15768  SCIPdebugMsg(scip, "linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
15769  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
15770  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
15771  if( !consdata->upgraded )
15772  (*nchgsides)++;
15773  }
15774  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
15775  {
15776  SCIPdebugMsg(scip, "linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
15777  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
15778  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
15779  if( !consdata->upgraded )
15780  (*nchgsides)++;
15781  }
15782  assert(consdata->nvars >= 1); /* otherwise, it should be redundant or infeasible */
15783 
15784  /* handle empty constraint */
15785  if( consdata->nvars == 0 )
15786  {
15787  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
15788  {
15789  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
15790  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
15791  cutoff = TRUE;
15792  }
15793  else
15794  {
15795  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
15796  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
15797  SCIP_CALL( SCIPdelCons(scip, cons) );
15798  assert(!SCIPconsIsActive(cons));
15799 
15800  if( !consdata->upgraded )
15801  (*ndelconss)++;
15802  }
15803  break;
15804  }
15805 
15806  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
15807  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
15808 
15809  /* try to simplify inequalities */
15810  if( conshdlrdata->simplifyinequalities )
15811  {
15812  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides) );
15813  }
15814 
15815  /* aggregation variable in equations */
15816  if( conshdlrdata->aggregatevariables )
15817  {
15818  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
15819  if( cutoff )
15820  break;
15821  }
15822  }
15823 
15824  if( !cutoff && !SCIPisStopped(scip) )
15825  {
15826  /* perform ranged row propagation */
15827  if( conshdlrdata->rangedrowpropagation )
15828  {
15829  int lastnfixedvars;
15830 
15831  lastnfixedvars = *nfixedvars;
15832 
15833  SCIP_CALL( rangedRowPropagation(scip, cons, &cutoff, nfixedvars, nchgbds, naddconss) );
15834  if( !cutoff )
15835  {
15836  if( lastnfixedvars < *nfixedvars )
15837  {
15838  SCIP_CALL( applyFixings(scip, cons, &cutoff) );
15839  }
15840  }
15841  }
15842 
15843  /* extract cliques from constraint */
15844  if( !cutoff && SCIPconsIsActive(cons) )
15845  {
15846  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->maxeasyactivitydelta, conshdlrdata->sortvars,
15847  nfixedvars, nchgbds, &cutoff) );
15848 
15849  /* check if the constraint got redundant or infeasible */
15850  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
15851  {
15852  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
15853  {
15854  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
15855  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
15856  cutoff = TRUE;
15857  }
15858  else
15859  {
15860  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
15861  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
15862  SCIP_CALL( SCIPdelCons(scip, cons) );
15863  assert(!SCIPconsIsActive(cons));
15864 
15865  if( !consdata->upgraded )
15866  (*ndelconss)++;
15867  }
15868  }
15869  }
15870 
15871  /* convert special equalities */
15872  if( !cutoff && SCIPconsIsActive(cons) )
15873  {
15874  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
15875  }
15876 
15877  /* apply dual presolving for variables that appear in only one constraint */
15878  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving && SCIPallowDualReds(scip) )
15879  {
15880  SCIP_CALL( dualPresolve(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
15881  }
15882 
15883  /* check if an inequality is parallel to the objective function */
15884  if( !cutoff && SCIPconsIsActive(cons) )
15885  {
15886  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
15887  }
15888 
15889  /* remember the first changed constraint to begin the next aggregation round with */
15890  if( firstchange == INT_MAX && consdata->changed )
15891  firstchange = c;
15892 
15893  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
15894  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
15895  firstupgradetry = c;
15896  }
15897 
15898  /* singleton column stuffing */
15899  if( !cutoff && SCIPconsIsActive(cons) && SCIPconsIsChecked(cons) &&
15900  (conshdlrdata->singletonstuffing || conshdlrdata->singlevarstuffing) && SCIPallowDualReds(scip) )
15901  {
15902  SCIP_CALL( presolStuffing(scip, cons, conshdlrdata->singletonstuffing,
15903  conshdlrdata->singlevarstuffing, &cutoff, nfixedvars, nchgbds) );
15904 
15905  /* handle empty constraint */
15906  if( consdata->nvars == 0 )
15907  {
15908  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
15909  {
15910  SCIPdebugMsg(scip, "empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
15911  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
15912  cutoff = TRUE;
15913  }
15914  else
15915  {
15916  SCIPdebugMsg(scip, "empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
15917  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
15918  SCIP_CALL( SCIPdelCons(scip, cons) );
15919  assert(!SCIPconsIsActive(cons));
15920 
15921  if( !consdata->upgraded )
15922  (*ndelconss)++;
15923  }
15924  break;
15925  }
15926  }
15927  }
15928 
15929  /* process pairs of constraints: check them for redundancy and try to aggregate them;
15930  * only apply this expensive procedure in exhaustive presolving timing
15931  */
15932  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
15933  {
15934  assert(firstchange >= 0);
15935 
15936  if( firstchange < nconss && conshdlrdata->presolusehashing )
15937  {
15938  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
15939  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
15940  ndelconss, nchgsides) );
15941  }
15942 
15943  if( firstchange < nconss && conshdlrdata->presolpairwise )
15944  {
15945  SCIP_CONS** usefulconss;
15946  int nusefulconss;
15947  int firstchangenew;
15948  SCIP_Longint npaircomparisons;
15949 
15950  npaircomparisons = 0;
15951  oldndelconss = *ndelconss;
15952  oldnchgsides = *nchgsides;
15953  oldnchgcoefs = *nchgcoefs;
15954 
15955  /* allocate temporary memory */
15956  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
15957 
15958  nusefulconss = 0;
15959  firstchangenew = -1;
15960  for( c = 0; c < nconss; ++c )
15961  {
15962  /* update firstchange */
15963  if( c == firstchange )
15964  firstchangenew = nusefulconss;
15965 
15966  /* ignore inactive and modifiable constraints */
15967  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
15968  continue;
15969 
15970  usefulconss[nusefulconss] = conss[c];
15971  ++nusefulconss;
15972  }
15973  firstchange = firstchangenew;
15974  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
15975 
15976  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
15977  {
15978  /* constraint has become inactive or modifiable during pairwise presolving */
15979  if( usefulconss[c] == NULL )
15980  continue;
15981 
15982  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
15983 
15984  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
15985  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
15986  &cutoff, ndelconss, nchgsides, nchgcoefs) );
15987 
15988  if( npaircomparisons > conshdlrdata->nmincomparisons )
15989  {
15990  assert(npaircomparisons > 0);
15991  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
15992  break;
15993  oldndelconss = *ndelconss;
15994  oldnchgsides = *nchgsides;
15995  oldnchgcoefs = *nchgcoefs;
15996  npaircomparisons = 0;
15997  }
15998  }
15999  /* free temporary memory */
16000  SCIPfreeBufferArray(scip, &usefulconss);
16001  }
16002  }
16003 
16004  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
16005  * in linear constraints and we therefore have full information about it
16006  */
16007  if( !cutoff && firstupgradetry < nconss
16008  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
16009  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
16010  )
16011  {
16012  if( conshdlrdata->dualpresolving && SCIPallowDualReds(scip) && !SCIPisStopped(scip) )
16013  {
16014  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
16015  }
16016  }
16017 
16018  /* try to upgrade constraints into a more specific constraint type;
16019  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
16020  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
16021  */
16022  if( !cutoff && (presoltiming & SCIP_PRESOLTIMING_EXHAUSTIVE) != 0 && SCIPisPresolveFinished(scip) )
16023  {
16024  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
16025  {
16026  cons = conss[c];
16027 
16028  /* don't upgrade modifiable constraints */
16029  if( SCIPconsIsModifiable(cons) )
16030  continue;
16031 
16032  consdata = SCIPconsGetData(cons);
16033  assert(consdata != NULL);
16034 
16035  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
16036  if( consdata->upgradetried )
16037  continue;
16038  /* @todo force that upgrade will be performed later? */
16039  if( !consdata->presolved )
16040  continue;
16041 
16042  consdata->upgradetried = TRUE;
16043  if( SCIPconsIsActive(cons) )
16044  {
16045  SCIP_CONS* upgdcons;
16046 
16047  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16048  if( upgdcons != NULL )
16049  {
16050  /* add the upgraded constraint to the problem */
16051  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
16052  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
16053  (*nupgdconss)++;
16054 
16055  /* mark the linear constraint being upgraded and to be removed after presolving;
16056  * don't delete it directly, because it may help to preprocess other linear constraints
16057  */
16058  assert(!consdata->upgraded);
16059  consdata->upgraded = TRUE;
16060 
16061  /* delete upgraded inequalities immediately;
16062  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
16063  */
16064  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
16065  || !conshdlrdata->presolpairwise
16066  || (conshdlrdata->maxaggrnormscale == 0.0) )
16067  {
16068  SCIP_CALL( SCIPdelCons(scip, cons) );
16069  }
16070  }
16071  }
16072  }
16073  }
16074 
16075  /* return the correct result code */
16076  if( cutoff )
16077  *result = SCIP_CUTOFF;
16078  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
16079  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
16080  *result = SCIP_SUCCESS;
16081  else
16082  *result = SCIP_DIDNOTFIND;
16083 
16084  return SCIP_OKAY;
16085 }
16086 
16087 
16088 /** propagation conflict resolving method of constraint handler */
16089 static
16090 SCIP_DECL_CONSRESPROP(consRespropLinear)
16091 { /*lint --e{715}*/
16092 
16093  assert(scip != NULL);
16094  assert(cons != NULL);
16095  assert(result != NULL);
16096 
16097  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
16098 
16099  return SCIP_OKAY;
16100 }
16101 
16102 
16103 /** variable rounding lock method of constraint handler */
16104 static
16105 SCIP_DECL_CONSLOCK(consLockLinear)
16106 { /*lint --e{715}*/
16107  SCIP_CONSDATA* consdata;
16108  SCIP_Bool haslhs;
16109  SCIP_Bool hasrhs;
16110  int i;
16111 
16112  assert(scip != NULL);
16113  assert(cons != NULL);
16114  consdata = SCIPconsGetData(cons);
16115  assert(consdata != NULL);
16116 
16117  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
16118  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
16119 
16120  /* update rounding locks of every single variable */
16121  for( i = 0; i < consdata->nvars; ++i )
16122  {
16123  if( SCIPisPositive(scip, consdata->vals[i]) )
16124  {
16125  if( haslhs )
16126  {
16127  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
16128  }
16129  if( hasrhs )
16130  {
16131  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksneg, nlockspos) );
16132  }
16133  }
16134  else
16135  {
16136  if( haslhs )
16137  {
16138  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksneg, nlockspos) );
16139  }
16140  if( hasrhs )
16141  {
16142  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
16143  }
16144  }
16145  }
16146 
16147  return SCIP_OKAY;
16148 }
16149 
16150 
16151 /** variable deletion method of constraint handler */
16152 static
16153 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
16154 {
16155  assert(scip != NULL);
16156  assert(conshdlr != NULL);
16157  assert(conss != NULL || nconss == 0);
16158 
16159  if( nconss > 0 )
16160  {
16161  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
16162  }
16163 
16164  return SCIP_OKAY;
16165 }
16166 
16167 /** constraint display method of constraint handler */
16168 static
16169 SCIP_DECL_CONSPRINT(consPrintLinear)
16170 { /*lint --e{715}*/
16171  assert(scip != NULL);
16172  assert(conshdlr != NULL);
16173  assert(cons != NULL);
16174 
16175  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
16176 
16177  return SCIP_OKAY;
16178 }
16179 
16180 /** constraint copying method of constraint handler */
16181 static
16182 SCIP_DECL_CONSCOPY(consCopyLinear)
16183 { /*lint --e{715}*/
16184  SCIP_VAR** sourcevars;
16185  SCIP_Real* sourcecoefs;
16186  const char* consname;
16187  int nvars;
16188 
16189  assert(scip != NULL);
16190  assert(sourcescip != NULL);
16191  assert(sourcecons != NULL);
16192 
16193  /* get variables and coefficients of the source constraint */
16194  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
16195  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
16196  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
16197 
16198  if( name != NULL )
16199  consname = name;
16200  else
16201  consname = SCIPconsGetName(sourcecons);
16202 
16203  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
16204  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
16205  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
16206  assert(cons != NULL || *valid == FALSE);
16207 
16208  return SCIP_OKAY;
16209 }
16210 
16211 /* find operators '<=', '==', '>=', [free] in input string and return those places. There should only be one operator,
16212  * except for ranged rows for which exactly two operators '<=' must be present
16213  */
16214 static
16216  const char* str, /**< null terminated input string */
16217  char** firstoperator, /**< pointer to store the string starting at the first operator */
16218  char** secondoperator, /**< pointer to store the string starting at the second operator */
16219  SCIP_Bool* success /**< pointer to store if the line contains a valid operator order */
16220  )
16221 {
16222  char* curr;
16223 
16224  assert(str != NULL);
16225  assert(firstoperator != NULL);
16226  assert(secondoperator != NULL);
16227 
16228  *firstoperator = NULL;
16229  *secondoperator = NULL;
16230 
16231  curr = (char*)str;
16232  *success = TRUE;
16233 
16234  /* loop over the input string to find all operators */
16235  while( *curr && *success )
16236  {
16237  SCIP_Bool found = FALSE;
16238  int increment = 1;
16239 
16240  /* try if we found a possible operator */
16241  switch( *curr )
16242  {
16243  case '<':
16244  case '=':
16245  case '>':
16246 
16247  /* check if the two characters curr[0,1] form an operator together */
16248  if( curr[1] == '=' )
16249  {
16250  found = TRUE;
16251 
16252  /* update increment to continue after this operator */
16253  increment = 2;
16254  }
16255  break;
16256  case '[':
16257  if( strncmp(curr, "[free]", 6) == 0 )
16258  {
16259  found = TRUE;
16260 
16261  /* update increment to continue after this operator */
16262  increment = 6;
16263  }
16264  break;
16265  default:
16266  break;
16267 
16268  }
16269 
16270  /* assign the found operator to the first or second pointer and check for violations of the linear constraint grammar */
16271  if( found )
16272  {
16273  if( *firstoperator == NULL )
16274  {
16275  *firstoperator = curr;
16276  }
16277  else
16278  {
16279  if( *secondoperator != NULL )
16280  {
16281  SCIPerrorMessage("Found more than two operators in line %s\n", str);
16282  *success = FALSE;
16283  }
16284  else if( strncmp(*firstoperator, "<=", 2) != 0 )
16285  {
16286  SCIPerrorMessage("Two operators in line that is not a ranged row: %s", str);
16287  *success = FALSE;
16288  }
16289  else if( strncmp(curr, "<=", 2) != 0 )
16290  {
16291  SCIPerrorMessage("Bad second operator, expected ranged row specification: %s", str);
16292  *success = FALSE;
16293  }
16294 
16295  *secondoperator = curr;
16296  }
16297  }
16298 
16299  curr += increment;
16300  }
16301 
16302  /* check if we did find at least one operator */
16303  if( *success )
16304  {
16305  if( *firstoperator == NULL )
16306  {
16307  SCIPerrorMessage("Could not find any operator in line %s\n", str);
16308  *success = FALSE;
16309  }
16310  }
16311 
16312  return SCIP_OKAY;
16313 }
16314 
16315 /** constraint parsing method of constraint handler */
16316 static
16317 SCIP_DECL_CONSPARSE(consParseLinear)
16318 { /*lint --e{715}*/
16319  SCIP_VAR** vars;
16320  SCIP_Real* coefs;
16321  int nvars;
16322  int coefssize;
16323  int requsize;
16324  SCIP_Real lhs;
16325  SCIP_Real rhs;
16326  char* endptr;
16327  char* firstop;
16328  char* secondop;
16329  SCIP_Bool operatorsuccess;
16330  char* lhsstrptr;
16331  char* rhsstrptr;
16332  char* varstrptr;
16333 
16334  assert(scip != NULL);
16335  assert(success != NULL);
16336  assert(str != NULL);
16337  assert(name != NULL);
16338  assert(cons != NULL);
16339 
16340  /* set left and right hand side to their default values */
16341  lhs = -SCIPinfinity(scip);
16342  rhs = SCIPinfinity(scip);
16343 
16344  (*success) = FALSE;
16345 
16346  /* return of string empty */
16347  if( !*str )
16348  return SCIP_OKAY;
16349 
16350  /* ignore whitespace */
16351  while( isspace((unsigned char)*str) )
16352  ++str;
16353 
16354  /* find operators in the line first, all other remaining parsing depends on occurence of the operators '<=', '>=', '==',
16355  * and the special word [free]
16356  */
16357  SCIP_CALL( findOperators(str, &firstop, &secondop, &operatorsuccess) );
16358 
16359  /* if the grammar is not valid for parsing a linear constraint, return */
16360  if( ! operatorsuccess )
16361  return SCIP_OKAY;
16362 
16363  varstrptr = (char *)str;
16364  lhsstrptr = rhsstrptr = NULL;
16365  assert(firstop != NULL);
16366 
16367  /* assign the strings for parsing the left hand side, right hand side, and the linear variable sum */
16368  switch( *firstop )
16369  {
16370  case '<':
16371  assert(firstop[1] == '=');
16372  /* we have ranged row lhs <= a_1 x_1 + ... + a_n x_n <= rhs */
16373  if( secondop != NULL )
16374  {
16375  assert(secondop[0] == '<' && secondop[1] == '=');
16376  lhsstrptr = (char *)str;
16377  varstrptr = firstop + 2;
16378  rhsstrptr = secondop + 2;
16379  }
16380  else
16381  {
16382  /* we have an inequality with infinite left hand side a_1 x_1 + ... + a_n x_n <= rhs */
16383  lhsstrptr = NULL;
16384  varstrptr = (char *)str;
16385  rhsstrptr = firstop + 2;
16386  }
16387  break;
16388  case '>':
16389  assert(firstop[1] == '=');
16390  assert(secondop == NULL);
16391  /* we have a_1 x_1 + ... + a_n x_n >= lhs */
16392  lhsstrptr = firstop + 2;
16393  break;
16394  case '=':
16395  assert(firstop[1] == '=');
16396  assert(secondop == NULL);
16397  /* we have a_1 x_1 + ... + a_n x_n == lhs (rhs) */
16398  rhsstrptr = firstop + 2;
16399  lhsstrptr = firstop + 2;
16400  break;
16401  case '[':
16402  assert(strncmp(firstop, "[free]", 6) == 0);
16403  assert(secondop == NULL);
16404  /* nothing to assign in case of a free a_1 x_1 + ... + a_n x_n [free] */
16405  break;
16406  default:
16407  /* it should not be possible that a different character appears in that position */
16408  SCIPerrorMessage("Parsing has wrong operator character '%c', should be one of <=>[", *firstop);
16409  return SCIP_READERROR;
16410  }
16411 
16412  /* parse left hand side, if necessary */
16413  if( lhsstrptr != NULL )
16414  {
16415  if( ! SCIPparseReal(scip, lhsstrptr, &lhs, &endptr) )
16416  {
16417  SCIPerrorMessage("error parsing left hand side number from <%s>\n", lhsstrptr);
16418  return SCIP_OKAY;
16419  }
16420 
16421  /* in case of an equation, assign the left also to the right hand side */
16422  if( rhsstrptr == lhsstrptr )
16423  rhs = lhs;
16424  }
16425 
16426  /* parse right hand side, if different from left hand side */
16427  if( rhsstrptr != NULL && rhsstrptr != lhsstrptr )
16428  {
16429  if( ! SCIPparseReal(scip, rhsstrptr, &rhs, &endptr) )
16430  {
16431  SCIPerrorMessage("error parsing right hand side number from <%s>\n", lhsstrptr);
16432  return SCIP_OKAY;
16433  }
16434  }
16435 
16436  /* initialize buffers for storing the variables and coefficients */
16437  coefssize = 100;
16438  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
16439  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
16440 
16441  assert(varstrptr != NULL);
16442 
16443  /* parse linear sum to get variables and coefficients */
16444  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
16445 
16446  if( *success && requsize > coefssize )
16447  {
16448  /* realloc buffers and try again */
16449  coefssize = requsize;
16450  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
16451  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
16452 
16453  SCIP_CALL( SCIPparseVarsLinearsum(scip, varstrptr, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
16454  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
16455  }
16456 
16457  if( !*success )
16458  {
16459  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", varstrptr);
16460  }
16461  else
16462  {
16463  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
16464  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
16465  }
16466 
16467  SCIPfreeBufferArray(scip, &coefs);
16468  SCIPfreeBufferArray(scip, &vars);
16469 
16470  return SCIP_OKAY;
16471 }
16472 
16473 
16474 /** constraint method of constraint handler which returns the variables (if possible) */
16475 static
16476 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
16477 { /*lint --e{715}*/
16478  SCIP_CONSDATA* consdata;
16479 
16480  consdata = SCIPconsGetData(cons);
16481  assert(consdata != NULL);
16482 
16483  if( varssize < consdata->nvars )
16484  (*success) = FALSE;
16485  else
16486  {
16487  assert(vars != NULL);
16488 
16489  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
16490  (*success) = TRUE;
16491  }
16492 
16493  return SCIP_OKAY;
16494 }
16495 
16496 /**! [Callback for the number of variables]*/
16497 /** constraint method of constraint handler which returns the number of variables (if possible) */
16498 static
16499 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
16500 { /*lint --e{715}*/
16501  SCIP_CONSDATA* consdata;
16502 
16503  consdata = SCIPconsGetData(cons);
16504  assert(consdata != NULL);
16505 
16506  (*nvars) = consdata->nvars;
16507  (*success) = TRUE;
16508 
16509  return SCIP_OKAY;
16510 }
16511 /**! [Callback for the number of variables]*/
16512 
16513 /*
16514  * Callback methods of event handler
16515  */
16517 static
16518 SCIP_DECL_EVENTEXEC(eventExecLinear)
16519 { /*lint --e{715}*/
16520  SCIP_CONS* cons;
16521  SCIP_CONSDATA* consdata;
16522  SCIP_VAR* var;
16523  SCIP_EVENTTYPE eventtype;
16524 
16525  assert(scip != NULL);
16526  assert(eventhdlr != NULL);
16527  assert(eventdata != NULL);
16528  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
16529  assert(event != NULL);
16530 
16531  cons = eventdata->cons;
16532  assert(cons != NULL);
16533  consdata = SCIPconsGetData(cons);
16534  assert(consdata != NULL);
16536  /* we can skip events droped for deleted constraints */
16537  if( SCIPconsIsDeleted(cons) )
16538  return SCIP_OKAY;
16539 
16540  eventtype = SCIPeventGetType(event);
16541  var = SCIPeventGetVar(event);
16542 
16543  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
16544  {
16545  SCIP_Real oldbound;
16546  SCIP_Real newbound;
16547  SCIP_Real val;
16548  int varpos;
16549 
16550  varpos = eventdata->varpos;
16551  assert(0 <= varpos && varpos < consdata->nvars);
16552  oldbound = SCIPeventGetOldbound(event);
16553  newbound = SCIPeventGetNewbound(event);
16554  assert(var != NULL);
16555  assert(consdata->vars[varpos] == var);
16556  val = consdata->vals[varpos];
16557 
16558  /* we only need to update the activities if the constraint is active,
16559  * otherwise we mark them to be invalid
16560  */
16561  if( SCIPconsIsActive(cons) )
16562  {
16563  /* update the activity values */
16564  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
16565  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
16566  else
16567  {
16568  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
16569  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
16570  }
16571  }
16572  else
16573  consdataInvalidateActivities(consdata);
16574 
16575  consdata->presolved = FALSE;
16576  consdata->rangedrowpropagated = 0;
16577 
16578  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
16579  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
16580  {
16581  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
16582 
16583  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
16584  if( consdata->maxactdeltavar == var )
16585  {
16586  consdata->maxactdelta = SCIP_INVALID;
16587  consdata->maxactdeltavar = NULL;
16588  }
16589 
16590  /* check whether bound tightening might now be successful */
16591  if( consdata->boundstightened > 0)
16592  {
16593  switch( eventtype )
16594  {
16596  if( (val > 0.0 ? !SCIPisInfinity(scip, consdata->rhs) : !SCIPisInfinity(scip, -consdata->lhs)) )
16597  consdata->boundstightened = 0;
16598  break;
16600  if( (val > 0.0 ? !SCIPisInfinity(scip, -consdata->lhs) : !SCIPisInfinity(scip, consdata->rhs)) )
16601  consdata->boundstightened = 0;
16602  break;
16603  default:
16604  SCIPerrorMessage("invalid event type %d\n", eventtype);
16605  return SCIP_INVALIDDATA;
16606  }
16607  }
16608  }
16609  /* update maximal activity delta if a bound was relaxed */
16610  else if( !SCIPisInfinity(scip, consdata->maxactdelta) )
16611  {
16612  SCIP_Real lb;
16613  SCIP_Real ub;
16614  SCIP_Real domain;
16615  SCIP_Real delta;
16616 
16617  assert((eventtype & SCIP_EVENTTYPE_BOUNDRELAXED) != 0);
16618 
16619  lb = SCIPvarGetLbLocal(var);
16620  ub = SCIPvarGetUbLocal(var);
16621 
16622  domain = ub - lb;
16623  delta = REALABS(val) * domain;
16624 
16625  if( delta > consdata->maxactdelta )
16626  {
16627  consdata->maxactdelta = delta;
16628  consdata->maxactdeltavar = var;
16629  }
16630  }
16631  }
16632  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
16633  {
16634  /* we want to remove the fixed variable */
16635  consdata->presolved = FALSE;
16636  consdata->removedfixings = FALSE;
16637  consdata->rangedrowpropagated = 0;
16638 
16639  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
16640  if( consdata->maxactdeltavar == var )
16641  {
16642  consdata->maxactdelta = SCIP_INVALID;
16643  consdata->maxactdeltavar = NULL;
16644  }
16645  }
16646 
16647  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
16648  {
16649  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
16650  assert(SCIPvarGetNLocksDown(var) <= 1);
16651  assert(SCIPvarGetNLocksUp(var) <= 1);
16652  consdata->presolved = FALSE;
16653  }
16654  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
16655  {
16656  SCIP_Real oldbound;
16657  SCIP_Real newbound;
16658  SCIP_Real val;
16659  int varpos;
16660 
16661  varpos = eventdata->varpos;
16662  assert(0 <= varpos && varpos < consdata->nvars);
16663  oldbound = SCIPeventGetOldbound(event);
16664  newbound = SCIPeventGetNewbound(event);
16665  assert(var != NULL);
16666  assert(consdata->vars[varpos] == var);
16667  val = consdata->vals[varpos];
16668 
16669  consdata->rangedrowpropagated = 0;
16670 
16671  /* update the activity values */
16672  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
16673  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
16674  else
16675  {
16676  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
16677  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
16678  }
16679  }
16680  else
16681  {
16682  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
16683  consdata->varsdeleted = TRUE;
16684  }
16685 
16686  return SCIP_OKAY;
16687 }
16688 
16689 
16690 /*
16691  * Callback methods of conflict handler
16692  */
16693 
16694 static
16695 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
16696 { /*lint --e{715}*/
16697  SCIP_VAR** vars;
16698  SCIP_Real* vals;
16699  SCIP_Real lhs;
16700  int i;
16701 
16702  assert(scip != NULL);
16703  assert(conflicthdlr != NULL);
16704  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
16705  assert(bdchginfos != NULL || nbdchginfos == 0);
16706  assert(result != NULL);
16707 
16708  /* don't process already resolved conflicts */
16709  if( resolved )
16710  {
16711  *result = SCIP_DIDNOTRUN;
16712  return SCIP_OKAY;
16713  }
16714 
16715  *result = SCIP_DIDNOTFIND;
16716 
16717  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
16718  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
16719  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
16720  lhs = 1.0;
16721  for( i = 0; i < nbdchginfos; ++i )
16722  {
16723  assert(bdchginfos != NULL);
16724 
16725  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
16726 
16727  /* we can only treat binary variables */
16728  /**@todo extend linear conflict constraints to some non-binary cases */
16729  if( !SCIPvarIsBinary(vars[i]) )
16730  break;
16731 
16732  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
16733  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
16734  vals[i] = 1.0;
16735  else
16736  {
16737  vals[i] = -1.0;
16738  lhs -= 1.0;
16739  }
16740  }
16741 
16742  if( i == nbdchginfos )
16743  {
16744  SCIP_CONS* cons;
16745  SCIP_CONS* upgdcons;
16746  char consname[SCIP_MAXSTRLEN];
16747 
16748  /* create a constraint out of the conflict set */
16749  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%" SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
16750  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
16751  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
16752 
16753  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
16754  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
16755  if( upgdcons != NULL )
16756  {
16757  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
16758  cons = upgdcons;
16759  }
16760 
16761  /* add conflict to SCIP */
16762  SCIP_CALL( SCIPaddConflict(scip, node, cons, validnode, conftype, cutoffinvolved) );
16763 
16764  *result = SCIP_CONSADDED;
16765  }
16766 
16767  /* free temporary memory */
16768  SCIPfreeBufferArray(scip, &vals);
16769  SCIPfreeBufferArray(scip, &vars);
16770 
16771  return SCIP_OKAY;
16772 }
16773 
16774 
16775 /*
16776  * Quadratic constraint upgrading
16777  */
16778 
16779 
16780 /** upgrades quadratic constraints with only and at least one linear variables into a linear constraint
16781  */
16782 static
16783 SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
16784 { /*lint --e{715}*/
16785  assert(scip != NULL);
16786  assert(cons != NULL);
16787  assert(nupgdconss != NULL);
16788  assert(upgdconss != NULL);
16789 
16790  *nupgdconss = 0;
16791 
16792  SCIPdebugMsg(scip, "upgradeConsQuadratic called for constraint <%s>\n", SCIPconsGetName(cons));
16793  SCIPdebugPrintCons(scip, cons, NULL);
16794 
16795  if( SCIPgetNQuadVarTermsQuadratic(scip, cons) > 0 )
16796  return SCIP_OKAY;
16797  if( SCIPgetNLinearVarsQuadratic(scip, cons) == 0 )
16798  return SCIP_OKAY;
16799 
16800  if( upgdconsssize < 1 )
16801  {
16802  /* signal that we need more memory */
16803  *nupgdconss = -1;
16804  return SCIP_OKAY;
16805  }
16806 
16807  *nupgdconss = 1;
16808  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
16809  SCIPgetNLinearVarsQuadratic(scip, cons),
16810  SCIPgetLinearVarsQuadratic(scip, cons),
16811  SCIPgetCoefsLinearVarsQuadratic(scip, cons),
16812  SCIPgetLhsQuadratic(scip, cons), SCIPgetRhsQuadratic(scip, cons),
16816  SCIPconsIsStickingAtNode(cons)) );
16817  SCIPdebugMsg(scip, "created linear constraint:\n");
16818  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
16819 
16820  return SCIP_OKAY;
16821 }
16822 
16823 /** tries to upgrade a nonlinear constraint into a linear constraint */
16824 static
16825 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
16826 {
16827  assert(nupgdconss != NULL);
16828  assert(upgdconss != NULL);
16829 
16830  *nupgdconss = 0;
16831 
16832  /* no interest in nonlinear constraints */
16833  if( SCIPgetExprgraphNodeNonlinear(scip, cons) != NULL )
16834  return SCIP_OKAY;
16835 
16836  /* no interest in constant constraints */
16837  if( SCIPgetNLinearVarsNonlinear(scip, cons) == 0 )
16838  return SCIP_OKAY;
16839 
16840  if( upgdconsssize < 1 )
16841  {
16842  /* request larger upgdconss array */
16843  *nupgdconss = -1;
16844  return SCIP_OKAY;
16845  }
16846 
16847  *nupgdconss = 1;
16848  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
16850  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons),
16854  SCIPconsIsStickingAtNode(cons)) );
16855 
16856  return SCIP_OKAY;
16857 }
16858 
16859 /*
16860  * constraint specific interface methods
16861  */
16862 
16863 /** creates the handler for linear constraints and includes it in SCIP */
16865  SCIP* scip /**< SCIP data structure */
16866  )
16867 {
16868  SCIP_CONSHDLRDATA* conshdlrdata;
16869  SCIP_CONSHDLR* conshdlr;
16870  SCIP_EVENTHDLR* eventhdlr;
16871  SCIP_CONFLICTHDLR* conflicthdlr;
16872 
16873  assert(scip != NULL);
16874 
16875  /* create event handler for bound change events */
16877  eventExecLinear, NULL) );
16878 
16879  /* create conflict handler for linear constraints */
16881  conflictExecLinear, NULL) );
16882 
16883  /* create constraint handler data */
16884  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
16885 
16886  /* include constraint handler */
16889  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
16890  conshdlrdata) );
16891 
16892  assert(conshdlr != NULL);
16893 
16894  /* set non-fundamental callbacks via specific setter functions */
16895  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
16896  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
16897  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
16898  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
16899  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
16900  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
16901  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
16902  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
16903  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
16904  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
16905  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
16906 #ifdef WITH_PRINTORIGCONSTYPES
16907  SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreLinear) );
16908 #endif
16909  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
16910  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
16911  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
16912  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
16914  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
16915  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
16917  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
16918  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxLinear) );
16919 
16920  if( SCIPfindConshdlr(scip, "quadratic") != NULL )
16921  {
16922  /* include function that upgrades quadratic constraint to linear constraints */
16924  }
16925 
16926  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
16927  {
16928  /* include the linear constraint upgrade in the nonlinear constraint handler */
16930  }
16931 
16932  /* add linear constraint handler parameters */
16933  SCIP_CALL( SCIPaddIntParam(scip,
16934  "constraints/" CONSHDLR_NAME "/tightenboundsfreq",
16935  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
16936  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, SCIP_MAXTREEDEPTH, NULL, NULL) );
16937  SCIP_CALL( SCIPaddIntParam(scip,
16938  "constraints/" CONSHDLR_NAME "/maxrounds",
16939  "maximal number of separation rounds per node (-1: unlimited)",
16940  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
16941  SCIP_CALL( SCIPaddIntParam(scip,
16942  "constraints/" CONSHDLR_NAME "/maxroundsroot",
16943  "maximal number of separation rounds per node in the root node (-1: unlimited)",
16944  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
16945  SCIP_CALL( SCIPaddIntParam(scip,
16946  "constraints/" CONSHDLR_NAME "/maxsepacuts",
16947  "maximal number of cuts separated per separation round",
16948  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
16949  SCIP_CALL( SCIPaddIntParam(scip,
16950  "constraints/" CONSHDLR_NAME "/maxsepacutsroot",
16951  "maximal number of cuts separated per separation round in the root node",
16952  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
16954  "constraints/" CONSHDLR_NAME "/presolpairwise",
16955  "should pairwise constraint comparison be performed in presolving?",
16956  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
16958  "constraints/" CONSHDLR_NAME "/presolusehashing",
16959  "should hash table be used for detecting redundant constraints in advance",
16960  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
16961  SCIP_CALL( SCIPaddIntParam(scip,
16962  "constraints/" CONSHDLR_NAME "/nmincomparisons",
16963  "number for minimal pairwise presolve comparisons",
16964  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
16966  "constraints/" CONSHDLR_NAME "/mingainpernmincomparisons",
16967  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
16968  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
16970  "constraints/" CONSHDLR_NAME "/maxaggrnormscale",
16971  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
16972  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
16974  "constraints/" CONSHDLR_NAME "/maxeasyactivitydelta",
16975  "maximum activity delta to run easy propagation on linear constraint (faster, but numerically less stable)",
16976  &conshdlrdata->maxeasyactivitydelta, TRUE, DEFAULT_MAXEASYACTIVITYDELTA, 0.0, SCIP_REAL_MAX, NULL, NULL) );
16978  "constraints/" CONSHDLR_NAME "/maxcardbounddist",
16979  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
16980  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
16982  "constraints/" CONSHDLR_NAME "/separateall",
16983  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
16984  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
16986  "constraints/" CONSHDLR_NAME "/aggregatevariables",
16987  "should presolving search for aggregations in equations",
16988  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
16990  "constraints/" CONSHDLR_NAME "/simplifyinequalities",
16991  "should presolving try to simplify inequalities",
16992  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
16994  "constraints/" CONSHDLR_NAME "/dualpresolving",
16995  "should dual presolving steps be performed?",
16996  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
16998  "constraints/" CONSHDLR_NAME "/singletonstuffing",
16999  "should stuffing of singleton continuous variables be performed?",
17000  &conshdlrdata->singletonstuffing, TRUE, DEFAULT_SINGLETONSTUFFING, NULL, NULL) );
17002  "constraints/" CONSHDLR_NAME "/singlevarstuffing",
17003  "should single variable stuffing be performed, which tries to fulfill constraints using the cheapest variable?",
17004  &conshdlrdata->singlevarstuffing, TRUE, DEFAULT_SINGLEVARSTUFFING, NULL, NULL) );
17006  "constraints/" CONSHDLR_NAME "/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
17007  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
17009  "constraints/" CONSHDLR_NAME "/checkrelmaxabs",
17010  "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)?",
17011  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
17013  "constraints/" CONSHDLR_NAME "/detectcutoffbound",
17014  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
17015  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
17017  "constraints/" CONSHDLR_NAME "/detectlowerbound",
17018  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
17019  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
17021  "constraints/" CONSHDLR_NAME "/detectpartialobjective",
17022  "should presolving try to detect subsets of constraints parallel to the objective function?",
17023  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
17025  "constraints/" CONSHDLR_NAME "/rangedrowpropagation",
17026  "should presolving and propagation try to improve bounds, detect infeasibility, and extract sub-constraints from ranged rows and equations?",
17027  &conshdlrdata->rangedrowpropagation, TRUE, DEFAULT_RANGEDROWPROPAGATION, NULL, NULL) );
17029  "constraints/" CONSHDLR_NAME "/rangedrowartcons",
17030  "should presolving and propagation extract sub-constraints from ranged rows and equations?",
17031  &conshdlrdata->rangedrowartcons, TRUE, DEFAULT_RANGEDROWARTCONS, NULL, NULL) );
17032  SCIP_CALL( SCIPaddIntParam(scip,
17033  "constraints/" CONSHDLR_NAME "/rangedrowmaxdepth",
17034  "maximum depth to apply ranged row propagation",
17035  &conshdlrdata->rangedrowmaxdepth, TRUE, DEFAULT_RANGEDROWMAXDEPTH, 0, INT_MAX, NULL, NULL) );
17036  SCIP_CALL( SCIPaddIntParam(scip,
17037  "constraints/" CONSHDLR_NAME "/rangedrowfreq",
17038  "frequency for applying ranged row propagation",
17039  &conshdlrdata->rangedrowfreq, TRUE, DEFAULT_RANGEDROWFREQ, 1, SCIP_MAXTREEDEPTH, NULL, NULL) );
17041  "constraints/" CONSHDLR_NAME "/multaggrremove",
17042  "should multi-aggregations only be performed if the constraint can be removed afterwards?",
17043  &conshdlrdata->multaggrremove, TRUE, DEFAULT_MULTAGGRREMOVE, NULL, NULL) );
17044 
17045  return SCIP_OKAY;
17046 }
17047 
17048 /** includes a linear constraint update method into the linear constraint handler */
17050  SCIP* scip, /**< SCIP data structure */
17051  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
17052  int priority, /**< priority of upgrading method */
17053  const char* conshdlrname /**< name of the constraint handler */
17054  )
17055 {
17056  SCIP_CONSHDLR* conshdlr;
17057  SCIP_CONSHDLRDATA* conshdlrdata;
17058  SCIP_LINCONSUPGRADE* linconsupgrade;
17059  char paramname[SCIP_MAXSTRLEN];
17060  char paramdesc[SCIP_MAXSTRLEN];
17061 
17062  assert(scip != NULL);
17063  assert(linconsupgd != NULL);
17064  assert(conshdlrname != NULL );
17065 
17066  /* find the linear constraint handler */
17067  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17068  if( conshdlr == NULL )
17069  {
17070  SCIPerrorMessage("linear constraint handler not found\n");
17071  return SCIP_PLUGINNOTFOUND;
17072  }
17073 
17074  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17075  assert(conshdlrdata != NULL);
17076 
17077  /* check if linear constraint update method already exists in constraint handler data */
17078  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
17079  {
17080  /* create a linear constraint upgrade data object */
17081  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
17082 
17083  /* insert linear constraint update method into constraint handler data */
17084  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
17085 
17086  /* adds parameter to turn on and off the upgrading step */
17087  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
17088  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
17090  paramname, paramdesc,
17091  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
17092  }
17093 
17094  return SCIP_OKAY;
17095 }
17096 
17097 /** creates and captures a linear constraint
17098  *
17099  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17100  */
17102  SCIP* scip, /**< SCIP data structure */
17103  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17104  const char* name, /**< name of constraint */
17105  int nvars, /**< number of nonzeros in the constraint */
17106  SCIP_VAR** vars, /**< array with variables of constraint entries */
17107  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17108  SCIP_Real lhs, /**< left hand side of constraint */
17109  SCIP_Real rhs, /**< right hand side of constraint */
17110  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
17111  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
17112  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
17113  * Usually set to TRUE. */
17114  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
17115  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17116  SCIP_Bool check, /**< should the constraint be checked for feasibility?
17117  * TRUE for model constraints, FALSE for additional, redundant constraints. */
17118  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
17119  * Usually set to TRUE. */
17120  SCIP_Bool local, /**< is constraint only valid locally?
17121  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
17122  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
17123  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
17124  * adds coefficients to this constraint. */
17125  SCIP_Bool dynamic, /**< is constraint subject to aging?
17126  * Usually set to FALSE. Set to TRUE for own cuts which
17127  * are separated as constraints. */
17128  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
17129  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
17130  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
17131  * if it may be moved to a more global node?
17132  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
17133  )
17134 {
17135  SCIP_CONSHDLRDATA* conshdlrdata;
17136  SCIP_CONSHDLR* conshdlr;
17137  SCIP_CONSDATA* consdata;
17138 
17139  assert(scip != NULL);
17140  assert(cons != NULL);
17141 
17142  /* find the linear constraint handler */
17143  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
17144  if( conshdlr == NULL )
17145  {
17146  SCIPerrorMessage("linear constraint handler not found\n");
17147  return SCIP_PLUGINNOTFOUND;
17148  }
17149 
17150  /* check for event handler */
17151  conshdlrdata = SCIPconshdlrGetData(conshdlr);
17152  assert(conshdlrdata != NULL);
17153  assert(conshdlrdata->eventhdlr != NULL);
17154 
17155  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17156  * constraint after presolving we have to ensure that it holds active variables
17157  */
17158  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
17159  {
17160  SCIP_VAR** consvars;
17161  SCIP_Real* consvals;
17162  SCIP_Real constant = 0.0;
17163  int nconsvars;
17164  int requiredsize;
17165 
17166  nconsvars = nvars;
17167  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
17168  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
17169 
17170  /* get active variables for new constraint */
17171  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17172 
17173  /* if space was not enough we need to resize the buffers */
17174  if( requiredsize > nconsvars )
17175  {
17176  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17177  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17178 
17179  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17180  assert(requiredsize <= nconsvars);
17181  }
17182 
17183  /* adjust sides and check that we do not subtract infinity values */
17184  if( SCIPisInfinity(scip, REALABS(constant)) )
17185  {
17186  if( constant < 0.0 )
17187  {
17188  if( SCIPisInfinity(scip, lhs) )
17189  {
17190  SCIPfreeBufferArray(scip, &consvals);
17191  SCIPfreeBufferArray(scip, &consvars);
17192 
17193  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);
17194 
17195  SCIPABORT();
17196  return SCIP_INVALIDDATA; /*lint !e527*/
17197  }
17198  if( SCIPisInfinity(scip, rhs) )
17199  {
17200  SCIPfreeBufferArray(scip, &consvals);
17201  SCIPfreeBufferArray(scip, &consvars);
17202 
17203  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);
17204 
17205  SCIPABORT();
17206  return SCIP_INVALIDDATA; /*lint !e527*/
17207  }
17208 
17209  lhs = -SCIPinfinity(scip);
17210  rhs = -SCIPinfinity(scip);
17211  }
17212  else
17213  {
17214  if( SCIPisInfinity(scip, -lhs) )
17215  {
17216  SCIPfreeBufferArray(scip, &consvals);
17217  SCIPfreeBufferArray(scip, &consvars);
17218 
17219  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);
17220 
17221  SCIPABORT();
17222  return SCIP_INVALIDDATA; /*lint !e527*/
17223  }
17224  if( SCIPisInfinity(scip, -rhs) )
17225  {
17226  SCIPfreeBufferArray(scip, &consvals);
17227  SCIPfreeBufferArray(scip, &consvars);
17228 
17229  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);
17230 
17231  SCIPABORT();
17232  return SCIP_INVALIDDATA; /*lint !e527*/
17233  }
17234 
17235  lhs = SCIPinfinity(scip);
17236  rhs = SCIPinfinity(scip);
17237  }
17238  }
17239  else
17240  {
17241  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17242  lhs -= constant;
17243  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17244  rhs -= constant;
17245 
17246  if( SCIPisInfinity(scip, -lhs) )
17247  lhs = -SCIPinfinity(scip);
17248  else if( SCIPisInfinity(scip, lhs) )
17249  lhs = SCIPinfinity(scip);
17250 
17251  if( SCIPisInfinity(scip, rhs) )
17252  rhs = SCIPinfinity(scip);
17253  else if( SCIPisInfinity(scip, -rhs) )
17254  rhs = -SCIPinfinity(scip);
17255  }
17256 
17257  /* create constraint data */
17258  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
17259  assert(consdata != NULL);
17260 
17261  SCIPfreeBufferArray(scip, &consvals);
17262  SCIPfreeBufferArray(scip, &consvars);
17263  }
17264  else
17265  {
17266  /* create constraint data */
17267  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
17268  assert(consdata != NULL);
17269  }
17270 
17271  /* create constraint */
17272  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
17273  local, modifiable, dynamic, removable, stickingatnode) );
17274 
17275  if( needEvents(scip) )
17276  {
17277  /* catch bound change events of variables */
17278  SCIP_CALL( consCatchAllEvents(scip, *cons, conshdlrdata->eventhdlr) );
17279  assert(consdata->eventdata != NULL);
17280  }
17281 
17282  return SCIP_OKAY;
17283 }
17284 
17285 /** creates and captures a linear constraint
17286  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
17287  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
17288  *
17289  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
17290  *
17291  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
17292  */
17294  SCIP* scip, /**< SCIP data structure */
17295  SCIP_CONS** cons, /**< pointer to hold the created constraint */
17296  const char* name, /**< name of constraint */
17297  int nvars, /**< number of nonzeros in the constraint */
17298  SCIP_VAR** vars, /**< array with variables of constraint entries */
17299  SCIP_Real* vals, /**< array with coefficients of constraint entries */
17300  SCIP_Real lhs, /**< left hand side of constraint */
17301  SCIP_Real rhs /**< right hand side of constraint */
17302  )
17303 {
17304  assert(scip != NULL);
17305 
17306  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
17307  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
17308 
17309  return SCIP_OKAY;
17311 
17312 /** creates by copying and captures a linear constraint */
17314  SCIP* scip, /**< target SCIP data structure */
17315  SCIP_CONS** cons, /**< pointer to store the created target constraint */
17316  SCIP* sourcescip, /**< source SCIP data structure */
17317  const char* name, /**< name of constraint */
17318  int nvars, /**< number of variables in source variable array */
17319  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
17320  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
17321  SCIP_Real lhs, /**< left hand side of the linear constraint */
17322  SCIP_Real rhs, /**< right hand side of the linear constraint */
17323  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
17324  * variables of the target SCIP */
17325  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
17326  * target constraints */
17327  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
17328  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
17329  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
17330  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
17331  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
17332  SCIP_Bool local, /**< is constraint only valid locally? */
17333  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
17334  SCIP_Bool dynamic, /**< is constraint subject to aging? */
17335  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
17336  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
17337  * if it may be moved to a more global node? */
17338  SCIP_Bool global, /**< create a global or a local copy? */
17339  SCIP_Bool* valid /**< pointer to store if the copying was valid */
17340  )
17341 {
17342  SCIP_VAR** vars;
17343  SCIP_Real* coefs;
17344 
17345  SCIP_Real constant;
17346  int requiredsize;
17347  int v;
17348  SCIP_Bool success;
17349 
17350  if( SCIPisGT(scip, lhs, rhs) )
17351  {
17352  *valid = FALSE;
17353  return SCIP_OKAY;
17354  }
17355 
17356  (*valid) = TRUE;
17357 
17358  if( nvars == 0 )
17359  {
17360  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
17361  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17362  return SCIP_OKAY;
17363  }
17364 
17365  /* duplicate variable array */
17366  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
17367 
17368  /* duplicate coefficient array */
17369  if( sourcecoefs != NULL )
17370  {
17371  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
17372  }
17373  else
17374  {
17375  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
17376  for( v = 0; v < nvars; ++v )
17377  coefs[v] = 1.0;
17378  }
17379 
17380  constant = 0.0;
17381 
17382  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
17383  * the target SCIP
17384  */
17385  if( !SCIPvarIsOriginal(vars[0]) )
17386  {
17387  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
17388 
17389  if( requiredsize > nvars )
17390  {
17391  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
17392  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
17393 
17394  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
17395  assert(requiredsize <= nvars);
17396  }
17397  }
17398  else
17399  {
17400  for( v = 0; v < nvars; ++v )
17401  {
17402  assert(SCIPvarIsOriginal(vars[v]));
17403  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
17404  assert(vars[v] != NULL);
17405  }
17406  }
17407 
17408 
17409  success = TRUE;
17410  /* map variables of the source constraint to variables of the target SCIP */
17411  for( v = 0; v < nvars && success; ++v )
17412  {
17413  SCIP_VAR* var;
17414  var = vars[v];
17415 
17416  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, &success) );
17417  assert(!(success) || vars[v] != NULL);
17418  }
17419 
17420  /* only create the target constraint, if all variables could be copied */
17421  if( success )
17422  {
17423  if( !SCIPisInfinity(scip, -lhs) )
17424  lhs -= constant;
17425 
17426  if( !SCIPisInfinity(scip, rhs) )
17427  rhs -= constant;
17428 
17429  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
17430  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
17431  }
17432  else
17433  *valid = FALSE;
17434 
17435  /* free buffer array */
17436  SCIPfreeBufferArray(scip, &coefs);
17437  SCIPfreeBufferArray(scip, &vars);
17438 
17439  return SCIP_OKAY;
17440 }
17441 
17442 /** adds coefficient to linear constraint (if it is not zero) */
17444  SCIP* scip, /**< SCIP data structure */
17445  SCIP_CONS* cons, /**< constraint data */
17446  SCIP_VAR* var, /**< variable of constraint entry */
17447  SCIP_Real val /**< coefficient of constraint entry */
17448  )
17449 {
17450  assert(scip != NULL);
17451  assert(cons != NULL);
17452  assert(var != NULL);
17453 
17454  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17455  {
17456  SCIPerrorMessage("constraint is not linear\n");
17457  return SCIP_INVALIDDATA;
17458  }
17459 
17460  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
17461  * constraint after presolving we have to ensure that it holds active variables
17462  */
17463  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
17464  {
17465  SCIP_CONSDATA* consdata;
17466  SCIP_VAR** consvars;
17467  SCIP_Real* consvals;
17468  SCIP_Real constant = 0.0;
17469  SCIP_Real rhs;
17470  SCIP_Real lhs;
17471  int nconsvars;
17472  int requiredsize;
17473  int v;
17474 
17475  nconsvars = 1;
17476  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
17477  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
17478  consvars[0] = var;
17479  consvals[0] = val;
17480 
17481  /* get active variables for new constraint */
17482  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
17483 
17484  /* if space was not enough we need to resize the buffers */
17485  if( requiredsize > nconsvars )
17486  {
17487  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
17488  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
17489 
17490  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
17491  assert(requiredsize <= nconsvars);
17492  }
17493 
17494  consdata = SCIPconsGetData(cons);
17495  assert(consdata != NULL);
17496 
17497  lhs = consdata->lhs;
17498  rhs = consdata->rhs;
17499 
17500  /* adjust sides and check that we do not subtract infinity values */
17501  /* constant is infinite */
17502  if( SCIPisInfinity(scip, REALABS(constant)) )
17503  {
17504  if( constant < 0.0 )
17505  {
17506  if( SCIPisInfinity(scip, lhs) )
17507  {
17508  SCIPfreeBufferArray(scip, &consvals);
17509  SCIPfreeBufferArray(scip, &consvars);
17510 
17511  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));
17512 
17513  SCIPABORT();
17514  return SCIP_INVALIDDATA; /*lint !e527*/
17515  }
17516  if( SCIPisInfinity(scip, rhs) )
17517  {
17518  SCIPfreeBufferArray(scip, &consvals);
17519  SCIPfreeBufferArray(scip, &consvars);
17520 
17521  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));
17522 
17523  SCIPABORT();
17524  return SCIP_INVALIDDATA; /*lint !e527*/
17525  }
17526 
17527  lhs = -SCIPinfinity(scip);
17528  rhs = -SCIPinfinity(scip);
17529  }
17530  else
17531  {
17532  if( SCIPisInfinity(scip, -lhs) )
17533  {
17534  SCIPfreeBufferArray(scip, &consvals);
17535  SCIPfreeBufferArray(scip, &consvars);
17536 
17537  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));
17538 
17539  SCIPABORT();
17540  return SCIP_INVALIDDATA; /*lint !e527*/
17541  }
17542  if( SCIPisInfinity(scip, -rhs) )
17543  {
17544  SCIPfreeBufferArray(scip, &consvals);
17545  SCIPfreeBufferArray(scip, &consvars);
17546 
17547  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));
17548 
17549  SCIPABORT();
17550  return SCIP_INVALIDDATA; /*lint !e527*/
17551  }
17552 
17553  lhs = SCIPinfinity(scip);
17554  rhs = SCIPinfinity(scip);
17555  }
17556  }
17557  /* constant is not infinite */
17558  else
17559  {
17560  if( !SCIPisInfinity(scip, REALABS(lhs)) )
17561  lhs -= constant;
17562  if( !SCIPisInfinity(scip, REALABS(rhs)) )
17563  rhs -= constant;
17564 
17565  if( SCIPisInfinity(scip, -lhs) )
17566  lhs = -SCIPinfinity(scip);
17567  else if( SCIPisInfinity(scip, lhs) )
17568  lhs = SCIPinfinity(scip);
17569 
17570  if( SCIPisInfinity(scip, rhs) )
17571  rhs = SCIPinfinity(scip);
17572  else if( SCIPisInfinity(scip, -rhs) )
17573  rhs = -SCIPinfinity(scip);
17574  }
17575 
17576  /* add all active variables to constraint */
17577  for( v = nconsvars - 1; v >= 0; --v )
17578  {
17579  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
17580  }
17581 
17582  /* update left and right hand sides */
17583  SCIP_CALL( chgLhs(scip, cons, lhs));
17584  SCIP_CALL( chgRhs(scip, cons, rhs));
17585 
17586  SCIPfreeBufferArray(scip, &consvals);
17587  SCIPfreeBufferArray(scip, &consvars);
17588  }
17589  else
17590  {
17591  SCIP_CALL( addCoef(scip, cons, var, val) );
17592  }
17593 
17594  return SCIP_OKAY;
17595 }
17596 
17597 /** changes coefficient of variable in linear constraint; deletes the variable if coefficient is zero; adds variable if
17598  * not yet contained in the constraint
17599  *
17600  * @note This method may only be called during problem creation stage for an original constraint and variable.
17601  *
17602  * @note This method requires linear time to search for occurences of the variable in the constraint data.
17603  */
17605  SCIP* scip, /**< SCIP data structure */
17606  SCIP_CONS* cons, /**< constraint data */
17607  SCIP_VAR* var, /**< variable of constraint entry */
17608  SCIP_Real val /**< new coefficient of constraint entry */
17609  )
17610 {
17611  SCIP_CONSDATA* consdata;
17612  SCIP_VAR** vars;
17613  SCIP_Bool found;
17614  int i;
17615 
17616  assert(scip != NULL);
17617  assert(cons != NULL);
17618  assert(var != NULL);
17619 
17620  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17621  {
17622  SCIPerrorMessage("constraint is not linear\n");
17623  return SCIP_INVALIDDATA;
17624  }
17625 
17626  if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM || !SCIPconsIsOriginal(cons) || !SCIPvarIsOriginal(var) )
17627  {
17628  SCIPerrorMessage("method may only be called during problem creation stage for original constraints and variables\n");
17629  return SCIP_INVALIDDATA;
17630  }
17631 
17632  consdata = SCIPconsGetData(cons);
17633  assert(consdata != NULL);
17634 
17635  vars = consdata->vars;
17636  found = FALSE;
17637  i = 0;
17638  while( i < consdata->nvars )
17639  {
17640  if( vars[i] == var )
17641  {
17642  if( found || SCIPisZero(scip, val) )
17643  {
17644  SCIP_CALL( delCoefPos(scip, cons, i) );
17645 
17646  /* decrease i by one since otherwise we would skip the coefficient which has been switched to position i */
17647  i--;
17648  }
17649  else
17650  {
17651  SCIP_CALL( chgCoefPos(scip, cons, i, val) );
17652  }
17653  found = TRUE;
17654  }
17655  i++;
17656  }
17657 
17658  if( !found && !SCIPisZero(scip, val) )
17659  {
17660  SCIP_CALL( SCIPaddCoefLinear(scip, cons, var, val) );
17661  }
17662 
17663  return SCIP_OKAY;
17664 }
17665 
17666 /** deletes variable from linear constraint
17667  *
17668  * @note This method may only be called during problem creation stage for an original constraint and variable.
17669  *
17670  * @note This method requires linear time to search for occurences of the variable in the constraint data.
17671  */
17673  SCIP* scip, /**< SCIP data structure */
17674  SCIP_CONS* cons, /**< constraint data */
17675  SCIP_VAR* var /**< variable of constraint entry */
17676  )
17677 {
17678  assert(scip != NULL);
17679  assert(cons != NULL);
17680  assert(var != NULL);
17681 
17682  SCIP_CALL( SCIPchgCoefLinear(scip, cons, var, 0.0) );
17683 
17684  return SCIP_OKAY;
17685 }
17686 
17687 /** gets left hand side of linear constraint */
17689  SCIP* scip, /**< SCIP data structure */
17690  SCIP_CONS* cons /**< constraint data */
17691  )
17692 {
17693  SCIP_CONSDATA* consdata;
17694 
17695  assert(cons != NULL);
17696 
17697  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17698  {
17699  SCIPerrorMessage("constraint is not linear\n");
17700  SCIPABORT();
17701  return SCIP_INVALID; /*lint !e527*/
17702  }
17703 
17704  consdata = SCIPconsGetData(cons);
17705  assert(consdata != NULL);
17706 
17707  return consdata->lhs;
17708 }
17709 
17710 /** gets right hand side of linear constraint */
17712  SCIP* scip, /**< SCIP data structure */
17713  SCIP_CONS* cons /**< constraint data */
17714  )
17715 {
17716  SCIP_CONSDATA* consdata;
17717 
17718  assert(cons != NULL);
17719 
17720  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17721  {
17722  SCIPerrorMessage("constraint is not linear\n");
17723  SCIPABORT();
17724  return SCIP_INVALID; /*lint !e527*/
17725  }
17726 
17727  consdata = SCIPconsGetData(cons);
17728  assert(consdata != NULL);
17729 
17730  return consdata->rhs;
17731 }
17732 
17733 /** changes left hand side of linear constraint */
17735  SCIP* scip, /**< SCIP data structure */
17736  SCIP_CONS* cons, /**< constraint data */
17737  SCIP_Real lhs /**< new left hand side */
17738  )
17739 {
17740  assert(scip != NULL);
17741  assert(cons != NULL);
17742 
17743  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17744  {
17745  SCIPerrorMessage("constraint is not linear\n");
17746  return SCIP_INVALIDDATA;
17747  }
17748 
17749  SCIP_CALL( chgLhs(scip, cons, lhs) );
17750 
17751  return SCIP_OKAY;
17752 }
17753 
17754 /** changes right hand side of linear constraint */
17756  SCIP* scip, /**< SCIP data structure */
17757  SCIP_CONS* cons, /**< constraint data */
17758  SCIP_Real rhs /**< new right hand side */
17759  )
17760 {
17761  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17762  {
17763  SCIPerrorMessage("constraint is not linear\n");
17764  return SCIP_INVALIDDATA;
17765  }
17766 
17767  SCIP_CALL( chgRhs(scip, cons, rhs) );
17768 
17769  return SCIP_OKAY;
17770 }
17771 
17772 /** gets the number of variables in the linear constraint */
17773 int SCIPgetNVarsLinear(
17774  SCIP* scip, /**< SCIP data structure */
17775  SCIP_CONS* cons /**< constraint data */
17776  )
17777 {
17778  SCIP_CONSDATA* consdata;
17779 
17780  assert(cons != NULL);
17781 
17782  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17783  {
17784  SCIPerrorMessage("constraint is not linear\n");
17785  SCIPABORT();
17786  return -1; /*lint !e527*/
17787  }
17788 
17789  consdata = SCIPconsGetData(cons);
17790  assert(consdata != NULL);
17791 
17792  return consdata->nvars;
17793 }
17794 
17795 /** gets the array of variables in the linear constraint; the user must not modify this array! */
17797  SCIP* scip, /**< SCIP data structure */
17798  SCIP_CONS* cons /**< constraint data */
17799  )
17800 {
17801  SCIP_CONSDATA* consdata;
17802 
17803  assert(cons != NULL);
17804 
17805  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17806  {
17807  SCIPerrorMessage("constraint is not linear\n");
17808  SCIPABORT();
17809  return NULL; /*lint !e527*/
17810  }
17811 
17812  consdata = SCIPconsGetData(cons);
17813  assert(consdata != NULL);
17814 
17815  return consdata->vars;
17816 }
17817 
17818 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
17820  SCIP* scip, /**< SCIP data structure */
17821  SCIP_CONS* cons /**< constraint data */
17822  )
17823 {
17824  SCIP_CONSDATA* consdata;
17825 
17826  assert(cons != NULL);
17827 
17828  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17829  {
17830  SCIPerrorMessage("constraint is not linear\n");
17831  SCIPABORT();
17832  return NULL; /*lint !e527*/
17833  }
17834 
17835  consdata = SCIPconsGetData(cons);
17836  assert(consdata != NULL);
17837 
17838  return consdata->vals;
17839 }
17840 
17841 /** gets the activity of the linear constraint in the given solution
17842  *
17843  * @note if the solution contains values at infinity, this method will return SCIP_INVALID in case the activity
17844  * comprises positive and negative infinity contributions
17845  */
17847  SCIP* scip, /**< SCIP data structure */
17848  SCIP_CONS* cons, /**< constraint data */
17849  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
17850  )
17851 {
17852  SCIP_CONSDATA* consdata;
17853 
17854  assert(cons != NULL);
17855 
17856  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17857  {
17858  SCIPerrorMessage("constraint is not linear\n");
17859  SCIPABORT();
17860  return SCIP_INVALID; /*lint !e527*/
17861  }
17862 
17863  consdata = SCIPconsGetData(cons);
17864  assert(consdata != NULL);
17865 
17866  if( consdata->row != NULL )
17867  return SCIPgetRowSolActivity(scip, consdata->row, sol);
17868  else
17869  return consdataGetActivity(scip, consdata, sol);
17870 }
17871 
17872 /** gets the feasibility of the linear constraint in the given solution */
17874  SCIP* scip, /**< SCIP data structure */
17875  SCIP_CONS* cons, /**< constraint data */
17876  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
17877  )
17878 {
17879  SCIP_CONSDATA* consdata;
17880 
17881  assert(cons != NULL);
17882 
17883  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17884  {
17885  SCIPerrorMessage("constraint is not linear\n");
17886  SCIPABORT();
17887  return SCIP_INVALID; /*lint !e527*/
17888  }
17889 
17890  consdata = SCIPconsGetData(cons);
17891  assert(consdata != NULL);
17892 
17893  if( consdata->row != NULL )
17894  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
17895  else
17896  return consdataGetFeasibility(scip, consdata, sol);
17897 }
17898 
17899 /** gets the dual solution of the linear constraint in the current LP */
17901  SCIP* scip, /**< SCIP data structure */
17902  SCIP_CONS* cons /**< constraint data */
17903  )
17904 {
17905  SCIP_CONSDATA* consdata;
17906 
17907  assert(cons != NULL);
17908 
17909  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17910  {
17911  SCIPerrorMessage("constraint is not linear\n");
17912  SCIPABORT();
17913  return SCIP_INVALID; /*lint !e527*/
17914  }
17915 
17916  consdata = SCIPconsGetData(cons);
17917  assert(consdata != NULL);
17918 
17919  if( consdata->row != NULL )
17920  return SCIProwGetDualsol(consdata->row);
17921  else
17922  return 0.0;
17923 }
17924 
17925 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
17927  SCIP* scip, /**< SCIP data structure */
17928  SCIP_CONS* cons /**< constraint data */
17929  )
17930 {
17931  SCIP_CONSDATA* consdata;
17932 
17933  assert(cons != NULL);
17934 
17935  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17936  {
17937  SCIPerrorMessage("constraint is not linear\n");
17938  SCIPABORT();
17939  return SCIP_INVALID; /*lint !e527*/
17940  }
17941 
17942  consdata = SCIPconsGetData(cons);
17943  assert(consdata != NULL);
17944 
17945  if( consdata->row != NULL )
17946  return SCIProwGetDualfarkas(consdata->row);
17947  else
17948  return 0.0;
17949 }
17950 
17951 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
17952  * the user must not modify the row!
17953  */
17955  SCIP* scip, /**< SCIP data structure */
17956  SCIP_CONS* cons /**< constraint data */
17957  )
17958 {
17959  SCIP_CONSDATA* consdata;
17960 
17961  assert(cons != NULL);
17962 
17963  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
17964  {
17965  SCIPerrorMessage("constraint is not linear\n");
17966  SCIPABORT();
17967  return NULL; /*lint !e527*/
17968  }
17969 
17970  consdata = SCIPconsGetData(cons);
17971  assert(consdata != NULL);
17972 
17973  return consdata->row;
17974 }
17975 
17976 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
17978  SCIP* scip, /**< SCIP data structure */
17979  SCIP_CONS* cons, /**< source constraint to try to convert */
17980  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
17981  )
17982 {
17983  SCIP_CONSHDLR* conshdlr;
17984  SCIP_CONSHDLRDATA* conshdlrdata;
17985  SCIP_CONSDATA* consdata;
17986  SCIP_VAR* var;
17987  SCIP_Real val;
17988  SCIP_Real lb;
17989  SCIP_Real ub;
17990  SCIP_Real poscoeffsum;
17991  SCIP_Real negcoeffsum;
17992  SCIP_Bool integral;
17993  int nposbin;
17994  int nnegbin;
17995  int nposint;
17996  int nnegint;
17997  int nposimpl;
17998  int nnegimpl;
17999  int nposimplbin;
18000  int nnegimplbin;
18001  int nposcont;
18002  int nnegcont;
18003  int ncoeffspone;
18004  int ncoeffsnone;
18005  int ncoeffspint;
18006  int ncoeffsnint;
18007  int ncoeffspfrac;
18008  int ncoeffsnfrac;
18009  int i;
18010 
18011  assert(scip != NULL);
18012  assert(cons != NULL);
18013  assert(upgdcons != NULL);
18014 
18015  *upgdcons = NULL;
18016 
18017  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
18018  if( SCIPconsIsModifiable(cons) )
18019  return SCIP_OKAY;
18020 
18021  /* check for upgradability */
18022  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
18023  return SCIP_OKAY;
18024 
18025  /* get the constraint handler and check, if it's really a linear constraint */
18026  conshdlr = SCIPconsGetHdlr(cons);
18027  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
18028  {
18029  SCIPerrorMessage("constraint is not linear\n");
18030  return SCIP_INVALIDDATA;
18031  }
18032 
18033  /* get constraint handler data and constraint data */
18034  conshdlrdata = SCIPconshdlrGetData(conshdlr);
18035  assert(conshdlrdata != NULL);
18036  consdata = SCIPconsGetData(cons);
18037  assert(consdata != NULL);
18038 
18039  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
18040  if( consdata->upgraded )
18041  return SCIP_OKAY;
18042 
18043  /* check, if the constraint is already stored as LP row */
18044  if( consdata->row != NULL )
18045  {
18046  if( SCIProwIsInLP(consdata->row) )
18047  {
18048  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
18049  return SCIP_INVALIDDATA;
18050  }
18051  else
18052  {
18053  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
18054  }
18055  }
18056 
18057  /* normalize constraint */
18058  SCIP_CALL( normalizeCons(scip, cons) );
18059 
18060 
18061  /*
18062  * calculate some statistics on linear constraint
18063  */
18064 
18065  nposbin = 0;
18066  nnegbin = 0;
18067  nposint = 0;
18068  nnegint = 0;
18069  nposimpl = 0;
18070  nnegimpl = 0;
18071  nposimplbin = 0;
18072  nnegimplbin = 0;
18073  nposcont = 0;
18074  nnegcont = 0;
18075  ncoeffspone = 0;
18076  ncoeffsnone = 0;
18077  ncoeffspint = 0;
18078  ncoeffsnint = 0;
18079  ncoeffspfrac = 0;
18080  ncoeffsnfrac = 0;
18081  integral = TRUE;
18082  poscoeffsum = 0.0;
18083  negcoeffsum = 0.0;
18084 
18085  for( i = 0; i < consdata->nvars; ++i )
18086  {
18087  var = consdata->vars[i];
18088  val = consdata->vals[i];
18089  lb = SCIPvarGetLbLocal(var);
18090  ub = SCIPvarGetUbLocal(var);
18091  assert(!SCIPisZero(scip, val));
18092 
18093  switch( SCIPvarGetType(var) )
18094  {
18095  case SCIP_VARTYPE_BINARY:
18096  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18097  integral = integral && SCIPisIntegral(scip, val);
18098  if( val >= 0.0 )
18099  nposbin++;
18100  else
18101  nnegbin++;
18102  break;
18103  case SCIP_VARTYPE_INTEGER:
18104  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18105  integral = integral && SCIPisIntegral(scip, val);
18106  if( val >= 0.0 )
18107  nposint++;
18108  else
18109  nnegint++;
18110  break;
18111  case SCIP_VARTYPE_IMPLINT:
18112  if( SCIPvarIsBinary(var) )
18113  {
18114  if( val >= 0.0 )
18115  nposimplbin++;
18116  else
18117  nnegimplbin++;
18118  }
18119  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
18120  integral = integral && SCIPisIntegral(scip, val);
18121  if( val >= 0.0 )
18122  nposimpl++;
18123  else
18124  nnegimpl++;
18125  break;
18127  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
18128  if( val >= 0.0 )
18129  nposcont++;
18130  else
18131  nnegcont++;
18132  break;
18133  default:
18134  SCIPerrorMessage("unknown variable type\n");
18135  return SCIP_INVALIDDATA;
18136  }
18137  if( SCIPisEQ(scip, val, 1.0) )
18138  ncoeffspone++;
18139  else if( SCIPisEQ(scip, val, -1.0) )
18140  ncoeffsnone++;
18141  else if( SCIPisIntegral(scip, val) )
18142  {
18143  if( SCIPisPositive(scip, val) )
18144  ncoeffspint++;
18145  else
18146  ncoeffsnint++;
18147  }
18148  else
18149  {
18150  if( SCIPisPositive(scip, val) )
18151  ncoeffspfrac++;
18152  else
18153  ncoeffsnfrac++;
18154  }
18155  if( SCIPisPositive(scip, val) )
18156  poscoeffsum += val;
18157  else
18158  negcoeffsum += val;
18159  }
18160 
18161 
18162  /*
18163  * call the upgrading methods
18164  */
18165 
18166  SCIPdebugMsg(scip, "upgrading linear constraint <%s> (%d upgrade methods):\n",
18167  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
18168  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",
18169  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
18170  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18171  poscoeffsum, negcoeffsum, integral);
18172 
18173  /* try all upgrading methods in priority order in case the upgrading step is enable */
18174  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
18175  {
18176  if( conshdlrdata->linconsupgrades[i]->active )
18177  {
18178  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
18179  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
18180  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
18181  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
18182  poscoeffsum, negcoeffsum, integral,
18183  upgdcons) );
18184  }
18185  }
18186 
18187 #ifdef SCIP_DEBUG
18188  if( *upgdcons != NULL )
18189  {
18190  SCIPdebugPrintCons(scip, cons, NULL);
18191  SCIPdebugMsg(scip, " -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
18192  SCIPdebugPrintCons(scip, *upgdcons, NULL);
18193  }
18194 #endif
18195 
18196  return SCIP_OKAY;
18197 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define EVENTHDLR_DESC
Definition: cons_linear.c:80
#define CONSHDLR_DELAYSEPA
Definition: cons_linear.c:72
void SCIPsortRealInt(SCIP_Real *realarray, int *intarray, int len)
SCIP_VAR ** SCIPgetLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21909
#define SCIP_DECL_LINCONSUPGD(x)
Definition: cons_linear.h:104
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
void SCIPconshdlrSetData(SCIP_CONSHDLR *conshdlr, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons.c:4143
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:46151
struct InferInfo INFERINFO
SCIP_RETCODE SCIPincConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:27934
SCIP_Real SCIPgetActivityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:21898
SCIP_RETCODE SCIPflattenVarAggregationGraph(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18829
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:6228
SCIP_Bool SCIPinRepropagation(SCIP *scip)
Definition: scip.c:40508
static SCIP_RETCODE tightenVarBounds(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:6631
static void consdataCalcMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1361
SCIP_RETCODE SCIPincludeNonlinconsUpgrade(SCIP *scip, SCIP_DECL_NONLINCONSUPGD((*nonlinconsupgd)), SCIP_DECL_EXPRGRAPHNODEREFORM((*nodereform)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:45274
SCIP_RETCODE SCIPincludeConshdlrLinear(SCIP *scip)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
Definition: cons_linear.c:860
static int inferInfoGetPos(INFERINFO inferinfo)
Definition: cons_linear.c:402
static SCIP_RETCODE consCatchEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:715
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21892
static SCIP_RETCODE chgCoefPos(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Real newval)
Definition: cons_linear.c:3890
static SCIP_RETCODE simplifyInequalities(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
SCIP_RETCODE SCIPtightenVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22118
static SCIP_Real consdataGetFeasibility(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3072
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19263
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46086
#define DEFAULT_MAXAGGRNORMSCALE
Definition: cons_linear.c:103
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:814
#define DEFAULT_PRESOLPAIRWISE
Definition: cons_linear.c:91
#define SCIP_EVENTTYPE_VARFIXED
Definition: type_event.h:58
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8140
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:16958
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:6251
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46099
#define CONSHDLR_NAME
Definition: cons_linear.c:61
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip.c:19123
#define CONSHDLR_MAXPREROUNDS
Definition: cons_linear.c:71
static void calculateMinvalAndMaxval(SCIP *scip, SCIP_Real side, SCIP_Real val, SCIP_Real minresactivity, SCIP_Real maxresactivity, SCIP_Real *minval, SCIP_Real *maxval)
#define BINWEIGHT
static void consdataUpdateSignatures(SCIP_CONSDATA *consdata, int pos)
Definition: cons_linear.c:3093
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2254
static void 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)
Definition: cons_linear.c:1528
#define DEFAULT_RANGEDROWFREQ
Definition: cons_linear.c:138
static void consdataRecomputeMaxActivityDelta(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1466
#define MAXSCALEDCOEF
Definition: cons_linear.c:145
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:40275
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6541
static SCIP_Bool checkEqualObjective(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real *scale, SCIP_Real *offset)
Definition: cons_linear.c:9896
#define DEFAULT_CHECKRELMAXABS
Definition: cons_linear.c:100
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:42499
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars)
Definition: cons_linear.c:7575
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17788
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:46449
#define DEFAULT_MAXROUNDS
Definition: cons_linear.c:87
#define DEFAULT_SORTVARS
Definition: cons_linear.c:97
static SCIP_RETCODE convertUnaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *ndelconss)
Definition: cons_linear.c:9186
static SCIP_RETCODE tightenVarLb(SCIP *scip, SCIP_CONS *cons, int pos, PROPRULE proprule, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5271
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17166
SCIP_RETCODE SCIPincludeQuadconsUpgrade(SCIP *scip, SCIP_DECL_QUADCONSUPGD((*quadconsupgd)), int priority, SCIP_Bool active, const char *conshdlrname)
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:6481
SCIP_RETCODE 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)
static SCIP_RETCODE findOperators(const char *str, char **firstoperator, char **secondoperator, SCIP_Bool *success)
SCIP_RETCODE SCIPupdateCutoffbound(SCIP *scip, SCIP_Real cutoffbound)
Definition: scip.c:42527
#define SCIP_MAXSTRLEN
Definition: def.h:215
#define SCIP_DECL_CONSINITPRE(x)
Definition: type_cons.h:114
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16753
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
Definition: scip.c:45471
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip.c:5973
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:27962
static SCIP_RETCODE consDropAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:818
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12481
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:45601
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:16946
static long bound
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30288
SCIP_RETCODE SCIPsetConsPropagated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool propagate)
Definition: scip.c:27521
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:45876
SCIP_Bool SCIPisSumRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46527
static void consdataUpdateActivitiesGlbUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1986
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17222
SCIP_Bool SCIPisUpdateUnreliable(SCIP *scip, SCIP_Real newvalue, SCIP_Real oldvalue)
Definition: scip.c:46634
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45803
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8526
static SCIP_Real consdataGetMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2216
static SCIP_RETCODE linconsupgradeCreate(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority)
Definition: cons_linear.c:505
void SCIPsortDownRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
#define DEFAULT_MAXSEPACUTS
Definition: cons_linear.c:89
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:18575
SCIP_RETCODE SCIPupdateConsFlags(SCIP *scip, SCIP_CONS *cons0, SCIP_CONS *cons1)
Definition: scip.c:27674
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18384
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16732
SCIP_RETCODE SCIPsetConshdlrInitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITPRE((*consinitpre)))
Definition: scip.c:6142
static void consdataRecomputeMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1231
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:46175
#define DEFAULT_DETECTPARTIALOBJECTIVE
Definition: cons_linear.c:132
SCIP_RETCODE SCIPconvertCutsToConss(SCIP *scip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip.c:2996
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46138
static void 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)
Definition: cons_linear.c:2790
static void permSortConsdata(SCIP_CONSDATA *consdata, int *perm, int nvars)
Definition: cons_linear.c:3151
#define DEFAULT_AGGREGATEVARIABLES
Definition: cons_linear.c:115
#define FALSE
Definition: def.h:64
SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
Definition: scip.c:21580
static SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
static SCIP_DECL_CONSEXITSOL(consExitsolLinear)
static void consdataInvalidateActivities(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1132
int SCIPconsGetPos(SCIP_CONS *cons)
Definition: cons.c:7891
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:5831
SCIP_Real * SCIPgetLinearCoefsNonlinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSCOPY(consCopyLinear)
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:45816
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:45888
static void 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)
Definition: cons_linear.c:2852
static SCIP_Bool conshdlrdataHasUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_DECL_LINCONSUPGD((*linconsupgd)), const char *conshdlrname)
Definition: cons_linear.c:586
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
#define DEFAULT_MAXCARDBOUNDDIST
Definition: cons_linear.c:109
SCIP_RETCODE SCIPunmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28192
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip.c:13222
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17003
enum Proprule PROPRULE
#define DEFAULT_NMINCOMPARISONS
Definition: cons_linear.c:93
#define SCIPstatisticMessage
Definition: pub_message.h:104
SCIP_ROW * SCIPgetRowLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:26813
static SCIP_DECL_CONSINITLP(consInitlpLinear)
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:21255
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8160
#define SCIP_PRESOLTIMING_EXHAUSTIVE
Definition: type_timing.h:45
static SCIP_RETCODE separateCons(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_SOL *sol, SCIP_Bool separatecards, SCIP_Bool separateall, int *ncuts, SCIP_Bool *cutoff)
Definition: cons_linear.c:7360
static SCIP_Bool consdataIsResidualIntegral(SCIP *scip, SCIP_CONSDATA *consdata, int pos, SCIP_Real val)
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
static SCIP_RETCODE preprocessConstraintPairs(SCIP *scip, SCIP_CONS **conss, int firstchange, int chkind, SCIP_Real maxaggrnormscale, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides, int *nchgcoefs)
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16859
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:61
static SCIP_DECL_CONSENFOPS(consEnfopsLinear)
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:16912
SCIP_Real SCIPgetRhsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:8190
static GRAPHNODE ** active
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:26717
SCIP_RETCODE SCIPtightenVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22234
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:21907
static SCIP_RETCODE tightenSides(SCIP *scip, SCIP_CONS *cons, int *nchgsides)
Definition: cons_linear.c:8676
#define SCIPdebugMessage
Definition: pub_message.h:77
#define DEFAULT_MINGAINPERNMINCOMP
Definition: cons_linear.c:94
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:5885
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:8482
int SCIPconsGetNLocksNeg(SCIP_CONS *cons)
Definition: cons.c:8240
SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
Definition: scip.c:1228
static SCIP_DECL_CONSEXITPRE(consExitpreLinear)
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:21933
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
enum Proprule PROPRULE
Definition: cons_linear.c:352
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45751
static SCIP_DECL_CONSRESPROP(consRespropLinear)
static SCIP_RETCODE detectRedundantConstraints(SCIP *scip, BMS_BLKMEM *blkmem, SCIP_CONS **conss, int nconss, int *firstchange, SCIP_Bool *cutoff, int *ndelconss, int *nchgsides)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:21937
static INFERINFO getInferInfo(PROPRULE proprule, int pos)
Definition: cons_linear.c:411
static SCIP_RETCODE rangedRowPropagation(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds, int *naddconss)
Definition: cons_linear.c:5658
SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
Definition: scip.c:21548
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16763
SCIP_RETCODE SCIPincludeConflicthdlrBasic(SCIP *scip, SCIP_CONFLICTHDLR **conflicthdlrptr, const char *name, const char *desc, int priority, SCIP_DECL_CONFLICTEXEC((*conflictexec)), SCIP_CONFLICTHDLRDATA *conflicthdlrdata)
Definition: scip.c:6625
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:21890
#define SCIPdebugPrintCons(x, y, z)
Definition: pub_message.h:83
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1010
SCIP_RETCODE SCIPdelCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:36161
static SCIP_RETCODE consDropEvent(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_linear.c:752
SCIP_RETCODE SCIPsetConshdlrDelvars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELVARS((*consdelvars)))
Definition: scip.c:6412
#define checkMaxActivityDelta(scip, consdata)
Definition: cons_linear.c:1461
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:16992
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8150
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:108
static SCIP_DECL_SORTINDCOMP(consdataCompVar)
Definition: cons_linear.c:3138
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:6274
SCIP_Real SCIProwGetDualsol(SCIP_ROW *row)
Definition: lp.c:16331
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1260
#define SCIPdebugMsgPrint
Definition: scip.h:452
#define SCIPdebugMsg
Definition: scip.h:451
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4202
static SCIP_Real consdataGetMinAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2232
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:18616
SCIP_Real SCIPgetRhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:6458
SCIP_Real SCIPgetLhsQuadratic(SCIP *scip, SCIP_CONS *cons)
#define DEFAULT_SEPARATEALL
Definition: cons_linear.c:112
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition: cons.c:7942
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1336
#define DEFAULT_MAXSEPACUTSROOT
Definition: cons_linear.c:90
int SCIPgetNContVars(SCIP *scip)
Definition: scip.c:11811
static SCIP_RETCODE addConflictFixedVars(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos)
Definition: cons_linear.c:4940
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, 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)
Definition: scip.c:27146
SCIP_Real SCIPepsilon(SCIP *scip)
Definition: scip.c:45246
SCIP_RETCODE SCIPparseVarsLinearsum(SCIP *scip, const char *str, SCIP_VAR **vars, SCIP_Real *vals, int *nvars, int varssize, int *requiredsize, char **endptr, SCIP_Bool *success)
Definition: scip.c:17832
#define CONSHDLR_PRESOLTIMING
Definition: cons_linear.c:76
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:26746
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:46223
#define CONSHDLR_PROP_TIMING
Definition: cons_linear.c:77
#define MAXMULTIAGGRQUOTIENT
Definition: cons_linear.c:9346
static SCIP_RETCODE rangedRowSimplify(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2015
int SCIPgetNQuadVarTermsQuadratic(SCIP *scip, SCIP_CONS *cons)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:46211
SCIP_Bool SCIPconsIsOriginal(SCIP_CONS *cons)
Definition: cons.c:8180
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:104
static SCIP_DECL_CONSFREE(consFreeLinear)
#define CONSHDLR_SEPAFREQ
Definition: cons_linear.c:66
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:16982
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:16522
#define MAXCONSPRESOLROUNDS
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:26695
static SCIP_DECL_EVENTEXEC(eventExecLinear)
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:8077
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:46434
static void linconsupgradeFree(SCIP *scip, SCIP_LINCONSUPGRADE **linconsupgrade)
Definition: cons_linear.c:526
SCIP_RETCODE SCIPsetConsSeparated(SCIP *scip, SCIP_CONS *cons, SCIP_Bool separate)
Definition: scip.c:27446
SCIP_RETCODE SCIPchgVarType(SCIP *scip, SCIP_VAR *var, SCIP_VARTYPE vartype, SCIP_Bool *infeasible)
Definition: scip.c:25045
static SCIP_RETCODE analyzeConflict(SCIP *scip, SCIP_CONS *cons, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:5149
static SCIP_RETCODE checkCons(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool checklprows, SCIP_Bool checkrelmaxabs, SCIP_Bool *violated)
Definition: cons_linear.c:7070
SCIP_RETCODE SCIPaddClique(SCIP *scip, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:23815
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17176
static SCIP_RETCODE checkParallelObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:21904
#define CONFLICTHDLR_NAME
Definition: cons_linear.c:82
static SCIP_RETCODE 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_RETCODE SCIPmultiaggregateVar(SCIP *scip, SCIP_VAR *var, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: scip.c:25384
Constraint handler for knapsack constraints of the form , x binary and .
#define DEFAULT_DETECTCUTOFFBOUND
Definition: cons_linear.c:122
static SCIP_RETCODE updateCutoffbound(SCIP *scip, SCIP_CONS *cons, SCIP_Real primalbound)
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1162
SCIP_Bool SCIPisPresolveFinished(SCIP *scip)
Definition: scip.c:1047
SCIP_Bool SCIPconsIsLocked(SCIP_CONS *cons)
Definition: cons.c:8220
static SCIP_DECL_CONSDELETE(consDeleteLinear)
#define CONFLICTHDLR_PRIORITY
Definition: cons_linear.c:84
static SCIP_RETCODE addRelaxation(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool *cutoff)
Definition: cons_linear.c:7311
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:5997
static SCIP_RETCODE tightenVarUb(SCIP *scip, SCIP_CONS *cons, int pos, PROPRULE proprule, SCIP_Real newub, SCIP_Real oldub, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5202
static void 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)
Definition: cons_linear.c:2413
#define SCIPhashFour(a, b, c, d)
Definition: pub_misc.h:473
SCIP_Bool SCIPisSumRelLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46553
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12410
#define CONSHDLR_PROPFREQ
Definition: cons_linear.c:67
SCIP_Real SCIPgetDualsolLinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45764
SCIP_RETCODE SCIPaddConsLocal(SCIP *scip, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:13030
static SCIP_DECL_CONSENFOLP(consEnfolpLinear)
SCIP_Bool SCIPdoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:25434
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:13111
static void consdataGetActivityBounds(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Bool goodrelax, SCIP_Real *minactivity, SCIP_Real *maxactivity, SCIP_Bool *minisrelax, SCIP_Bool *maxisrelax)
Definition: cons_linear.c:2512
SCIP_RETCODE SCIPinferVarFixCons(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22345
SCIP_RETCODE SCIPupgradeConsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_CONS **upgdcons)
static SCIP_DECL_CONSSEPALP(consSepalpLinear)
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip.c:18929
SCIP_Real * SCIPgetCoefsLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static void consdataCalcMaxAbsval(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1337
SCIP_RETCODE SCIPaddVarImplication(SCIP *scip, SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition: scip.c:23687
#define DEFAULT_MULTAGGRREMOVE
Definition: cons_linear.c:140
static SCIP_RETCODE chgRhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
Definition: cons_linear.c:3493
static SCIP_RETCODE conshdlrdataEnsureLinconsupgradesSize(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, int num)
Definition: cons_linear.c:445
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:45519
static void consdataUpdateDelCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2059
static SCIP_RETCODE consdataSort(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3224
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21383
static void consdataUpdateAddCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:2009
static int inferInfoGetProprule(INFERINFO inferinfo)
Definition: cons_linear.c:393
static SCIP_RETCODE consdataTightenCoefs(SCIP *scip, SCIP_CONS *cons, int *nchgcoefs, int *nchgsides)
Definition: cons_linear.c:8759
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7881
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:16923
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8100
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16552
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:6022
constraint handler for quadratic constraints
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4133
static SCIP_RETCODE addConflictReasonVars(SCIP *scip, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5005
#define NULL
Definition: lpi_spx1.cpp:137
SCIP_RETCODE SCIPmarkConsPropagate(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:28164
static SCIP_RETCODE delCoefPos(SCIP *scip, SCIP_CONS *cons, int pos)
Definition: cons_linear.c:3769
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, INFERINFO inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
Definition: cons_linear.c:5056
static int getInferInt(PROPRULE proprule, int pos)
Definition: cons_linear.c:430
#define REALABS(x)
Definition: def.h:159
SCIP_RETCODE SCIPgetIntParam(SCIP *scip, const char *name, int *value)
Definition: scip.c:4388
static SCIP_RETCODE checkPartialObjective(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata)
Definition: cons_linear.c:9974
static SCIP_RETCODE conshdlrdataIncludeUpgrade(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_LINCONSUPGRADE *linconsupgrade)
Definition: cons_linear.c:616
#define CONSHDLR_DELAYPROP
Definition: cons_linear.c:73
int SCIPconsGetNLocksPos(SCIP_CONS *cons)
Definition: cons.c:8230
int SCIPconshdlrGetPropFreq(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:5009
#define SCIP_CALL(x)
Definition: def.h:306
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:42323
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:63
static SCIP_Bool canTightenBounds(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:5173
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46125
#define CONSHDLR_CHECKPRIORITY
Definition: cons_linear.c:65
static SCIP_RETCODE tightenVarBoundsEasy(SCIP *scip, SCIP_CONS *cons, int pos, SCIP_Bool *cutoff, int *nchgbds, SCIP_Bool force)
Definition: cons_linear.c:5340
#define SCIPhashSignature64(a)
Definition: pub_misc.h:470
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: scip.c:18873
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:16970
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2384
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46112
static void 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)
Definition: cons_linear.c:2312
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:27097
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1353
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8120
static SCIP_RETCODE scaleCons(SCIP *scip, SCIP_CONS *cons, SCIP_Real scalar)
Definition: cons_linear.c:3957
static SCIP_DECL_CONSINIT(consInitLinear)
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:6297
#define SCIPdebugGetSolVal(scip, var, val)
Definition: debug.h:265
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:33869
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
static SCIP_DECL_CONSTRANS(consTransLinear)
#define SCIP_EVENTTYPE_BOUNDTIGHTENED
Definition: type_event.h:106
static SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:28769
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:105
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool tightenbounds, SCIP_Bool rangedrowpropagation, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:7450
SCIP_Real SCIPgetDualfarkasLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
Definition: scip.c:45839
static void consdataUpdateChgCoef(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldval, SCIP_Real newval, SCIP_Bool checkreliability)
Definition: cons_linear.c:2116
#define DEFAULT_DETECTLOWERBOUND
Definition: cons_linear.c:127
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:21448
SCIP_Real SCIPgetRhsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_RETCODE consdataPrint(SCIP *scip, SCIP_CONSDATA *consdata, FILE *file)
Definition: cons_linear.c:1093
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16681
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2494
#define QUADCONSUPGD_PRIORITY
Definition: cons_linear.c:157
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21925
public data structures and miscellaneous methods
static SCIP_RETCODE chgLhs(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
Definition: cons_linear.c:3372
SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46024
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:982
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip.c:30205
#define CONSHDLR_NEEDSCONS
Definition: cons_linear.c:74
#define CONSHDLR_EAGERFREQ
Definition: cons_linear.c:68
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
static SCIP_RETCODE performVarDeletions(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss)
Definition: cons_linear.c:4041
static const char * paramname[]
Definition: lpi_msk.c:4268
static void consdataRecomputeGlbMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1311
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:30022
SCIP_Real SCIPgetLhsNonlinear(SCIP *scip, SCIP_CONS *cons)
static SCIP_Real consdataGetActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
Definition: cons_linear.c:3004
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:42094
#define MAXTIGHTENROUNDS
Definition: cons_linear.c:6899
constraint handler for nonlinear constraints
static void conshdlrdataFree(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata)
Definition: cons_linear.c:564
#define DEFAULT_SINGLEVARSTUFFING
Definition: cons_linear.c:119
static SCIP_DECL_CONSPROP(consPropLinear)
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:28652
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3217
#define DEFAULT_DUALPRESOLVING
Definition: cons_linear.c:117
#define MAX(x, y)
Definition: tclique_def.h:75
static SCIP_RETCODE mergeMultiples(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4446
static SCIP_DECL_CONSDELVARS(consDelvarsLinear)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7901
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11249
methods for debugging
SCIP_Bool SCIPconsIsDeleted(SCIP_CONS *cons)
Definition: cons.c:8010
static SCIP_RETCODE presolStuffing(SCIP *scip, SCIP_CONS *cons, SCIP_Bool singletonstuffing, SCIP_Bool singlevarstuffing, SCIP_Bool *cutoff, int *nfixedvars, int *nchgbds)
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip.c:30181
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8080
static void consdataUpdateActivitiesGlbLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1963
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8050
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17014
static SCIP_Real consdataComputePseudoActivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1178
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:40321
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17778
static void consdataCalcActivities(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:2250
#define NONLINCONSUPGD_PRIORITY
Definition: cons_linear.c:158
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:16901
SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: scip.c:17237
static int getVarWeight(SCIP_VAR *var)
#define SCIPcombineFourInt(a, b, c, d)
Definition: pub_misc.h:481
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:25141
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
int SCIPgetNRuns(SCIP *scip)
Definition: scip.c:41099
SCIP_Real SCIProwGetDualfarkas(SCIP_ROW *row)
Definition: lp.c:16344
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:21309
#define MAXDNOM
Definition: cons_linear.c:144
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:6435
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
Constraint handler for linear constraints in their most general form, .
int SCIPgetNObjVars(SCIP *scip)
Definition: scip.c:11859
SCIP_Longint SCIPgetNConflictConssApplied(SCIP *scip)
Definition: scip.c:42068
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2315
SCIP_RETCODE SCIPchgRhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real rhs)
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:16934
SCIP_Bool SCIPisSumRelGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46579
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:45827
SCIP_Real SCIPgetRowSolActivity(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:30713
#define DEFAULT_MAXROUNDSROOT
Definition: cons_linear.c:88
#define SCIP_EVENTTYPE_GBDCHANGED
Definition: type_event.h:103
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12080
SCIP_Real SCIPgetFeasibilityLinear(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol)
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22414
Proprule
#define DEFAULT_TIGHTENBOUNDSFREQ
Definition: cons_linear.c:86
#define SCIP_MAXTREEDEPTH
Definition: def.h:242
static SCIP_Bool needEvents(SCIP *scip)
Definition: cons_linear.c:849
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11676
static SCIP_RETCODE aggregateVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:35033
#define DEFAULT_SIMPLIFYINEQUALITIES
Definition: cons_linear.c:116
static SCIP_RETCODE createRow(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:7287
#define MINVALRECOMP
Definition: cons_linear.c:154
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2065
SCIP_RETCODE SCIPincludeLinconsUpgrade(SCIP *scip, SCIP_DECL_LINCONSUPGD((*linconsupgd)), int priority, const char *conshdlrname)
#define CONSHDLR_SEPAPRIORITY
Definition: cons_linear.c:63
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11631
int SCIPconsGetNUpgradeLocks(SCIP_CONS *cons)
Definition: cons.c:8272
#define SCIP_REAL_MAX
Definition: def.h:136
static void consdataGetReliableResidualActivity(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *cancelvar, SCIP_Real *resactivity, SCIP_Bool isminresact, SCIP_Bool useglobalbounds)
Definition: cons_linear.c:2558
static void consdataRecomputeMaxactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1258
SCIP_RETCODE SCIPwriteVarsLinearsum(SCIP *scip, FILE *file, SCIP_VAR **vars, SCIP_Real *vals, int nvars, SCIP_Bool type)
Definition: scip.c:17466
SCIP_RETCODE SCIPupdateLocalLowerbound(SCIP *scip, SCIP_Real newbound)
Definition: scip.c:13333
static SCIP_DECL_CONSENFORELAX(consEnforelaxLinear)
#define MAXSCALEDCOEFINTEGER
Definition: cons_linear.c:146
static SCIP_DECL_CONSCHECK(consCheckLinear)
SCIP_RETCODE 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)
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITPRE((*consexitpre)))
Definition: scip.c:6166
static SCIP_RETCODE conshdlrdataCreate(SCIP *scip, SCIP_CONSHDLRDATA **conshdlrdata, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:540
static void consdataCalcSignatures(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:3118
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30160
int SCIPgetNLinearVarsQuadratic(SCIP *scip, SCIP_CONS *cons)
static SCIP_DECL_CONSPARSE(consParseLinear)
static SCIP_RETCODE analyzeConflictRangedRow(SCIP *scip, SCIP_CONS *cons, SCIP_VAR **vars, int nvars, SCIP_VAR *var, SCIP_Real bound)
Definition: cons_linear.c:5600
static SCIP_RETCODE lockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:648
static SCIP_DECL_CONSGETVARS(consGetVarsLinear)
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3162
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:4653
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45790
static void 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)
Definition: cons_linear.c:2639
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:45900
static SCIP_RETCODE fullDualPresolve(SCIP *scip, SCIP_CONS **conss, int nconss, SCIP_Bool *cutoff, int *nchgbds)
int SCIPgetNLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
static const SCIP_Real scalars[]
Definition: lp.c:5563
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1911
SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:11311
SCIP_VAR ** SCIPgetVarsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7911
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22527
SCIP_RETCODE SCIPsetConshdlrInit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINIT((*consinit)))
Definition: scip.c:6046
#define CONTWEIGHT
SCIP_Real SCIPgetHugeValue(SCIP *scip)
Definition: scip.c:45853
static SCIP_DECL_CONSLOCK(consLockLinear)
SCIP_RETCODE SCIPsetConsEnforced(SCIP *scip, SCIP_CONS *cons, SCIP_Bool enforce)
Definition: scip.c:27471
static void consdataCheckNonbinvar(SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1390
static SCIP_RETCODE consCatchAllEvents(SCIP *scip, SCIP_CONS *cons, SCIP_EVENTHDLR *eventhdlr)
Definition: cons_linear.c:786
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip.c:6070
static SCIP_DECL_CONSSEPASOL(consSepasolLinear)
static SCIP_RETCODE extractCliques(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, int *nfixedvars, int *nchgbds, SCIP_Bool *cutoff)
Definition: cons_linear.c:7710
SCIP_Bool SCIPisConsCompressionEnabled(SCIP *scip)
Definition: scip.c:1861
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27323
static SCIP_DECL_CONSPRINT(consPrintLinear)
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip.c:25447
const char * SCIPconflicthdlrGetName(SCIP_CONFLICTHDLR *conflicthdlr)
Definition: conflict.c:714
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:6190
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1138
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:46163
static SCIP_RETCODE convertBinaryEquality(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9242
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11586
static SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
#define CONFLICTHDLR_DESC
Definition: cons_linear.c:83
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16671
SCIP_RETCODE SCIPaggregateVars(SCIP *scip, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *redundant, SCIP_Bool *aggregated)
Definition: scip.c:25250
static SCIP_RETCODE normalizeCons(SCIP *scip, SCIP_CONS *cons)
Definition: cons_linear.c:4100
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18350
#define SCIP_Real
Definition: def.h:135
static SCIP_RETCODE tightenBounds(SCIP *scip, SCIP_CONS *cons, SCIP_Real maxeasyactivitydelta, SCIP_Bool sortvars, SCIP_Bool *cutoff, int *nchgbds)
Definition: cons_linear.c:6903
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8130
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:30314
SCIP_VAR ** SCIPgetLinearVarsNonlinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1138
#define SCIP_EVENTTYPE_VARUNLOCKED
Definition: type_event.h:59
static void getNewSidesAfterAggregation(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *slackvar, SCIP_Real slackcoef, SCIP_Real *newlhs, SCIP_Real *newrhs)
Definition: cons_linear.c:9300
#define DEFAULT_SINGLETONSTUFFING
Definition: cons_linear.c:118
#define MIN(x, y)
Definition: memory.c:75
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:6504
#define EVENTHDLR_NAME
Definition: cons_linear.c:79
SCIP_Bool SCIPisScalingIntegral(SCIP *scip, SCIP_Real val, SCIP_Real scalar)
Definition: scip.c:45912
#define CONSHDLR_ENFOPRIORITY
Definition: cons_linear.c:64
static SCIP_RETCODE convertEquality(SCIP *scip, SCIP_CONS *cons, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)
static SCIP_RETCODE applyFixings(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
Definition: cons_linear.c:4517
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8070
SCIP_Bool SCIPdoNotAggr(SCIP *scip)
Definition: scip.c:25414
#define SCIP_INVALID
Definition: def.h:155
#define DEFAULT_RANGEDROWPROPAGATION
Definition: cons_linear.c:135
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8060
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:30762
static SCIP_RETCODE addCoef(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:3615
static SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
#define CONSHDLR_DESC
Definition: cons_linear.c:62
SCIP_Real SCIPcutoffbounddelta(SCIP *scip)
Definition: scip.c:45330
#define SCIP_Longint
Definition: def.h:120
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17278
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16849
SCIP_Real SCIPgetRowSolFeasibility(SCIP *scip, SCIP_ROW *row, SCIP_SOL *sol)
Definition: scip.c:30736
static SCIP_RETCODE consdataEnsureVarsSize(SCIP *scip, SCIP_CONSDATA *consdata, int num)
Definition: cons_linear.c:470
#define SCIPdebugAddSolVal(scip, var, val)
Definition: debug.h:264
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16717
static SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
#define MAX_CLIQUE_NONZEROS_PER_CONS
Definition: cons_linear.c:7643
static void consdataRecomputeGlbMinactivity(SCIP *scip, SCIP_CONSDATA *consdata)
Definition: cons_linear.c:1285
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:45864
SCIP_Real * SCIPgetValsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:45777
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
static SCIP_RETCODE convertLongEquality(SCIP *scip, SCIP_CONSHDLRDATA *conshdlrdata, SCIP_CONS *cons, SCIP_Bool *cutoff, int *naggrvars, int *ndelconss)
Definition: cons_linear.c:9356
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
SCIP_RETCODE SCIPchgLhsLinear(SCIP *scip, SCIP_CONS *cons, SCIP_Real lhs)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17232
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:21910
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:46187
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16694
static int inferInfoToInt(INFERINFO inferinfo)
Definition: cons_linear.c:384
SCIP_Bool SCIPconsIsMarkedPropagate(SCIP_CONS *cons)
Definition: cons.c:8090
#define MAXVALRECOMP
Definition: cons_linear.c:153
static SCIP_RETCODE unlockRounding(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
Definition: cons_linear.c:681
static SCIP_DECL_CONSPRESOL(consPresolLinear)
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
#define DEFAULT_MAXEASYACTIVITYDELTA
Definition: cons_linear.c:106
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:392
SCIP_EXPRGRAPHNODE * SCIPgetExprgraphNodeNonlinear(SCIP *scip, SCIP_CONS *cons)
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
SCIP_RETCODE SCIPaddConflict(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:12866
static SCIP_RETCODE enforceConstraint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result)
static SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:45949
static SCIP_DECL_CONSEXIT(consExitLinear)
#define DEFAULT_RANGEDROWMAXDEPTH
Definition: cons_linear.c:137
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:6118
#define SCIPABORT()
Definition: def.h:278
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16743
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:7945
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38007
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16773
static INFERINFO intToInferInfo(int i)
Definition: cons_linear.c:371
SCIP_RETCODE SCIPaddObjoffset(SCIP *scip, SCIP_Real addval)
Definition: scip.c:10924
int SCIPgetNVarsLinear(SCIP *scip, SCIP_CONS *cons)
#define INTWEIGHT
SCIP_Real SCIPgetLhsLinear(SCIP *scip, SCIP_CONS *cons)
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4258
static SCIP_RETCODE addConflictBounds(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, SCIP_BDCHGIDX *bdchgidx, int inferpos, SCIP_Bool reasonisrhs)
Definition: cons_linear.c:4758
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8056
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:45937
#define SCIP_EVENTTYPE_VARDELETED
Definition: type_event.h:57
static void consdataUpdateActivitiesLb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldlb, SCIP_Real newlb, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1913
SCIP_RETCODE SCIPseparateRelaxedKnapsack(SCIP *scip, SCIP_CONS *cons, SCIP_SEPA *sepa, int nknapvars, SCIP_VAR **knapvars, SCIP_Real *knapvals, SCIP_Real valscale, SCIP_Real rhs, SCIP_SOL *sol, SCIP_Bool *cutoff, int *ncuts)
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4176
int SCIPgetNSepaRounds(SCIP *scip)
Definition: scip.c:41933
#define DEFAULT_PRESOLUSEHASHING
Definition: cons_linear.c:92
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16839
#define HASHSIZE_LINEARCONS
Definition: cons_linear.c:152
SCIP_RETCODE SCIPchgCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16707
static void consdataUpdateActivitiesUb(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Real oldub, SCIP_Real newub, SCIP_Real val, SCIP_Bool checkreliability)
Definition: cons_linear.c:1938
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
Definition: cons_linear.c:1058
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:21929
#define SCIPrealHashCode(x, n)
Definition: pub_misc.h:484
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5931
SCIP_RETCODE SCIPsetConsInitial(SCIP *scip, SCIP_CONS *cons, SCIP_Bool initial)
Definition: scip.c:27421
#define SCIP_EVENTTYPE_BOUNDRELAXED
Definition: type_event.h:107
#define DEFAULT_RANGEDROWARTCONS
Definition: cons_linear.c:136
static SCIP_RETCODE dualPresolve(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *cutoff, int *nfixedvars, int *naggrvars, int *ndelconss)