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-2014 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_DELAYPRESOL FALSE /**< should presolving method be delayed, if other presolvers found reductions? */
74 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
75 
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_MAXCARDBOUNDDIST 0.0 /**< maximal relative distance from current node's dual bound to primal bound compared
102  * to best node's dual bound for separating knapsack cardinality cuts */
103 #define DEFAULT_SEPARATEALL FALSE /**< should all constraints be subject to cardinality cut generation instead of only
104  * the ones with non-zero dual value? */
105 #define DEFAULT_AGGREGATEVARIABLES TRUE /**< should presolving search for redundant variables in equations */
106 #define DEFAULT_SIMPLIFYINEQUALITIES TRUE /**< should presolving try to simplify inequalities */
107 #define DEFAULT_DUALPRESOLVING TRUE /**< should dual presolving steps be performed? */
108 #define DEFAULT_DETECTCUTOFFBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
109  * function defining an upper bound and prevent these constraints from
110  * entering the LP */
111 #define DEFAULT_DETECTLOWERBOUND TRUE /**< should presolving try to detect constraints parallel to the objective
112  * function defining a lower bound and prevent these constraints from
113  * entering the LP */
114 #define DEFAULT_DETECTPARTIALOBJECTIVE TRUE/**< should presolving try to detect subsets of constraints parallel to the
115  * objective function */
116 
117 #define MAXDNOM 10000LL /**< maximal denominator for simple rational fixed values */
118 #define MAXSCALEDCOEF 1e+03 /**< maximal coefficient value after scaling */
119 #define MAXSCALEDCOEFINTEGER 1e+05 /**< maximal coefficient value after scaling if all variables are of integral
120  * type
121  */
122 
123 #define HASHSIZE_LINEARCONS 131101 /**< minimal size of hash table in linear constraint tables */
124 
125 #define QUADCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of quadratic constraints */
126 #define NONLINCONSUPGD_PRIORITY 1000000 /**< priority of the constraint handler for upgrading of nonlinear constraints */
127 
128 #ifdef WITH_PRINTORIGCONSTYPES
129 /** constraint type */
130 enum SCIP_Constype
131 {
132  SCIP_CONSTYPE_EMPTY = 0, /**< */
133  SCIP_CONSTYPE_FREE = 1, /**< */
134  SCIP_CONSTYPE_SINGLETON = 2, /**< */
135  SCIP_CONSTYPE_AGGREGATION = 3, /**< */
136  SCIP_CONSTYPE_VARBOUND = 4, /**< */
137  SCIP_CONSTYPE_SETPARTITION = 5, /**< */
138  SCIP_CONSTYPE_SETPACKING = 6, /**< */
139  SCIP_CONSTYPE_SETCOVERING = 7, /**< */
140  SCIP_CONSTYPE_CARDINALITY = 8, /**< */
141  SCIP_CONSTYPE_INVKNAPSACK = 9, /**< */
142  SCIP_CONSTYPE_EQKNAPSACK = 10, /**< */
143  SCIP_CONSTYPE_BINPACKING = 11, /**< */
144  SCIP_CONSTYPE_KNAPSACK = 12, /**< */
145  SCIP_CONSTYPE_INTKNAPSACK = 13, /**< */
146  SCIP_CONSTYPE_MIXEDBINARY = 14, /**< */
147  SCIP_CONSTYPE_GENERAL = 15 /**< */
148 };
149 typedef enum SCIP_Constype SCIP_CONSTYPE;
150 #endif
151 
152 /* @todo add multi-aggregation of variables that are in exactly two equations (, if not numerically an issue),
153  * maybe in fullDualPresolve(), see convertLongEquality()
154  */
155 
156 
157 /** constraint data for linear constraints */
158 struct SCIP_ConsData
159 {
160  SCIP_Real lhs; /**< left hand side of row (for ranged rows) */
161  SCIP_Real rhs; /**< right hand side of row */
162  SCIP_Real maxabsval; /**< maximum absolute value of all coefficients */
163  SCIP_Real minactivity; /**< minimal value w.r.t. the variable's local bounds for the constraint's
164  * activity, ignoring the coefficients contributing with infinite value */
165  SCIP_Real maxactivity; /**< maximal value w.r.t. the variable's local bounds for the constraint's
166  * activity, ignoring the coefficients contributing with infinite value */
167  SCIP_Real lastminactivity; /**< last minimal activity which was computed by complete summation
168  * over all contributing values */
169  SCIP_Real lastmaxactivity; /**< last maximal activity which was computed by complete summation
170  * over all contributing values */
171  SCIP_Real glbminactivity; /**< minimal value w.r.t. the variable's global bounds for the constraint's
172  * activity, ignoring the coefficients contributing with infinite value */
173  SCIP_Real glbmaxactivity; /**< maximal value w.r.t. the variable's global bounds for the constraint's
174  * activity, ignoring the coefficients contributing with infinite value */
175  SCIP_Real lastglbminactivity; /**< last global minimal activity which was computed by complete summation
176  * over all contributing values */
177  SCIP_Real lastglbmaxactivity; /**< last global maximal activity which was computed by complete summation
178  * over all contributing values */
179  SCIP_Real maxactdelta; /**< maximal activity contribution of a single variable, or SCIP_INVALID if invalid */
180  SCIP_Longint possignature; /**< bit signature of coefficients that may take a positive value */
181  SCIP_Longint negsignature; /**< bit signature of coefficients that may take a negative value */
182  SCIP_ROW* row; /**< LP row, if constraint is already stored in LP row format */
183  SCIP_VAR** vars; /**< variables of constraint entries */
184  SCIP_Real* vals; /**< coefficients of constraint entries */
185  SCIP_EVENTDATA** eventdatas; /**< event datas for bound change events of the variables */
186  int minactivityneginf; /**< number of coefficients contributing with neg. infinite value to minactivity */
187  int minactivityposinf; /**< number of coefficients contributing with pos. infinite value to minactivity */
188  int maxactivityneginf; /**< number of coefficients contributing with neg. infinite value to maxactivity */
189  int maxactivityposinf; /**< number of coefficients contributing with pos. infinite value to maxactivity */
190  int minactivityneghuge; /**< number of coefficients contributing with huge neg. value to minactivity */
191  int minactivityposhuge; /**< number of coefficients contributing with huge pos. value to minactivity */
192  int maxactivityneghuge; /**< number of coefficients contributing with huge neg. value to maxactivity */
193  int maxactivityposhuge; /**< number of coefficients contributing with huge pos. value to maxactivity */
194  int glbminactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbminactivity */
195  int glbminactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbminactivity */
196  int glbmaxactivityneginf;/**< number of coefficients contrib. with neg. infinite value to glbmaxactivity */
197  int glbmaxactivityposinf;/**< number of coefficients contrib. with pos. infinite value to glbmaxactivity */
198  int glbminactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbminactivity */
199  int glbminactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbminactivity */
200  int glbmaxactivityneghuge;/**< number of coefficients contrib. with huge neg. value to glbmaxactivity */
201  int glbmaxactivityposhuge;/**< number of coefficients contrib. with huge pos. value to glbmaxactivity */
202  int varssize; /**< size of the vars- and vals-arrays */
203  int nvars; /**< number of nonzeros in constraint */
204  int nbinvars; /**< the number of binary variables in the constraint, only valid after
205  * sorting in stage >= SCIP_STAGE_INITSOLVE
206  */
207  unsigned int validmaxabsval:1; /**< is the maximum absolute value valid? */
208  unsigned int validactivities:1; /**< are the activity bounds (local and global) valid? */
209  unsigned int validminact:1; /**< is the local minactivity valid? */
210  unsigned int validmaxact:1; /**< is the local maxactivity valid? */
211  unsigned int validglbminact:1; /**< is the global minactivity valid? */
212  unsigned int validglbmaxact:1; /**< is the global maxactivity valid? */
213  unsigned int propagated:1; /**< is constraint already propagated? */
214  unsigned int boundstightened:1; /**< is constraint already propagated with bound tightening? */
215  unsigned int presolved:1; /**< is constraint already presolved? */
216  unsigned int removedfixings:1; /**< are all fixed variables removed from the constraint? */
217  unsigned int validsignature:1; /**< is the bit signature valid? */
218  unsigned int changed:1; /**< was constraint changed since last aggregation round in preprocessing? */
219  unsigned int normalized:1; /**< is the constraint in normalized form? */
220  unsigned int upgradetried:1; /**< was the constraint already tried to be upgraded? */
221  unsigned int upgraded:1; /**< is the constraint upgraded and will it be removed after preprocessing? */
222  unsigned int sorted:1; /**< are the constraint's variables sorted? */
223  unsigned int merged:1; /**< are the constraint's equal variables already merged? */
224  unsigned int cliquesadded:1; /**< were the cliques of the constraint already extracted? */
225  unsigned int implsadded:1; /**< were the implications of the constraint already extracted? */
226  unsigned int binvarssorted:1; /**< are binary variables sorted w.r.t. the absolute of their coefficient? */
227  unsigned int varsdeleted:1; /**< were variables deleted after last cleanup? */
228 };
229 
230 /** event data for bound change event */
231 struct SCIP_EventData
232 {
233  SCIP_CONS* cons; /**< linear constraint to process the bound change for */
234  int varpos; /**< position of variable in vars array */
235  int filterpos; /**< position of event in variable's event filter */
236 };
237 
238 /** constraint handler data */
239 struct SCIP_ConshdlrData
240 {
241  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
242  SCIP_LINCONSUPGRADE** linconsupgrades; /**< linear constraint upgrade methods for specializing linear constraints */
243  SCIP_Real maxaggrnormscale; /**< maximal allowed relative gain in maximum norm for constraint aggregation
244  * (0.0: disable constraint aggregation) */
245  SCIP_Real maxcardbounddist; /**< maximal relative distance from current node's dual bound to primal bound compared
246  * to best node's dual bound for separating knapsack cardinality cuts */
247  SCIP_Real mingainpernmincomp; /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
248  int linconsupgradessize;/**< size of linconsupgrade array */
249  int nlinconsupgrades; /**< number of linear constraint upgrade methods */
250  int tightenboundsfreq; /**< multiplier on propagation frequency, how often the bounds are tightened */
251  int maxrounds; /**< maximal number of separation rounds per node (-1: unlimited) */
252  int maxroundsroot; /**< maximal number of separation rounds in the root node (-1: unlimited) */
253  int maxsepacuts; /**< maximal number of cuts separated per separation round */
254  int maxsepacutsroot; /**< maximal number of cuts separated per separation round in root node */
255  int nmincomparisons; /**< number for minimal pairwise presolving comparisons */
256  SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
257  SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
258  SCIP_Bool separateall; /**< should all constraints be subject to cardinality cut generation instead of only
259  * the ones with non-zero dual value? */
260  SCIP_Bool aggregatevariables; /**< should presolving search for redundant variables in equations */
261  SCIP_Bool simplifyinequalities;/**< should presolving try to cancel down or delete coefficients in inequalities */
262  SCIP_Bool dualpresolving; /**< should dual presolving steps be performed? */
263  SCIP_Bool sortvars; /**< should binary variables be sorted for faster propagation? */
264  SCIP_Bool checkrelmaxabs; /**< should the violation for a constraint with side 0.0 be checked relative
265  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
266  SCIP_Bool detectcutoffbound; /**< should presolving try to detect constraints parallel to the objective
267  * function defining an upper bound and prevent these constraints from
268  * entering the LP */
269  SCIP_Bool detectlowerbound; /**< should presolving try to detect constraints parallel to the objective
270  * function defining a lower bound and prevent these constraints from
271  * entering the LP */
272  SCIP_Bool detectpartialobjective;/**< should presolving try to detect subsets of constraints parallel to
273  * the objective function */
274 
275 };
276 
277 /** linear constraint update method */
279 {
280  SCIP_DECL_LINCONSUPGD((*linconsupgd)); /**< method to call for upgrading linear constraint */
281  int priority; /**< priority of upgrading method */
282  SCIP_Bool active; /**< is upgrading enabled */
283 };
284 
285 
286 /*
287  * Propagation rules
288  */
289 
291 {
292  PROPRULE_1_RHS = 1, /**< activity residuals of all other variables tighten bounds of single
293  * variable due to the right hand side of the inequality */
294  PROPRULE_1_LHS = 2, /**< activity residuals of all other variables tighten bounds of single
295  * variable due to the left hand side of the inequality */
296  PROPRULE_INVALID = 0 /**< propagation was applied without a specific propagation rule */
297 };
298 typedef enum Proprule PROPRULE;
299 
300 /** inference information */
301 struct InferInfo
302 {
303  union
304  {
305  struct
306  {
307  unsigned int proprule:8; /**< propagation rule that was applied */
308  unsigned int pos:24; /**< variable position, the propagation rule was applied at */
309  } asbits;
310  int asint; /**< inference information as a single int value */
311  } val;
312 };
313 typedef struct InferInfo INFERINFO;
314 
315 /** converts an integer into an inference information */
316 static
318  int i /**< integer to convert */
319  )
320 {
321  INFERINFO inferinfo;
322 
323  inferinfo.val.asint = i;
324 
325  return inferinfo;
326 }
327 
328 /** converts an inference information into an int */
329 static
331  INFERINFO inferinfo /**< inference information to convert */
332  )
333 {
334  return inferinfo.val.asint;
335 }
336 
337 /** returns the propagation rule stored in the inference information */
338 static
340  INFERINFO inferinfo /**< inference information to convert */
341  )
342 {
343  return (int) inferinfo.val.asbits.proprule;
344 }
345 
346 /** returns the position stored in the inference information */
347 static
349  INFERINFO inferinfo /**< inference information to convert */
350  )
351 {
352  return (int) inferinfo.val.asbits.pos;
353 }
354 
355 /** constructs an inference information out of a propagation rule and a position number */
356 static
358  PROPRULE proprule, /**< propagation rule that deduced the value */
359  int pos /**< variable position, the propagation rule was applied at */
360  )
361 {
362  INFERINFO inferinfo;
363  assert( pos >= 0 );
364 
365  inferinfo.val.asbits.proprule = (unsigned int) proprule; /*lint !e641*/
366  inferinfo.val.asbits.pos = (unsigned int) pos; /*lint !e732*/
367 
368  return inferinfo;
369 }
370 
371 /** constructs an inference information out of a propagation rule and a position number, returns info as int */
372 static
374  PROPRULE proprule, /**< propagation rule that deduced the value */
375  int pos /**< variable position, the propagation rule was applied at */
376  )
377 {
378  return inferInfoToInt(getInferInfo(proprule, pos));
379 }
380 
381 
382 /*
383  * memory growing methods for dynamically allocated arrays
384  */
385 
386 /** ensures, that linconsupgrades array can store at least num entries */
387 static
389  SCIP* scip, /**< SCIP data structure */
390  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
391  int num /**< minimum number of entries to store */
392  )
393 {
394  assert(scip != NULL);
395  assert(conshdlrdata != NULL);
396  assert(conshdlrdata->nlinconsupgrades <= conshdlrdata->linconsupgradessize);
397 
398  if( num > conshdlrdata->linconsupgradessize )
399  {
400  int newsize;
401 
402  newsize = SCIPcalcMemGrowSize(scip, num);
403  SCIP_CALL( SCIPreallocMemoryArray(scip, &conshdlrdata->linconsupgrades, newsize) );
404  conshdlrdata->linconsupgradessize = newsize;
405  }
406  assert(num <= conshdlrdata->linconsupgradessize);
407 
408  return SCIP_OKAY;
409 }
410 
411 /** ensures, that vars and vals arrays can store at least num entries */
412 static
414  SCIP* scip, /**< SCIP data structure */
415  SCIP_CONSDATA* consdata, /**< linear constraint data */
416  int num /**< minimum number of entries to store */
417  )
418 {
419  assert(scip != NULL);
420  assert(consdata != NULL);
421  assert(consdata->nvars <= consdata->varssize);
422 
423  if( num > consdata->varssize )
424  {
425  int newsize;
426 
427  newsize = SCIPcalcMemGrowSize(scip, num);
428  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->varssize, newsize) );
429  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vals, consdata->varssize, newsize) );
430  if( consdata->eventdatas != NULL )
431  {
432  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->eventdatas, consdata->varssize, newsize) );
433  }
434  consdata->varssize = newsize;
435  }
436  assert(num <= consdata->varssize);
437 
438  return SCIP_OKAY;
439 }
440 
441 
442 /*
443  * local methods for managing linear constraint update methods
444  */
445 
446 /** creates a linear constraint upgrade data object */
447 static
449  SCIP* scip, /**< SCIP data structure */
450  SCIP_LINCONSUPGRADE** linconsupgrade, /**< pointer to store the linear constraint upgrade */
451  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
452  int priority /**< priority of upgrading method */
453  )
454 {
455  assert(scip != NULL);
456  assert(linconsupgrade != NULL);
457  assert(linconsupgd != NULL);
458 
459  SCIP_CALL( SCIPallocMemory(scip, linconsupgrade) );
460  (*linconsupgrade)->linconsupgd = linconsupgd;
461  (*linconsupgrade)->priority = priority;
462  (*linconsupgrade)->active = TRUE;
463 
464  return SCIP_OKAY;
465 }
466 
467 /** frees a linear constraint upgrade data object */
468 static
470  SCIP* scip, /**< SCIP data structure */
471  SCIP_LINCONSUPGRADE** linconsupgrade /**< pointer to the linear constraint upgrade */
472  )
473 {
474  assert(scip != NULL);
475  assert(linconsupgrade != NULL);
476  assert(*linconsupgrade != NULL);
477 
478  SCIPfreeMemory(scip, linconsupgrade);
479 }
480 
481 /** creates constraint handler data for linear constraint handler */
482 static
484  SCIP* scip, /**< SCIP data structure */
485  SCIP_CONSHDLRDATA** conshdlrdata, /**< pointer to store the constraint handler data */
486  SCIP_EVENTHDLR* eventhdlr /**< event handler */
487  )
488 {
489  assert(scip != NULL);
490  assert(conshdlrdata != NULL);
491  assert(eventhdlr != NULL);
492 
493  SCIP_CALL( SCIPallocMemory(scip, conshdlrdata) );
494  (*conshdlrdata)->linconsupgrades = NULL;
495  (*conshdlrdata)->linconsupgradessize = 0;
496  (*conshdlrdata)->nlinconsupgrades = 0;
497 
498  /* set event handler for updating linear constraint activity bounds */
499  (*conshdlrdata)->eventhdlr = eventhdlr;
500 
501  return SCIP_OKAY;
502 }
503 
504 /** frees constraint handler data for linear constraint handler */
505 static
507  SCIP* scip, /**< SCIP data structure */
508  SCIP_CONSHDLRDATA** conshdlrdata /**< pointer to the constraint handler data */
509  )
510 {
511  int i;
512 
513  assert(scip != NULL);
514  assert(conshdlrdata != NULL);
515  assert(*conshdlrdata != NULL);
516 
517  for( i = 0; i < (*conshdlrdata)->nlinconsupgrades; ++i )
518  {
519  linconsupgradeFree(scip, &(*conshdlrdata)->linconsupgrades[i]);
520  }
521  SCIPfreeMemoryArrayNull(scip, &(*conshdlrdata)->linconsupgrades);
522 
523  SCIPfreeMemory(scip, conshdlrdata);
524 }
525 
526 /** creates a linear constraint upgrade data object */
527 static
529  SCIP* scip, /**< SCIP data structure */
530  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
531  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
532  const char* conshdlrname /**< name of the constraint handler */
533  )
534 {
535  int i;
536 
537  assert(scip != NULL);
538  assert(conshdlrdata != NULL);
539  assert(linconsupgd != NULL);
540  assert(conshdlrname != NULL);
541 
542  for( i = conshdlrdata->nlinconsupgrades - 1; i >= 0; --i )
543  {
544  if( conshdlrdata->linconsupgrades[i]->linconsupgd == linconsupgd )
545  {
546 #ifdef SCIP_DEBUG
547  SCIPwarningMessage(scip, "Try to add already known upgrade message %p for constraint handler %s.\n", linconsupgd, conshdlrname);
548 #endif
549  return TRUE;
550  }
551  }
552 
553  return FALSE;
554 }
555 
556 /** adds a linear constraint update method to the constraint handler's data */
557 static
559  SCIP* scip, /**< SCIP data structure */
560  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
561  SCIP_LINCONSUPGRADE* linconsupgrade /**< linear constraint upgrade method */
562  )
563 {
564  int i;
565 
566  assert(scip != NULL);
567  assert(conshdlrdata != NULL);
568  assert(linconsupgrade != NULL);
569 
570  SCIP_CALL( conshdlrdataEnsureLinconsupgradesSize(scip, conshdlrdata, conshdlrdata->nlinconsupgrades+1) );
571 
572  for( i = conshdlrdata->nlinconsupgrades;
573  i > 0 && conshdlrdata->linconsupgrades[i-1]->priority < linconsupgrade->priority; --i )
574  {
575  conshdlrdata->linconsupgrades[i] = conshdlrdata->linconsupgrades[i-1];
576  }
577  assert(0 <= i && i <= conshdlrdata->nlinconsupgrades);
578  conshdlrdata->linconsupgrades[i] = linconsupgrade;
579  conshdlrdata->nlinconsupgrades++;
580 
581  return SCIP_OKAY;
582 }
583 
584 /*
585  * local methods
586  */
587 
588 /** installs rounding locks for the given variable associated to the given coefficient in the linear constraint */
589 static
591  SCIP* scip, /**< SCIP data structure */
592  SCIP_CONS* cons, /**< linear constraint */
593  SCIP_VAR* var, /**< variable of constraint entry */
594  SCIP_Real val /**< coefficient of constraint entry */
595  )
596 {
597  SCIP_CONSDATA* consdata;
598 
599  assert(scip != NULL);
600  assert(cons != NULL);
601  assert(var != NULL);
602 
603  consdata = SCIPconsGetData(cons);
604  assert(consdata != NULL);
605  assert(!SCIPisZero(scip, val));
606 
607  if( SCIPisPositive(scip, val) )
608  {
609  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
610  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
611  }
612  else
613  {
614  SCIP_CALL( SCIPlockVarCons(scip, var, cons,
615  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
616  }
617 
618  return SCIP_OKAY;
619 }
620 
621 /** removes rounding locks for the given variable associated to the given coefficient in the linear constraint */
622 static
624  SCIP* scip, /**< SCIP data structure */
625  SCIP_CONS* cons, /**< linear constraint */
626  SCIP_VAR* var, /**< variable of constraint entry */
627  SCIP_Real val /**< coefficient of constraint entry */
628  )
629 {
630  SCIP_CONSDATA* consdata;
631 
632  assert(scip != NULL);
633  assert(cons != NULL);
634  assert(var != NULL);
635 
636  consdata = SCIPconsGetData(cons);
637  assert(consdata != NULL);
638  assert(!SCIPisZero(scip, val));
639 
640  if( SCIPisPositive(scip, val) )
641  {
642  SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
643  !SCIPisInfinity(scip, -consdata->lhs), !SCIPisInfinity(scip, consdata->rhs)) );
644  }
645  else
646  {
647  SCIP_CALL( SCIPunlockVarCons(scip, var, cons,
648  !SCIPisInfinity(scip, consdata->rhs), !SCIPisInfinity(scip, -consdata->lhs)) );
649  }
650 
651  return SCIP_OKAY;
652 }
653 
654 /** creates event data for variable at given position, and catches events */
655 static
657  SCIP* scip, /**< SCIP data structure */
658  SCIP_CONS* cons, /**< linear constraint */
659  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
660  int pos /**< array position of variable to catch bound change events for */
661  )
662 {
663  SCIP_CONSDATA* consdata;
664  assert(scip != NULL);
665  assert(cons != NULL);
666  assert(eventhdlr != NULL);
667 
668  consdata = SCIPconsGetData(cons);
669  assert(consdata != NULL);
670 
671  assert(0 <= pos && pos < consdata->nvars);
672  assert(consdata->vars != NULL);
673  assert(consdata->vars[pos] != NULL);
674  assert(SCIPvarIsTransformed(consdata->vars[pos]));
675  assert(consdata->eventdatas != NULL);
676  assert(consdata->eventdatas[pos] == NULL);
677 
678  SCIP_CALL( SCIPallocBlockMemory(scip, &(consdata->eventdatas[pos])) ); /*lint !e866*/
679  consdata->eventdatas[pos]->cons = cons;
680  consdata->eventdatas[pos]->varpos = pos;
681 
682  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos],
685  eventhdlr, consdata->eventdatas[pos], &consdata->eventdatas[pos]->filterpos) );
686 
687  return SCIP_OKAY;
688 }
689 
690 /** deletes event data for variable at given position, and drops events */
691 static
693  SCIP* scip, /**< SCIP data structure */
694  SCIP_CONS* cons, /**< linear constraint */
695  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
696  int pos /**< array position of variable to catch bound change events for */
697  )
698 {
699  SCIP_CONSDATA* consdata;
700  assert(scip != NULL);
701  assert(cons != NULL);
702  assert(eventhdlr != NULL);
703 
704  consdata = SCIPconsGetData(cons);
705  assert(consdata != NULL);
706 
707  assert(0 <= pos && pos < consdata->nvars);
708  assert(consdata->vars[pos] != NULL);
709  assert(consdata->eventdatas != NULL);
710  assert(consdata->eventdatas[pos] != NULL);
711  assert(consdata->eventdatas[pos]->cons == cons);
712  assert(consdata->eventdatas[pos]->varpos == pos);
713 
714  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos],
717  eventhdlr, consdata->eventdatas[pos], consdata->eventdatas[pos]->filterpos) );
718 
719  SCIPfreeBlockMemory(scip, &consdata->eventdatas[pos]); /*lint !e866*/
720 
721  return SCIP_OKAY;
722 }
723 
724 /** catches bound change events for all variables in transformed linear constraint */
725 static
727  SCIP* scip, /**< SCIP data structure */
728  SCIP_CONS* cons, /**< linear constraint */
729  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
730  )
731 {
732  SCIP_CONSDATA* consdata;
733  int i;
734 
735  assert(scip != NULL);
736  assert(cons != NULL);
737 
738  consdata = SCIPconsGetData(cons);
739  assert(consdata != NULL);
740  assert(consdata->eventdatas == NULL);
741 
742  /* allocate eventdatas array */
743  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->eventdatas, consdata->varssize) );
744  assert(consdata->eventdatas != NULL);
745  BMSclearMemoryArray(consdata->eventdatas, consdata->nvars);
746 
747  /* catch event for every single variable */
748  for( i = 0; i < consdata->nvars; ++i )
749  {
750  SCIP_CALL( consCatchEvent(scip, cons, eventhdlr, i) );
751  }
752 
753  return SCIP_OKAY;
754 }
755 
756 /** drops bound change events for all variables in transformed linear constraint */
757 static
759  SCIP* scip, /**< SCIP data structure */
760  SCIP_CONS* cons, /**< linear constraint */
761  SCIP_EVENTHDLR* eventhdlr /**< event handler to call for the event processing */
762  )
763 {
764  SCIP_CONSDATA* consdata;
765  int i;
766 
767  assert(scip != NULL);
768  assert(cons != NULL);
769 
770  consdata = SCIPconsGetData(cons);
771  assert(consdata != NULL);
772  assert(consdata->eventdatas != NULL);
773 
774  /* drop event of every single variable */
775  for( i = consdata->nvars - 1; i >= 0; --i )
776  {
777  SCIP_CALL( consDropEvent(scip, cons, eventhdlr, i) );
778  }
779 
780  /* free eventdatas array */
781  SCIPfreeBlockMemoryArray(scip, &consdata->eventdatas, consdata->varssize);
782  assert(consdata->eventdatas == NULL);
783 
784  return SCIP_OKAY;
785 }
786 
787 /** returns whether we are in a stage, where the variable events should be caught */
788 static
790  SCIP* scip /**< SCIP data structure */
791  )
792 {
793  assert(scip != NULL);
794 
796 }
797 
798 /** creates a linear constraint data */
799 static
801  SCIP* scip, /**< SCIP data structure */
802  SCIP_CONSDATA** consdata, /**< pointer to linear constraint data */
803  int nvars, /**< number of nonzeros in the constraint */
804  SCIP_VAR** vars, /**< array with variables of constraint entries */
805  SCIP_Real* vals, /**< array with coefficients of constraint entries */
806  SCIP_Real lhs, /**< left hand side of row */
807  SCIP_Real rhs /**< right hand side of row */
808  )
809 {
810  int v;
811 
812  assert(scip != NULL);
813  assert(consdata != NULL);
814  assert(nvars == 0 || vars != NULL);
815  assert(nvars == 0 || vals != NULL);
816 
817  if( SCIPisInfinity(scip, rhs) )
818  rhs = SCIPinfinity(scip);
819  else if( SCIPisInfinity(scip, -rhs) )
820  rhs = -SCIPinfinity(scip);
821 
822  if( SCIPisInfinity(scip, -lhs) )
823  lhs = -SCIPinfinity(scip);
824  else if( SCIPisInfinity(scip, lhs) )
825  lhs = SCIPinfinity(scip);
826 
827  if( SCIPisGT(scip, lhs, rhs) )
828  {
829  SCIPerrorMessage("left hand side of linear constraint greater than right hand side\n");
830  SCIPerrorMessage(" -> lhs=%g, rhs=%g\n", lhs, rhs);
831  return SCIP_INVALIDDATA;
832  }
833 
834  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
835 
836  (*consdata)->varssize = nvars;
837  (*consdata)->nvars = nvars;
838  if( nvars > 0 )
839  {
840  int k;
841 
842  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars, vars, nvars) );
843  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vals, vals, nvars) );
844  k = 0;
845  for( v = 0; v < nvars; ++v )
846  {
847  assert((*consdata)->vars[v] != NULL);
848  if( !SCIPisZero(scip, (*consdata)->vals[v]) )
849  {
850  (*consdata)->vars[k] = (*consdata)->vars[v];
851  (*consdata)->vals[k] = (*consdata)->vals[v];
852  k++;
853  }
854  }
855  (*consdata)->nvars = k;
856  }
857  else
858  {
859  (*consdata)->vars = NULL;
860  (*consdata)->vals = NULL;
861  }
862  (*consdata)->eventdatas = NULL;
863 
864  (*consdata)->row = NULL;
865  (*consdata)->lhs = lhs;
866  (*consdata)->rhs = rhs;
867  (*consdata)->maxabsval = SCIP_INVALID;
868  (*consdata)->minactivity = SCIP_INVALID;
869  (*consdata)->maxactivity = SCIP_INVALID;
870  (*consdata)->lastminactivity = SCIP_INVALID;
871  (*consdata)->lastmaxactivity = SCIP_INVALID;
872  (*consdata)->maxactdelta = SCIP_INVALID;
873  (*consdata)->minactivityneginf = -1;
874  (*consdata)->minactivityposinf = -1;
875  (*consdata)->maxactivityneginf = -1;
876  (*consdata)->maxactivityposinf = -1;
877  (*consdata)->minactivityneghuge = -1;
878  (*consdata)->minactivityposhuge = -1;
879  (*consdata)->maxactivityneghuge = -1;
880  (*consdata)->maxactivityposhuge = -1;
881  (*consdata)->glbminactivity = SCIP_INVALID;
882  (*consdata)->glbmaxactivity = SCIP_INVALID;
883  (*consdata)->lastglbminactivity = SCIP_INVALID;
884  (*consdata)->lastglbmaxactivity = SCIP_INVALID;
885  (*consdata)->glbminactivityneginf = -1;
886  (*consdata)->glbminactivityposinf = -1;
887  (*consdata)->glbmaxactivityneginf = -1;
888  (*consdata)->glbmaxactivityposinf = -1;
889  (*consdata)->glbminactivityneghuge = -1;
890  (*consdata)->glbminactivityposhuge = -1;
891  (*consdata)->glbmaxactivityneghuge = -1;
892  (*consdata)->glbmaxactivityposhuge = -1;
893  (*consdata)->possignature = 0;
894  (*consdata)->negsignature = 0;
895  (*consdata)->validmaxabsval = FALSE;
896  (*consdata)->validactivities = FALSE;
897  (*consdata)->validminact = FALSE;
898  (*consdata)->validmaxact = FALSE;
899  (*consdata)->validglbminact = FALSE;
900  (*consdata)->validglbmaxact = FALSE;
901  (*consdata)->propagated = FALSE;
902  (*consdata)->boundstightened = FALSE;
903  (*consdata)->presolved = FALSE;
904  (*consdata)->removedfixings = FALSE;
905  (*consdata)->validsignature = FALSE;
906  (*consdata)->changed = TRUE;
907  (*consdata)->normalized = FALSE;
908  (*consdata)->upgradetried = FALSE;
909  (*consdata)->upgraded = FALSE;
910  (*consdata)->sorted = (nvars <= 1);
911  (*consdata)->merged = (nvars <= 1);
912  (*consdata)->cliquesadded = FALSE;
913  (*consdata)->implsadded = FALSE;
914  (*consdata)->binvarssorted = FALSE;
915  (*consdata)->nbinvars = -1;
916  (*consdata)->varsdeleted = FALSE;
917 
918  if( SCIPisTransformed(scip) )
919  {
920  /* get transformed variables */
921  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
922  }
923 
924  /* capture variables */
925  for( v = 0; v < (*consdata)->nvars; v++ )
926  {
927  assert((*consdata)->vars[v] != NULL);
928  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
929  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[v]) );
930  }
931 
932  return SCIP_OKAY;
933 }
934 
935 /** frees a linear constraint data */
936 static
938  SCIP* scip, /**< SCIP data structure */
939  SCIP_CONSDATA** consdata /**< pointer to linear constraint data */
940  )
941 {
942  int v;
943 
944  assert(scip != NULL);
945  assert(consdata != NULL);
946  assert(*consdata != NULL);
947  assert((*consdata)->varssize >= 0);
948 
949  /* release the row */
950  if( (*consdata)->row != NULL )
951  {
952  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
953  }
954 
955  /* release variables */
956  for( v = 0; v < (*consdata)->nvars; v++ )
957  {
958  assert((*consdata)->vars[v] != NULL);
959  assert(!SCIPisZero(scip, (*consdata)->vals[v]));
960  SCIP_CALL( SCIPreleaseVar(scip, &((*consdata)->vars[v])) );
961  }
962 
963  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vars, (*consdata)->varssize);
964  SCIPfreeBlockMemoryArrayNull(scip, &(*consdata)->vals, (*consdata)->varssize);
965  SCIPfreeBlockMemory(scip, consdata);
966 
967  return SCIP_OKAY;
968 }
969 
970 /** prints linear constraint in CIP format to file stream */
971 static
973  SCIP* scip, /**< SCIP data structure */
974  SCIP_CONSDATA* consdata, /**< linear constraint data */
975  FILE* file /**< output file (or NULL for standard output) */
976  )
977 {
978  assert(scip != NULL);
979  assert(consdata != NULL);
980 
981  /* print left hand side for ranged rows */
982  if( !SCIPisInfinity(scip, -consdata->lhs)
983  && !SCIPisInfinity(scip, consdata->rhs)
984  && !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
985  SCIPinfoMessage(scip, file, "%.15g <= ", consdata->lhs);
986 
987  /* print coefficients and variables */
988  if( consdata->nvars == 0 )
989  SCIPinfoMessage(scip, file, "0");
990  else
991  {
992  /* post linear sum of the linear constraint */
993  SCIP_CALL( SCIPwriteVarsLinearsum(scip, file, consdata->vars, consdata->vals, consdata->nvars, TRUE) );
994  }
995 
996  /* print right hand side */
997  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
998  SCIPinfoMessage(scip, file, " == %.15g", consdata->rhs);
999  else if( !SCIPisInfinity(scip, consdata->rhs) )
1000  SCIPinfoMessage(scip, file, " <= %.15g", consdata->rhs);
1001  else if( !SCIPisInfinity(scip, -consdata->lhs) )
1002  SCIPinfoMessage(scip, file, " >= %.15g", consdata->lhs);
1003  else
1004  SCIPinfoMessage(scip, file, " [free]");
1005 
1006  return SCIP_OKAY;
1007 }
1008 
1009 /** invalidates activity bounds, such that they are recalculated in next get */
1010 static
1012  SCIP_CONSDATA* consdata /**< linear constraint */
1013  )
1014 {
1015  assert(consdata != NULL);
1016 
1017  consdata->validactivities = FALSE;
1018  consdata->validminact = FALSE;
1019  consdata->validmaxact = FALSE;
1020  consdata->validglbminact = FALSE;
1021  consdata->validglbmaxact = FALSE;
1022  consdata->minactivity = SCIP_INVALID;
1023  consdata->maxactivity = SCIP_INVALID;
1024  consdata->lastminactivity = SCIP_INVALID;
1025  consdata->lastmaxactivity = SCIP_INVALID;
1026  consdata->maxactdelta = SCIP_INVALID;
1027  consdata->minactivityneginf = -1;
1028  consdata->minactivityposinf = -1;
1029  consdata->maxactivityneginf = -1;
1030  consdata->maxactivityposinf = -1;
1031  consdata->minactivityneghuge = -1;
1032  consdata->minactivityposhuge = -1;
1033  consdata->maxactivityneghuge = -1;
1034  consdata->maxactivityposhuge = -1;
1035  consdata->glbminactivity = SCIP_INVALID;
1036  consdata->glbmaxactivity = SCIP_INVALID;
1037  consdata->lastglbminactivity = SCIP_INVALID;
1038  consdata->lastglbmaxactivity = SCIP_INVALID;
1039  consdata->glbminactivityneginf = -1;
1040  consdata->glbminactivityposinf = -1;
1041  consdata->glbmaxactivityneginf = -1;
1042  consdata->glbmaxactivityposinf = -1;
1043  consdata->glbminactivityneghuge = -1;
1044  consdata->glbminactivityposhuge = -1;
1045  consdata->glbmaxactivityneghuge = -1;
1046  consdata->glbmaxactivityposhuge = -1;
1047 }
1048 
1049 /** compute the pseudo activity of a constraint */
1050 static
1052  SCIP* scip, /**< SCIP data structure */
1053  SCIP_CONSDATA* consdata /**< linear constraint data */
1054  )
1055 {
1056  int i;
1057  int pseudoactivityposinf;
1058  int pseudoactivityneginf;
1059  SCIP_Real pseudoactivity;
1060  SCIP_Real bound;
1061  SCIP_Real val;
1062 
1063  pseudoactivity = 0;
1064  pseudoactivityposinf = 0;
1065  pseudoactivityneginf = 0;
1066 
1067  for( i = consdata->nvars - 1; i >= 0; --i )
1068  {
1069  val = consdata->vals[i];
1070  bound = (SCIPvarGetBestBoundType(consdata->vars[i]) == SCIP_BOUNDTYPE_LOWER) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1071  if( SCIPisInfinity(scip, bound) )
1072  {
1073  if( val > 0.0 )
1074  pseudoactivityposinf++;
1075  else
1076  pseudoactivityneginf++;
1077  }
1078  else
1079  {
1080  if( SCIPisInfinity(scip, -bound) )
1081  {
1082  if( val > 0.0 )
1083  pseudoactivityneginf++;
1084  else
1085  pseudoactivityposinf++;
1086  }
1087  else
1088  pseudoactivity += val * bound;
1089  }
1090  }
1091 
1092  if( pseudoactivityneginf > 0 )
1093  return -SCIPinfinity(scip);
1094  else if( pseudoactivityposinf > 0 )
1095  return SCIPinfinity(scip);
1096 
1097  return pseudoactivity;
1098 }
1099 
1100 /** recompute the minactivity of a constraint */
1101 static
1103  SCIP* scip, /**< SCIP data structure */
1104  SCIP_CONSDATA* consdata /**< linear constraint data */
1105  )
1106 {
1107  int i;
1108  SCIP_Real bound;
1109 
1110  consdata->minactivity = 0;
1111 
1112  for( i = consdata->nvars - 1; i >= 0; --i )
1113  {
1114  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbLocal(consdata->vars[i]) : SCIPvarGetUbLocal(consdata->vars[i]);
1115  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1116  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1117  consdata->minactivity += consdata->vals[i] * bound;
1118  }
1119 
1120  /* the activity was just computed from scratch and is valid now */
1121  consdata->validminact = TRUE;
1122 
1123  /* the activity was just computed from scratch, mark it to be reliable */
1124  consdata->lastminactivity = consdata->minactivity;
1125 }
1126 
1127 /** recompute the maxactivity of a constraint */
1128 static
1130  SCIP* scip, /**< SCIP data structure */
1131  SCIP_CONSDATA* consdata /**< linear constraint data */
1132  )
1133 {
1134  int i;
1135  SCIP_Real bound;
1136 
1137  consdata->maxactivity = 0;
1138 
1139  for( i = consdata->nvars - 1; i >= 0; --i )
1140  {
1141  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbLocal(consdata->vars[i]) : SCIPvarGetLbLocal(consdata->vars[i]);
1142  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound)
1143  && !SCIPisHugeValue(scip, consdata->vals[i] * bound) && !SCIPisHugeValue(scip, -consdata->vals[i] * bound) )
1144  consdata->maxactivity += consdata->vals[i] * bound;
1145  }
1146 
1147  /* the activity was just computed from scratch and is valid now */
1148  consdata->validmaxact = TRUE;
1149 
1150  /* the activity was just computed from scratch, mark it to be reliable */
1151  consdata->lastmaxactivity = consdata->maxactivity;
1152 }
1153 
1154 /** recompute the global minactivity of a constraint */
1155 static
1157  SCIP* scip, /**< SCIP data structure */
1158  SCIP_CONSDATA* consdata /**< linear constraint data */
1159  )
1160 {
1161  int i;
1162  SCIP_Real bound;
1163 
1164  consdata->glbminactivity = 0;
1165 
1166  for( i = consdata->nvars - 1; i >= 0; --i )
1167  {
1168  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetLbGlobal(consdata->vars[i]) : SCIPvarGetUbGlobal(consdata->vars[i]);
1169  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) )
1170  consdata->glbminactivity += consdata->vals[i] * bound;
1171  }
1172 
1173  /* the activity was just computed from scratch and is valid now */
1174  consdata->validglbminact = TRUE;
1175 
1176  /* the activity was just computed from scratch, mark it to be reliable */
1177  consdata->lastglbminactivity = consdata->glbminactivity;
1178 }
1179 
1180 /** recompute the global maxactivity of a constraint */
1181 static
1183  SCIP* scip, /**< SCIP data structure */
1184  SCIP_CONSDATA* consdata /**< linear constraint data */
1185  )
1186 {
1187  int i;
1188  SCIP_Real bound;
1189 
1190  consdata->glbmaxactivity = 0;
1191 
1192  for( i = consdata->nvars - 1; i >= 0; --i )
1193  {
1194  bound = (consdata->vals[i] > 0.0 ) ? SCIPvarGetUbGlobal(consdata->vars[i]) : SCIPvarGetLbGlobal(consdata->vars[i]);
1195  if( !SCIPisInfinity(scip, bound) && !SCIPisInfinity(scip, -bound) )
1196  consdata->glbmaxactivity += consdata->vals[i] * bound;
1197  }
1198 
1199  /* the activity was just computed from scratch and is valid now */
1200  consdata->validglbmaxact = TRUE;
1201 
1202  /* the activity was just computed from scratch, mark it to be reliable */
1203  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1204 }
1205 
1206 /** recompute maximal activity contribution for a single variable */
1207 static
1209  SCIP* scip, /**< SCIP data structure */
1210  SCIP_CONSDATA* consdata /**< linear constraint data */
1211  )
1212 {
1213  SCIP_Real domain;
1214  SCIP_Real delta;
1215  SCIP_Real lb;
1216  SCIP_Real ub;
1217  int v;
1218 
1219  consdata->maxactdelta = 0.0;
1220 
1221  for( v = consdata->nvars - 1; v >= 0; --v )
1222  {
1223  lb = SCIPvarGetLbLocal(consdata->vars[v]);
1224  ub = SCIPvarGetUbLocal(consdata->vars[v]);
1225 
1226  if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
1227  {
1228  consdata->maxactdelta = SCIPinfinity(scip);
1229  break;
1230  }
1231 
1232  domain = ub - lb;
1233  delta = REALABS(consdata->vals[v]) * domain;
1234 
1235  consdata->maxactdelta = MAX(delta, consdata->maxactdelta);
1236  }
1237 }
1238 
1239 
1240 /** updates activities for a change in a bound */
1241 static
1243  SCIP* scip, /**< SCIP data structure */
1244  SCIP_CONSDATA* consdata, /**< linear constraint data */
1245  SCIP_VAR* var, /**< variable that has been changed; can be NULL for global bound changes */
1246  SCIP_Real oldbound, /**< old bound of variable */
1247  SCIP_Real newbound, /**< new bound of variable */
1248  SCIP_Real val, /**< coefficient of constraint entry */
1249  SCIP_BOUNDTYPE boundtype, /**< type of the bound change */
1250  SCIP_Bool global, /**< is it a global or a local bound change? */
1251  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1252  )
1253 {
1254  SCIP_Real* activity;
1255  SCIP_Real* lastactivity;
1256  int* activityposinf;
1257  int* activityneginf;
1258  int* activityposhuge;
1259  int* activityneghuge;
1260  SCIP_Real delta;
1261  SCIP_Bool validact;
1262 
1263  assert(scip != NULL);
1264  assert(consdata != NULL);
1265  assert(global || (var != NULL));
1266  assert(consdata->validactivities);
1267  assert(consdata->minactivity < SCIP_INVALID);
1268  assert(consdata->maxactivity < SCIP_INVALID);
1269  assert(consdata->lastminactivity < SCIP_INVALID);
1270  assert(consdata->lastmaxactivity < SCIP_INVALID);
1271  assert(consdata->minactivityneginf >= 0);
1272  assert(consdata->minactivityposinf >= 0);
1273  assert(consdata->maxactivityneginf >= 0);
1274  assert(consdata->maxactivityposinf >= 0);
1275  assert(consdata->minactivityneghuge >= 0);
1276  assert(consdata->minactivityposhuge >= 0);
1277  assert(consdata->maxactivityneghuge >= 0);
1278  assert(consdata->maxactivityposhuge >= 0);
1279  assert(consdata->glbminactivity < SCIP_INVALID);
1280  assert(consdata->glbmaxactivity < SCIP_INVALID);
1281  assert(consdata->lastglbminactivity < SCIP_INVALID);
1282  assert(consdata->lastglbmaxactivity < SCIP_INVALID);
1283  assert(consdata->glbminactivityneginf >= 0);
1284  assert(consdata->glbminactivityposinf >= 0);
1285  assert(consdata->glbmaxactivityneginf >= 0);
1286  assert(consdata->glbmaxactivityposinf >= 0);
1287  assert(consdata->glbminactivityneghuge >= 0);
1288  assert(consdata->glbminactivityposhuge >= 0);
1289  assert(consdata->glbmaxactivityneghuge >= 0);
1290  assert(consdata->glbmaxactivityposhuge >= 0);
1291 
1292  delta = 0.0;
1293 
1294  /* we are updating global activities */
1295  if( global )
1296  {
1297  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1298  * lower bound + pos. coef: update minactivity
1299  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1300  * upper bound + pos. coef: update maxactivity
1301  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1302  */
1303  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1304  {
1305  if( val > 0.0 )
1306  {
1307  activity = &(consdata->glbminactivity);
1308  lastactivity = &(consdata->lastglbminactivity);
1309  activityposinf = &(consdata->glbminactivityposinf);
1310  activityneginf = &(consdata->glbminactivityneginf);
1311  activityposhuge = &(consdata->glbminactivityposhuge);
1312  activityneghuge = &(consdata->glbminactivityneghuge);
1313  validact = consdata->validglbminact;
1314  }
1315  else
1316  {
1317  activity = &(consdata->glbmaxactivity);
1318  lastactivity = &(consdata->lastglbmaxactivity);
1319  activityposinf = &(consdata->glbmaxactivityneginf);
1320  activityneginf = &(consdata->glbmaxactivityposinf);
1321  activityposhuge = &(consdata->glbmaxactivityposhuge);
1322  activityneghuge = &(consdata->glbmaxactivityneghuge);
1323  validact = consdata->validglbmaxact;
1324  }
1325  }
1326  else
1327  {
1328  if( val > 0.0 )
1329  {
1330  activity = &(consdata->glbmaxactivity);
1331  lastactivity = &(consdata->lastglbmaxactivity);
1332  activityposinf = &(consdata->glbmaxactivityposinf);
1333  activityneginf = &(consdata->glbmaxactivityneginf);
1334  activityposhuge = &(consdata->glbmaxactivityposhuge);
1335  activityneghuge = &(consdata->glbmaxactivityneghuge);
1336  validact = consdata->validglbmaxact;
1337  }
1338  else
1339  {
1340  activity = &(consdata->glbminactivity);
1341  lastactivity = &(consdata->lastglbminactivity);
1342  activityposinf = &(consdata->glbminactivityneginf);
1343  activityneginf = &(consdata->glbminactivityposinf);
1344  activityposhuge = &(consdata->glbminactivityposhuge);
1345  activityneghuge = &(consdata->glbminactivityneghuge);
1346  validact = consdata->validglbminact;
1347  }
1348  }
1349  }
1350  /* we are updating local activities */
1351  else
1352  {
1353  /* depending on the boundtype and the coefficient, we choose the activity to be updated:
1354  * lower bound + pos. coef: update minactivity
1355  * lower bound + neg. coef: update maxactivity, positive and negative infinity counters have to be switched
1356  * upper bound + pos. coef: update maxactivity
1357  * upper bound + neg. coef: update minactivity, positive and negative infinity counters have to be switched
1358  */
1359  if( boundtype == SCIP_BOUNDTYPE_LOWER )
1360  {
1361  if( val > 0.0 )
1362  {
1363  activity = &(consdata->minactivity);
1364  lastactivity = &(consdata->lastminactivity);
1365  activityposinf = &(consdata->minactivityposinf);
1366  activityneginf = &(consdata->minactivityneginf);
1367  activityposhuge = &(consdata->minactivityposhuge);
1368  activityneghuge = &(consdata->minactivityneghuge);
1369  validact = consdata->validminact;
1370  }
1371  else
1372  {
1373  activity = &(consdata->maxactivity);
1374  lastactivity = &(consdata->lastmaxactivity);
1375  activityposinf = &(consdata->maxactivityneginf);
1376  activityneginf = &(consdata->maxactivityposinf);
1377  activityposhuge = &(consdata->maxactivityposhuge);
1378  activityneghuge = &(consdata->maxactivityneghuge);
1379  validact = consdata->validmaxact;
1380  }
1381  }
1382  else
1383  {
1384  if( val > 0.0 )
1385  {
1386  activity = &(consdata->maxactivity);
1387  lastactivity = &(consdata->lastmaxactivity);
1388  activityposinf = &(consdata->maxactivityposinf);
1389  activityneginf = &(consdata->maxactivityneginf);
1390  activityposhuge = &(consdata->maxactivityposhuge);
1391  activityneghuge = &(consdata->maxactivityneghuge);
1392  validact = consdata->validmaxact;
1393  }
1394  else
1395  {
1396  activity = &(consdata->minactivity);
1397  lastactivity = &(consdata->lastminactivity);
1398  activityposinf = &(consdata->minactivityneginf);
1399  activityneginf = &(consdata->minactivityposinf);
1400  activityposhuge = &(consdata->minactivityposhuge);
1401  activityneghuge = &(consdata->minactivityneghuge);
1402  validact = consdata->validminact;
1403  }
1404  }
1405  }
1406 
1407  /* old bound was +infinity */
1408  if( SCIPisInfinity(scip, oldbound) )
1409  {
1410  assert((*activityposinf) >= 1);
1411 
1412  /* we only have to do something if the new bound is not again +infinity */
1413  if( !SCIPisInfinity(scip, newbound) )
1414  {
1415  /* decrease the counter for positive infinite contributions */
1416  (*activityposinf)--;
1417 
1418  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1419  if( SCIPisInfinity(scip, -newbound) )
1420  (*activityneginf)++;
1421  /* if the contribution of this variable is too large, increase the counter for huge values */
1422  else if( SCIPisHugeValue(scip, val * newbound) )
1423  {
1424  (*activityposhuge)++;
1425  }
1426  else if( SCIPisHugeValue(scip, -val * newbound) )
1427  {
1428  (*activityneghuge)++;
1429  }
1430  /* "normal case": just add the contribution to the activity */
1431  else
1432  delta = val * newbound;
1433  }
1434  }
1435  /* old bound was -infinity */
1436  else if( SCIPisInfinity(scip, -oldbound) )
1437  {
1438  assert((*activityneginf) >= 1);
1439 
1440  /* we only have to do something ig the new bound is not again -infinity */
1441  if( !SCIPisInfinity(scip, -newbound) )
1442  {
1443  /* decrease the counter for negative infinite contributions */
1444  (*activityneginf)--;
1445 
1446  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1447  if( SCIPisInfinity(scip, newbound) )
1448  (*activityposinf)++;
1449  /* if the contribution of this variable is too large, increase the counter for huge values */
1450  else if( SCIPisHugeValue(scip, val * newbound) )
1451  {
1452  (*activityposhuge)++;
1453  }
1454  else if( SCIPisHugeValue(scip, -val * newbound) )
1455  {
1456  (*activityneghuge)++;
1457  }
1458  /* "normal case": just add the contribution to the activity */
1459  else
1460  delta = val * newbound;
1461  }
1462  }
1463  /* old contribution was too large and positive */
1464  else if( SCIPisHugeValue(scip, val * oldbound) )
1465  {
1466  assert((*activityposhuge) >= 1);
1467 
1468  /* decrease the counter for huge positive contributions; it might be increased again later,
1469  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1470  */
1471  (*activityposhuge)--;
1472 
1473  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1474  if( SCIPisInfinity(scip, newbound) )
1475  (*activityposinf)++;
1476  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1477  else if( SCIPisInfinity(scip, -newbound) )
1478  (*activityneginf)++;
1479  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1480  else if( SCIPisHugeValue(scip, val * newbound) )
1481  {
1482  (*activityposhuge)++;
1483  }
1484  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1485  else if( SCIPisHugeValue(scip, -val * newbound) )
1486  {
1487  (*activityneghuge)++;
1488  }
1489  /* "normal case": just add the contribution to the activity */
1490  else
1491  delta = val * newbound;
1492  }
1493  /* old contribution was too large and negative */
1494  else if( SCIPisHugeValue(scip, -val * oldbound) )
1495  {
1496  assert((*activityneghuge) >= 1);
1497 
1498  /* decrease the counter for huge negative contributions; it might be increased again later,
1499  * but checking here that the bound is not huge again would not handle a change from a huge to an infinite bound
1500  */
1501  (*activityneghuge)--;
1502 
1503  /* if the bound changed to +infinity, increase the counter for positive infinite contributions */
1504  if( SCIPisInfinity(scip, newbound) )
1505  (*activityposinf)++;
1506  /* if the bound changed to -infinity, increase the counter for negative infinite contributions */
1507  else if( SCIPisInfinity(scip, -newbound) )
1508  (*activityneginf)++;
1509  /* if the contribution of this variable is too large and positive, increase the corresponding counter */
1510  else if( SCIPisHugeValue(scip, val * newbound) )
1511  {
1512  (*activityposhuge)++;
1513  }
1514  /* if the contribution of this variable is too large and negative, increase the corresponding counter */
1515  else if( SCIPisHugeValue(scip, -val * newbound) )
1516  {
1517  (*activityneghuge)++;
1518  }
1519  /* "normal case": just add the contribution to the activity */
1520  else
1521  delta = val * newbound;
1522  }
1523  /* old bound was finite and not too large */
1524  else
1525  {
1526  /* if the new bound is +infinity, the old contribution has to be subtracted
1527  * and the counter for positive infinite contributions has to be increased
1528  */
1529  if( SCIPisInfinity(scip, newbound) )
1530  {
1531  (*activityposinf)++;
1532  delta = -val * oldbound;
1533  }
1534  /* if the new bound is -infinity, the old contribution has to be subtracted
1535  * and the counter for negative infinite contributions has to be increased
1536  */
1537  else if( SCIPisInfinity(scip, -newbound) )
1538  {
1539  (*activityneginf)++;
1540  delta = -val * oldbound;
1541  }
1542  /* if the contribution of this variable is too large, increase the counter for huge values */
1543  else if( SCIPisHugeValue(scip, val * newbound) )
1544  {
1545  (*activityposhuge)++;
1546  delta = -val * oldbound;
1547  }
1548  else if( SCIPisHugeValue(scip, -val * newbound) )
1549  {
1550  (*activityneghuge)++;
1551  delta = -val * oldbound;
1552  }
1553  /* "normal case": just update the activity */
1554  else
1555  delta = val * (newbound - oldbound);
1556  }
1557 
1558  /* update the activity, if the current value is valid and there was a change in the finite part */
1559  if( validact && (delta != 0.0) )
1560  {
1561  /* if the absolute value of the activity is increased, this is regarded as reliable,
1562  * otherwise, we check whether we can still trust the updated value
1563  */
1564  (*activity) = (*activity) + delta;
1565  assert(!SCIPisInfinity(scip, -(*activity)) && !SCIPisInfinity(scip, *activity));
1566 
1567  if( REALABS((*lastactivity)) < REALABS(*activity) )
1568  {
1569  (*lastactivity) = (*activity);
1570  }
1571  else
1572  {
1573  if( checkreliability && SCIPisUpdateUnreliable(scip, (*activity), (*lastactivity)) )
1574  {
1575  SCIPdebugMessage("%s activity of linear constraint unreliable after update: %16.9g\n",
1576  (global ? "global " : ""), (*activity));
1577 
1578  /* mark the activity that was just changed and is not reliable anymore to be invalid */
1579  if( global )
1580  {
1581  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1582  consdata->validglbminact = FALSE;
1583  else
1584  consdata->validglbmaxact = FALSE;
1585  }
1586  else
1587  {
1588  if( (boundtype == SCIP_BOUNDTYPE_LOWER) == (val > 0.0) )
1589  consdata->validminact = FALSE;
1590  else
1591  consdata->validmaxact = FALSE;
1592  }
1593  }
1594  }
1595  }
1596 }
1597 
1598 /** updates minimum and maximum activity for a change in lower bound */
1599 static
1601  SCIP* scip, /**< SCIP data structure */
1602  SCIP_CONSDATA* consdata, /**< linear constraint data */
1603  SCIP_VAR* var, /**< variable that has been changed */
1604  SCIP_Real oldlb, /**< old lower bound of variable */
1605  SCIP_Real newlb, /**< new lower bound of variable */
1606  SCIP_Real val, /**< coefficient of constraint entry */
1607  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1608  )
1609 {
1610  assert(scip != NULL);
1611  assert(consdata != NULL);
1612  assert(var != NULL);
1613 
1614  if( consdata->validactivities )
1615  {
1616  consdataUpdateActivities(scip, consdata, var, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, FALSE, checkreliability);
1617 
1618  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1619  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1620  }
1621 }
1622 
1623 /** updates minimum and maximum activity for a change in upper bound */
1624 static
1626  SCIP* scip, /**< SCIP data structure */
1627  SCIP_CONSDATA* consdata, /**< linear constraint data */
1628  SCIP_VAR* var, /**< variable that has been changed */
1629  SCIP_Real oldub, /**< old upper bound of variable */
1630  SCIP_Real newub, /**< new upper bound of variable */
1631  SCIP_Real val, /**< coefficient of constraint entry */
1632  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1633  )
1634 {
1635  assert(scip != NULL);
1636  assert(consdata != NULL);
1637  assert(var != NULL);
1638 
1639  if( consdata->validactivities )
1640  {
1641  consdataUpdateActivities(scip, consdata, var, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, FALSE, checkreliability);
1642 
1643  assert(!SCIPisInfinity(scip, -consdata->minactivity) && !SCIPisInfinity(scip, consdata->minactivity));
1644  assert(!SCIPisInfinity(scip, -consdata->maxactivity) && !SCIPisInfinity(scip, consdata->maxactivity));
1645  }
1646 }
1647 
1648 /** updates minimum and maximum global activity for a change in the global lower bound */
1649 static
1651  SCIP* scip, /**< SCIP data structure */
1652  SCIP_CONSDATA* consdata, /**< linear constraint data */
1653  SCIP_Real oldlb, /**< old lower bound of variable */
1654  SCIP_Real newlb, /**< new lower bound of variable */
1655  SCIP_Real val, /**< coefficient of constraint entry */
1656  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1657  )
1658 {
1659  assert(scip != NULL);
1660  assert(consdata != NULL);
1661 
1662  if( consdata->validactivities )
1663  {
1664  consdataUpdateActivities(scip, consdata, NULL, oldlb, newlb, val, SCIP_BOUNDTYPE_LOWER, TRUE, checkreliability);
1665 
1666  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
1667  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
1668  }
1669 }
1670 
1671 /** updates minimum and maximum global activity for a change in global upper bound */
1672 static
1674  SCIP* scip, /**< SCIP data structure */
1675  SCIP_CONSDATA* consdata, /**< linear constraint data */
1676  SCIP_Real oldub, /**< old upper bound of variable */
1677  SCIP_Real newub, /**< new upper bound of variable */
1678  SCIP_Real val, /**< coefficient of constraint entry */
1679  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1680  )
1681 {
1682  assert(scip != NULL);
1683  assert(consdata != NULL);
1684 
1685  if( consdata->validactivities )
1686  {
1687  consdataUpdateActivities(scip, consdata, NULL, oldub, newub, val, SCIP_BOUNDTYPE_UPPER, TRUE, checkreliability);
1688 
1689  assert(!SCIPisInfinity(scip, -consdata->glbminactivity) && !SCIPisInfinity(scip, consdata->glbminactivity));
1690  assert(!SCIPisInfinity(scip, -consdata->glbmaxactivity) && !SCIPisInfinity(scip, consdata->glbmaxactivity));
1691  }
1692 }
1693 
1694 /** updates minimum and maximum activity and maximum absolute value for coefficient addition */
1695 static
1697  SCIP* scip, /**< SCIP data structure */
1698  SCIP_CONSDATA* consdata, /**< linear constraint data */
1699  SCIP_VAR* var, /**< variable of constraint entry */
1700  SCIP_Real val, /**< coefficient of constraint entry */
1701  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1702  )
1703 {
1704  assert(scip != NULL);
1705  assert(consdata != NULL);
1706  assert(var != NULL);
1707 
1708  /* update maximum absolute value */
1709  if( consdata->validmaxabsval )
1710  {
1711  SCIP_Real absval;
1712 
1713  assert(consdata->maxabsval < SCIP_INVALID);
1714 
1715  absval = REALABS(val);
1716  consdata->maxabsval = MAX(consdata->maxabsval, absval);
1717  }
1718 
1719  /* update minimal and maximal activity */
1720  if( consdata->validactivities )
1721  {
1722  assert(consdata->minactivity < SCIP_INVALID);
1723  assert(consdata->maxactivity < SCIP_INVALID);
1724  assert(consdata->glbminactivity < SCIP_INVALID);
1725  assert(consdata->glbmaxactivity < SCIP_INVALID);
1726 
1727  consdataUpdateActivitiesLb(scip, consdata, var, 0.0, SCIPvarGetLbLocal(var), val, checkreliability);
1728  consdataUpdateActivitiesUb(scip, consdata, var, 0.0, SCIPvarGetUbLocal(var), val, checkreliability);
1729  consdataUpdateActivitiesGlbLb(scip, consdata, 0.0, SCIPvarGetLbGlobal(var), val, checkreliability);
1730  consdataUpdateActivitiesGlbUb(scip, consdata, 0.0, SCIPvarGetUbGlobal(var), val, checkreliability);
1731  }
1732 }
1733 
1734 /** updates minimum and maximum activity for coefficient deletion, invalidates maximum absolute value if necessary */
1735 static
1737  SCIP* scip, /**< SCIP data structure */
1738  SCIP_CONSDATA* consdata, /**< linear constraint data */
1739  SCIP_VAR* var, /**< variable of constraint entry */
1740  SCIP_Real val, /**< coefficient of constraint entry */
1741  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1742  )
1743 {
1744  assert(scip != NULL);
1745  assert(consdata != NULL);
1746  assert(var != NULL);
1747 
1748  /* invalidate maximum absolute value, if this coefficient was the maximum */
1749  if( consdata->validmaxabsval )
1750  {
1751  SCIP_Real absval;
1752 
1753  absval = REALABS(val);
1754 
1755  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
1756  {
1757  consdata->validmaxabsval = FALSE;
1758  consdata->maxabsval = SCIP_INVALID;
1759  }
1760  }
1761 
1762  /* update minimal and maximal activity */
1763  if( consdata->validactivities )
1764  {
1765  assert(consdata->minactivity < SCIP_INVALID);
1766  assert(consdata->maxactivity < SCIP_INVALID);
1767  assert(consdata->glbminactivity < SCIP_INVALID);
1768  assert(consdata->glbmaxactivity < SCIP_INVALID);
1769 
1770  consdataUpdateActivitiesLb(scip, consdata, var, SCIPvarGetLbLocal(var), 0.0, val, checkreliability);
1771  consdataUpdateActivitiesUb(scip, consdata, var, SCIPvarGetUbLocal(var), 0.0, val, checkreliability);
1772  consdataUpdateActivitiesGlbLb(scip, consdata, SCIPvarGetLbGlobal(var), 0.0, val, checkreliability);
1773  consdataUpdateActivitiesGlbUb(scip, consdata, SCIPvarGetUbGlobal(var), 0.0, val, checkreliability);
1774  }
1775 }
1776 
1777 /** updates minimum and maximum activity for coefficient change, invalidates maximum absolute value if necessary */
1778 static
1780  SCIP* scip, /**< SCIP data structure */
1781  SCIP_CONSDATA* consdata, /**< linear constraint data */
1782  SCIP_VAR* var, /**< variable of constraint entry */
1783  SCIP_Real oldval, /**< old coefficient of constraint entry */
1784  SCIP_Real newval, /**< new coefficient of constraint entry */
1785  SCIP_Bool checkreliability /**< should the reliability of the recalculated activity be checked? */
1786  )
1787 {
1788  assert(scip != NULL);
1789  assert(consdata != NULL);
1790  assert(var != NULL);
1791 
1792  /* old zero coefficients should be handled by consdataUpdateAddCoef() */
1793  assert(!SCIPisZero(scip, oldval));
1794 
1795  /* new zero coefficients should be handled by consdataUpdateDelCoef() */
1796  assert(!SCIPisZero(scip, newval));
1797 
1798  /* update maximum absolute value */
1799  if( consdata->validmaxabsval )
1800  {
1801  SCIP_Real absval;
1802 
1803  absval = REALABS(newval);
1804 
1805  if( SCIPisGE(scip, absval, consdata->maxabsval) )
1806  consdata->maxabsval = absval;
1807  else
1808  {
1809  absval = REALABS(oldval);
1810 
1811  /* invalidate maximum absolute value */
1812  if( SCIPisEQ(scip, absval, consdata->maxabsval) )
1813  {
1814  consdata->validmaxabsval = FALSE;
1815  consdata->maxabsval = SCIP_INVALID;
1816  }
1817  }
1818  }
1819 
1820  /* @todo do something more clever here, e.g. if oldval * newval >= 0, do the update directly */
1821  consdataUpdateDelCoef(scip, consdata, var, oldval, checkreliability);
1822  consdataUpdateAddCoef(scip, consdata, var, newval, checkreliability);
1823 }
1824 
1825 /** calculates maximum absolute value of coefficients */
1826 static
1828  SCIP_CONSDATA* consdata /**< linear constraint data */
1829  )
1830 {
1831  SCIP_Real absval;
1832  int i;
1833 
1834  assert(consdata != NULL);
1835  assert(!consdata->validmaxabsval);
1836  assert(consdata->maxabsval >= SCIP_INVALID);
1837 
1838  consdata->validmaxabsval = TRUE;
1839  consdata->maxabsval = 0.0;
1840  for( i = 0; i < consdata->nvars; ++i )
1841  {
1842  absval = consdata->vals[i];
1843  absval = REALABS(absval);
1844  consdata->maxabsval = MAX(consdata->maxabsval, absval);
1845  }
1846 }
1847 
1848 /** returns the maximum absolute value of all coefficients in the constraint */
1849 static
1851  SCIP_CONSDATA* consdata /**< linear constraint data */
1852  )
1853 {
1854  assert(consdata != NULL);
1855 
1856  if( !consdata->validmaxabsval )
1857  consdataCalcMaxAbsval(consdata);
1858  assert(consdata->validmaxabsval);
1859  assert(consdata->maxabsval < SCIP_INVALID);
1860 
1861  return consdata->maxabsval;
1862 }
1863 
1864 /** calculates minimum and maximum local and global activity for constraint from scratch;
1865  * additionally recalculates maximum absolute value of coefficients
1866  */
1867 static
1869  SCIP* scip, /**< SCIP data structure */
1870  SCIP_CONSDATA* consdata /**< linear constraint data */
1871  )
1872 {
1873  int i;
1874 
1875  assert(scip != NULL);
1876  assert(consdata != NULL);
1877  assert(!consdata->validactivities);
1878  assert(consdata->minactivity >= SCIP_INVALID || consdata->validminact);
1879  assert(consdata->maxactivity >= SCIP_INVALID || consdata->validmaxact);
1880  assert(consdata->glbminactivity >= SCIP_INVALID || consdata->validglbminact);
1881  assert(consdata->glbmaxactivity >= SCIP_INVALID || consdata->validglbmaxact);
1882 
1883  consdata->validmaxabsval = TRUE;
1884  consdata->validactivities = TRUE;
1885  consdata->validminact = TRUE;
1886  consdata->validmaxact = TRUE;
1887  consdata->validglbminact = TRUE;
1888  consdata->validglbmaxact = TRUE;
1889  consdata->maxabsval = 0.0;
1890  consdata->minactivity = 0.0;
1891  consdata->maxactivity = 0.0;
1892  consdata->lastminactivity = 0.0;
1893  consdata->lastmaxactivity = 0.0;
1894  consdata->minactivityneginf = 0;
1895  consdata->minactivityposinf = 0;
1896  consdata->maxactivityneginf = 0;
1897  consdata->maxactivityposinf = 0;
1898  consdata->minactivityneghuge = 0;
1899  consdata->minactivityposhuge = 0;
1900  consdata->maxactivityneghuge = 0;
1901  consdata->maxactivityposhuge = 0;
1902  consdata->glbminactivity = 0.0;
1903  consdata->glbmaxactivity = 0.0;
1904  consdata->lastglbminactivity = 0.0;
1905  consdata->lastglbmaxactivity = 0.0;
1906  consdata->glbminactivityneginf = 0;
1907  consdata->glbminactivityposinf = 0;
1908  consdata->glbmaxactivityneginf = 0;
1909  consdata->glbmaxactivityposinf = 0;
1910  consdata->glbminactivityneghuge = 0;
1911  consdata->glbminactivityposhuge = 0;
1912  consdata->glbmaxactivityneghuge = 0;
1913  consdata->glbmaxactivityposhuge = 0;
1914 
1915  for( i = 0; i < consdata->nvars; ++i )
1916  consdataUpdateAddCoef(scip, consdata, consdata->vars[i], consdata->vals[i], FALSE);
1917 
1918  consdata->lastminactivity = consdata->minactivity;
1919  consdata->lastmaxactivity = consdata->maxactivity;
1920  consdata->lastglbminactivity = consdata->glbminactivity;
1921  consdata->lastglbmaxactivity = consdata->glbmaxactivity;
1922 }
1923 
1924 /** gets minimal activity for constraint and given values of counters for infinite and huge contributions
1925  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
1926  */
1927 static
1929  SCIP* scip, /**< SCIP data structure */
1930  SCIP_CONSDATA* consdata, /**< linear constraint */
1931  int posinf, /**< number of coefficients contributing pos. infinite value */
1932  int neginf, /**< number of coefficients contributing neg. infinite value */
1933  int poshuge, /**< number of coefficients contributing huge pos. value */
1934  int neghuge, /**< number of coefficients contributing huge neg. value */
1935  SCIP_Real delta, /**< value to subtract from stored minactivity
1936  * (contribution of the variable set to zero when getting residual activity) */
1937  SCIP_Bool global, /**< should the global or local minimal activity be returned? */
1938  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
1939  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
1940  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
1941  * i.e. is <= the exact minactivity (in case of huge contributing values) */
1942  SCIP_Bool* issettoinfinity /**< pointer to store whether minactivity was set to infinity or calculated */
1943  )
1944 {
1945  assert(scip != NULL);
1946  assert(consdata != NULL);
1947  assert(posinf >= 0);
1948  assert(neginf >= 0);
1949  assert(poshuge >= 0);
1950  assert(neghuge >= 0);
1951  assert(minactivity != NULL);
1952  assert(isrelax != NULL);
1953  assert(issettoinfinity != NULL);
1954 
1955  /* if we have pos. infinite contributions, the minactivity is +infty */
1956  if( posinf > 0 )
1957  {
1958  *minactivity = SCIPinfinity(scip);
1959  *issettoinfinity = TRUE;
1960  *isrelax = FALSE;
1961  }
1962  /* if we have neg. (and no pos.) infinite contributions, the minactivity is -infty */
1963  else if( neginf > 0 )
1964  {
1965  *minactivity = -SCIPinfinity(scip);
1966  *issettoinfinity = TRUE;
1967  *isrelax = FALSE;
1968  }
1969  /* if we have neg. huge contributions, we only know that -infty is a relaxation of the minactivity */
1970  else if( neghuge > 0 )
1971  {
1972  *minactivity = -SCIPinfinity(scip);
1973  *issettoinfinity = TRUE;
1974  *isrelax = TRUE;
1975  }
1976  /* we do not need a good relaxation and we have positve huge contributions, so we just return -infty as activity */
1977  else if( !goodrelax && poshuge > 0 )
1978  {
1979  *minactivity = -SCIPinfinity(scip);
1980  *issettoinfinity = TRUE;
1981  *isrelax = TRUE;
1982  }
1983  else
1984  {
1985  SCIP_Real tmpactivity;
1986 
1987  /* recompute minactivity if it is not valid */
1988  if( global )
1989  {
1990  if( !consdata->validglbminact )
1991  consdataRecomputeGlbMinactivity(scip, consdata);
1992  assert(consdata->validglbminact);
1993 
1994  tmpactivity = consdata->glbminactivity;
1995  }
1996  else
1997  {
1998  if( !consdata->validminact )
1999  consdataRecomputeMinactivity(scip, consdata);
2000  assert(consdata->validminact);
2001 
2002  tmpactivity = consdata->minactivity;
2003  }
2004 
2005  /* we have no infinite and no neg. huge contributions, but pos. huge contributions;
2006  * a feasible relaxation of the minactivity is the number of positive huge contributions
2007  * times the minimum value counting as "huge" plus finite (and non-huge) part of minactivity - delta
2008  */
2009  if( poshuge > 0 )
2010  {
2011  *minactivity = 1.0 * poshuge * SCIPgetHugeValue(scip) + (tmpactivity - delta);
2012  *issettoinfinity = FALSE;
2013  *isrelax = TRUE;
2014  }
2015  /* all counters are zero, so the minactivity is just stored and we subtract the delta */
2016  else
2017  {
2018  *minactivity = tmpactivity - delta;
2019  *issettoinfinity = FALSE;
2020  *isrelax = FALSE;
2021  }
2022  }
2023 }
2024 
2025 /** gets maximal activity for constraint and given values of counters for infinite and huge contributions
2026  * and (if needed) delta to subtract from stored finite part of activity in case of a residual activity
2027  */
2028 static
2030  SCIP* scip, /**< SCIP data structure */
2031  SCIP_CONSDATA* consdata, /**< linear constraint */
2032  int posinf, /**< number of coefficients contributing pos. infinite value */
2033  int neginf, /**< number of coefficients contributing neg. infinite value */
2034  int poshuge, /**< number of coefficients contributing huge pos. value */
2035  int neghuge, /**< number of coefficients contributing huge neg. value */
2036  SCIP_Real delta, /**< value to subtract from stored maxactivity
2037  * (contribution of the variable set to zero when getting residual activity) */
2038  SCIP_Bool global, /**< should the global or local maximal activity be returned? */
2039  SCIP_Bool goodrelax, /**< should a good relaxation be computed or are relaxed acticities ignored, anyway? */
2040  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2041  SCIP_Bool* isrelax, /**< pointer to store whether the activity is a relaxation,
2042  * i.e. is >= the exact maxactivity (in case of huge contributing values) */
2043  SCIP_Bool* issettoinfinity /**< pointer to store whether maxactivity was set to infinity or calculated */
2044  )
2045 {
2046  assert(scip != NULL);
2047  assert(consdata != NULL);
2048  assert(posinf >= 0);
2049  assert(neginf >= 0);
2050  assert(poshuge >= 0);
2051  assert(neghuge >= 0);
2052  assert(maxactivity != NULL);
2053  assert(isrelax != NULL);
2054  assert(issettoinfinity != NULL);
2055 
2056  /* if we have neg. infinite contributions, the maxactivity is -infty */
2057  if( neginf > 0 )
2058  {
2059  *maxactivity = -SCIPinfinity(scip);
2060  *issettoinfinity = TRUE;
2061  *isrelax = FALSE;
2062  }
2063  /* if we have pos. (and no neg.) infinite contributions, the maxactivity is +infty */
2064  else if( posinf > 0 )
2065  {
2066  *maxactivity = SCIPinfinity(scip);
2067  *issettoinfinity = TRUE;
2068  *isrelax = FALSE;
2069  }
2070  /* if we have pos. huge contributions, we only know that +infty is a relaxation of the maxactivity */
2071  else if( poshuge > 0 )
2072  {
2073  *maxactivity = SCIPinfinity(scip);
2074  *issettoinfinity = TRUE;
2075  *isrelax = TRUE;
2076  }
2077  /* we do not need a good relaxation and we have positve huge contributions, so we just return +infty as activity */
2078  else if( !goodrelax && neghuge > 0 )
2079  {
2080  *maxactivity = SCIPinfinity(scip);
2081  *issettoinfinity = TRUE;
2082  *isrelax = TRUE;
2083  }
2084  else
2085  {
2086  SCIP_Real tmpactivity;
2087 
2088  /* recompute maxactivity if it is not valid */
2089  if( global )
2090  {
2091  if( !consdata->validglbmaxact )
2092  consdataRecomputeGlbMaxactivity(scip, consdata);
2093  assert(consdata->validglbmaxact);
2094 
2095  tmpactivity = consdata->glbmaxactivity;
2096  }
2097  else
2098  {
2099  if( !consdata->validmaxact )
2100  consdataRecomputeMaxactivity(scip, consdata);
2101  assert(consdata->validmaxact);
2102 
2103  tmpactivity = consdata->maxactivity;
2104  }
2105 
2106  /* we have no infinite, and no pos. huge contributions, but neg. huge contributions;
2107  * a feasible relaxation of the maxactivity is minus the number of negative huge contributions
2108  * times the minimum value counting as "huge" plus the finite (and non-huge) part of maxactivity minus delta
2109  */
2110  if( neghuge > 0 )
2111  {
2112  *maxactivity = -1.0 * neghuge * SCIPgetHugeValue(scip) + tmpactivity - delta;
2113  *issettoinfinity = FALSE;
2114  *isrelax = TRUE;
2115  }
2116  /* all counters are zero, so the maxactivity is just stored and we subtract the delta */
2117  else
2118  {
2119  *maxactivity = tmpactivity - delta;
2120  *issettoinfinity = FALSE;
2121  *isrelax = FALSE;
2122  }
2123  }
2124 }
2125 
2126 /** gets activity bounds for constraint */
2127 static
2129  SCIP* scip, /**< SCIP data structure */
2130  SCIP_CONSDATA* consdata, /**< linear constraint */
2131  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2132  * relaxed acticities ignored, anyway? */
2133  SCIP_Real* minactivity, /**< pointer to store the minimal activity */
2134  SCIP_Real* maxactivity, /**< pointer to store the maximal activity */
2135  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2136  * i.e. <= the exact minactivity (in case of huge contributions),
2137  * or equal to the exact minimal activity */
2138  SCIP_Bool* maxisrelax /**< pointer to store whether the returned maxactivity is just a relaxation,
2139  * i.e. >= the exact maxactivity (in case of huge contributions),
2140  * or equal to the exact maximal activity */
2141  )
2142 {
2143  SCIP_Bool issettoinfinity;
2144 
2145  assert(scip != NULL);
2146  assert(consdata != NULL);
2147  assert(minactivity != NULL);
2148  assert(maxactivity != NULL);
2149 
2150  if( !consdata->validactivities )
2151  {
2152  consdataCalcActivities(scip, consdata);
2153  assert(consdata->validminact);
2154  assert(consdata->validmaxact);
2155  }
2156  assert(consdata->minactivity < SCIP_INVALID);
2157  assert(consdata->maxactivity < SCIP_INVALID);
2158  assert(consdata->minactivityneginf >= 0);
2159  assert(consdata->minactivityposinf >= 0);
2160  assert(consdata->maxactivityneginf >= 0);
2161  assert(consdata->maxactivityposinf >= 0);
2162 
2163  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2164  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2165  minactivity, minisrelax, &issettoinfinity);
2166 
2167  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2168  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2169  maxactivity, maxisrelax, &issettoinfinity);
2170 }
2171 
2172 /** calculates activity bounds for constraint after setting variable to zero */
2173 static
2175  SCIP* scip, /**< SCIP data structure */
2176  SCIP_CONSDATA* consdata, /**< linear constraint */
2177  SCIP_VAR* cancelvar, /**< variable to calculate activity residual for */
2178  SCIP_Real* resactivity, /**< pointer to store the residual activity */
2179  SCIP_Bool isminresact, /**< should minimal or maximal residual activity be calculated? */
2180  SCIP_Bool useglobalbounds /**< should global or local bounds be used? */
2181  )
2182 {
2183  SCIP_VAR* var;
2184  SCIP_Real val;
2185  SCIP_Real lb;
2186  SCIP_Real ub;
2187  int v;
2188 
2189  assert(scip != NULL);
2190  assert(consdata != NULL);
2191  assert(cancelvar != NULL);
2192  assert(resactivity != NULL);
2193 
2194  *resactivity = 0.0;
2195 
2196  for( v = 0; v < consdata->nvars; ++v )
2197  {
2198  var = consdata->vars[v];
2199  assert(var != NULL);
2200  if( var == cancelvar )
2201  continue;
2202 
2203  val = consdata->vals[v];
2204 
2205  if( useglobalbounds )
2206  {
2207  lb = SCIPvarGetLbGlobal(var);
2208  ub = SCIPvarGetUbGlobal(var);
2209  }
2210  else
2211  {
2212  lb = SCIPvarGetLbLocal(var);
2213  ub = SCIPvarGetUbLocal(var);
2214  }
2215 
2216  assert(!SCIPisZero(scip, val));
2217  assert(SCIPisLE(scip, lb, ub));
2218 
2219  if( val > 0.0 )
2220  {
2221  if( isminresact )
2222  {
2223  assert(!SCIPisInfinity(scip, -lb));
2224  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2225  *resactivity += val*lb;
2226  }
2227  else
2228  {
2229  assert(!SCIPisInfinity(scip, ub));
2230  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2231  *resactivity += val*ub;
2232  }
2233  }
2234  else
2235  {
2236  if( isminresact)
2237  {
2238  assert(!SCIPisInfinity(scip, ub));
2239  assert(!SCIPisHugeValue(scip, REALABS(val*ub)));
2240  *resactivity += val*ub;
2241  }
2242  else
2243  {
2244  assert(!SCIPisInfinity(scip, -lb));
2245  assert(!SCIPisHugeValue(scip, REALABS(val*lb)));
2246  *resactivity += val*lb;
2247  }
2248  }
2249  }
2250  assert(!SCIPisInfinity(scip, *resactivity) && !SCIPisInfinity(scip, -(*resactivity)));
2251 }
2252 
2253 /** gets activity bounds for constraint after setting variable to zero */
2254 static
2256  SCIP* scip, /**< SCIP data structure */
2257  SCIP_CONSDATA* consdata, /**< linear constraint */
2258  SCIP_VAR* var, /**< variable to calculate activity residual for */
2259  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2260  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2261  * relaxed acticities ignored, anyway? */
2262  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity */
2263  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity */
2264  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2265  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2266  * contributions), or equal to the exact residual minactivity */
2267  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2268  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2269  * contributions), or equal to the exact residual minactivity */
2270  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2271  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2272  )
2273 {
2274  SCIP_Real minactbound;
2275  SCIP_Real maxactbound;
2276  SCIP_Real absval;
2277 
2278  assert(scip != NULL);
2279  assert(consdata != NULL);
2280  assert(var != NULL);
2281  assert(minresactivity != NULL);
2282  assert(maxresactivity != NULL);
2283  assert(minisrelax != NULL);
2284  assert(maxisrelax != NULL);
2285  assert(isminsettoinfinity != NULL);
2286  assert(ismaxsettoinfinity != NULL);
2287 
2288  /* get activity bounds of linear constraint */
2289  if( !consdata->validactivities )
2290  {
2291  consdataCalcActivities(scip, consdata);
2292  assert(consdata->validminact);
2293  assert(consdata->validmaxact);
2294  }
2295  assert(consdata->minactivity < SCIP_INVALID);
2296  assert(consdata->maxactivity < SCIP_INVALID);
2297  assert(consdata->minactivityneginf >= 0);
2298  assert(consdata->minactivityposinf >= 0);
2299  assert(consdata->maxactivityneginf >= 0);
2300  assert(consdata->maxactivityposinf >= 0);
2301  assert(consdata->minactivityneghuge >= 0);
2302  assert(consdata->minactivityposhuge >= 0);
2303  assert(consdata->maxactivityneghuge >= 0);
2304  assert(consdata->maxactivityposhuge >= 0);
2305 
2306  if( val > 0.0 )
2307  {
2308  minactbound = SCIPvarGetLbLocal(var);
2309  maxactbound = SCIPvarGetUbLocal(var);
2310  absval = val;
2311  }
2312  else
2313  {
2314  minactbound = -SCIPvarGetUbLocal(var);
2315  maxactbound = -SCIPvarGetLbLocal(var);
2316  absval = -val;
2317  }
2318 
2319  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2320  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2321  */
2322  if( SCIPisInfinity(scip, minactbound) )
2323  {
2324  assert(consdata->minactivityposinf >= 1);
2325 
2326  getMinActivity(scip, consdata, consdata->minactivityposinf - 1, consdata->minactivityneginf,
2327  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2328  minresactivity, minisrelax, isminsettoinfinity);
2329  }
2330  else if( SCIPisInfinity(scip, -minactbound) )
2331  {
2332  assert(consdata->minactivityneginf >= 1);
2333 
2334  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf - 1,
2335  consdata->minactivityposhuge, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2336  minresactivity, minisrelax, isminsettoinfinity);
2337  }
2338  else if( SCIPisHugeValue(scip, minactbound * absval) )
2339  {
2340  assert(consdata->minactivityposhuge >= 1);
2341 
2342  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2343  consdata->minactivityposhuge - 1, consdata->minactivityneghuge, 0.0, FALSE, goodrelax,
2344  minresactivity, minisrelax, isminsettoinfinity);
2345  }
2346  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2347  {
2348  assert(consdata->minactivityneghuge >= 1);
2349 
2350  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2351  consdata->minactivityposhuge, consdata->minactivityneghuge - 1, 0.0, FALSE, goodrelax,
2352  minresactivity, minisrelax, isminsettoinfinity);
2353  }
2354  else
2355  {
2356  getMinActivity(scip, consdata, consdata->minactivityposinf, consdata->minactivityneginf,
2357  consdata->minactivityposhuge, consdata->minactivityneghuge, absval * minactbound, FALSE, goodrelax,
2358  minresactivity, minisrelax, isminsettoinfinity);
2359  }
2360 
2361  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2362  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2363  */
2364  if( SCIPisInfinity(scip, -maxactbound) )
2365  {
2366  assert(consdata->maxactivityneginf >= 1);
2367 
2368  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf - 1,
2369  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2370  maxresactivity, maxisrelax, ismaxsettoinfinity);
2371  }
2372  else if( SCIPisInfinity(scip, maxactbound) )
2373  {
2374  assert(consdata->maxactivityposinf >= 1);
2375 
2376  getMaxActivity(scip, consdata, consdata->maxactivityposinf - 1, consdata->maxactivityneginf,
2377  consdata->maxactivityposhuge, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2378  maxresactivity, maxisrelax, ismaxsettoinfinity);
2379  }
2380  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2381  {
2382  assert(consdata->maxactivityposhuge >= 1);
2383 
2384  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2385  consdata->maxactivityposhuge - 1, consdata->maxactivityneghuge, 0.0, FALSE, goodrelax,
2386  maxresactivity, maxisrelax, ismaxsettoinfinity);
2387  }
2388  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2389  {
2390  assert(consdata->maxactivityneghuge >= 1);
2391 
2392  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2393  consdata->maxactivityposhuge, consdata->maxactivityneghuge - 1, 0.0, FALSE, goodrelax,
2394  maxresactivity, maxisrelax, ismaxsettoinfinity);
2395  }
2396  else
2397  {
2398  getMaxActivity(scip, consdata, consdata->maxactivityposinf, consdata->maxactivityneginf,
2399  consdata->maxactivityposhuge, consdata->maxactivityneghuge, absval * maxactbound, FALSE, goodrelax,
2400  maxresactivity, maxisrelax, ismaxsettoinfinity);
2401  }
2402 }
2403 
2404 /** gets global activity bounds for constraint */
2405 static
2407  SCIP* scip, /**< SCIP data structure */
2408  SCIP_CONSDATA* consdata, /**< linear constraint */
2409  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2410  * relaxed acticities ignored, anyway? */
2411  SCIP_Real* glbminactivity, /**< pointer to store the minimal activity, or NULL, if not needed */
2412  SCIP_Real* glbmaxactivity, /**< pointer to store the maximal activity, or NULL, if not needed */
2413  SCIP_Bool* minisrelax, /**< pointer to store whether the returned minactivity is just a relaxation,
2414  * i.e. <= the exact minactivity (in case of huge contributions),
2415  * or equal to the exact minimal activity */
2416  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned maxactivity is just a relaxation,
2417  * i.e. >= the exact maxactivity (in case of huge contributions),
2418  * or equal to the exact maximal activity */
2419  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2420  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2421  )
2422 {
2423  assert(scip != NULL);
2424  assert(consdata != NULL);
2425  assert((glbminactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL)
2426  || (glbmaxactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2427 
2428  if( !consdata->validactivities )
2429  {
2430  consdataCalcActivities(scip, consdata);
2431  assert(consdata->validglbminact);
2432  assert(consdata->validglbmaxact);
2433  }
2434  assert(consdata->glbminactivity < SCIP_INVALID);
2435  assert(consdata->glbmaxactivity < SCIP_INVALID);
2436  assert(consdata->glbminactivityneginf >= 0);
2437  assert(consdata->glbminactivityposinf >= 0);
2438  assert(consdata->glbmaxactivityneginf >= 0);
2439  assert(consdata->glbmaxactivityposinf >= 0);
2440  assert(consdata->glbminactivityneghuge >= 0);
2441  assert(consdata->glbminactivityposhuge >= 0);
2442  assert(consdata->glbmaxactivityneghuge >= 0);
2443  assert(consdata->glbmaxactivityposhuge >= 0);
2444 
2445  if( glbminactivity != NULL )
2446  {
2447  assert(isminsettoinfinity != NULL);
2448  assert(minisrelax != NULL);
2449 
2450  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2451  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2452  glbminactivity, minisrelax, isminsettoinfinity);
2453  }
2454 
2455  if( glbmaxactivity != NULL )
2456  {
2457  assert(ismaxsettoinfinity != NULL);
2458  assert(maxisrelax != NULL);
2459 
2460  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2461  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2462  glbmaxactivity, maxisrelax, ismaxsettoinfinity);
2463  }
2464 }
2465 
2466 /** gets global activity bounds for constraint after setting variable to zero */
2467 static
2469  SCIP* scip, /**< SCIP data structure */
2470  SCIP_CONSDATA* consdata, /**< linear constraint */
2471  SCIP_VAR* var, /**< variable to calculate activity residual for */
2472  SCIP_Real val, /**< coefficient value of variable in linear constraint */
2473  SCIP_Bool goodrelax, /**< if we have huge contributions, do we need a good relaxation or are
2474  * relaxed acticities ignored, anyway? */
2475  SCIP_Real* minresactivity, /**< pointer to store the minimal residual activity, or NULL, if not needed */
2476  SCIP_Real* maxresactivity, /**< pointer to store the maximal residual activity, or NULL, if not needed */
2477  SCIP_Bool* minisrelax, /**< pointer to store whether the returned residual minactivity is just a
2478  * relaxation, i.e. <= the exact residual minactivity (in case of huge
2479  * contributions), or equal to the exact residual minactivity */
2480  SCIP_Bool* maxisrelax, /**< pointer to store whether the returned residual maxactivity is just a
2481  * relaxation, i.e. <= the exact residual maxactivity (in case of huge
2482  * contributions), or equal to the exact residual minactivity */
2483  SCIP_Bool* isminsettoinfinity, /**< pointer to store whether minresactivity was set to infinity or calculated */
2484  SCIP_Bool* ismaxsettoinfinity /**< pointer to store whether maxresactivity was set to infinity or calculated */
2485  )
2486 {
2487  SCIP_Real minactbound;
2488  SCIP_Real maxactbound;
2489  SCIP_Real absval;
2490 
2491  assert(scip != NULL);
2492  assert(consdata != NULL);
2493  assert(var != NULL);
2494  assert((minresactivity != NULL && minisrelax != NULL && isminsettoinfinity != NULL )
2495  || (maxresactivity != NULL && maxisrelax != NULL && ismaxsettoinfinity != NULL));
2496 
2497  /* get activity bounds of linear constraint */
2498  if( !consdata->validactivities )
2499  consdataCalcActivities(scip, consdata);
2500 
2501  assert(consdata->glbminactivity < SCIP_INVALID);
2502  assert(consdata->glbmaxactivity < SCIP_INVALID);
2503  assert(consdata->glbminactivityneginf >= 0);
2504  assert(consdata->glbminactivityposinf >= 0);
2505  assert(consdata->glbmaxactivityneginf >= 0);
2506  assert(consdata->glbmaxactivityposinf >= 0);
2507 
2508  if( val > 0.0 )
2509  {
2510  minactbound = SCIPvarGetLbGlobal(var);
2511  maxactbound = SCIPvarGetUbGlobal(var);
2512  absval = val;
2513  }
2514  else
2515  {
2516  minactbound = -SCIPvarGetUbGlobal(var);
2517  maxactbound = -SCIPvarGetLbGlobal(var);
2518  absval = -val;
2519  }
2520 
2521  if( minresactivity != NULL )
2522  {
2523  assert(isminsettoinfinity != NULL);
2524  assert(minisrelax != NULL);
2525 
2526  /* get/compute minactivity by calling getMinActivity() with updated counters for infinite and huge values
2527  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2528  */
2529  if( SCIPisInfinity(scip, minactbound) )
2530  {
2531  assert(consdata->glbminactivityposinf >= 1);
2532 
2533  getMinActivity(scip, consdata, consdata->glbminactivityposinf - 1, consdata->glbminactivityneginf,
2534  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2535  minresactivity, minisrelax, isminsettoinfinity);
2536  }
2537  else if( SCIPisInfinity(scip, -minactbound) )
2538  {
2539  assert(consdata->glbminactivityneginf >= 1);
2540 
2541  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf - 1,
2542  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2543  minresactivity, minisrelax, isminsettoinfinity);
2544  }
2545  else if( SCIPisHugeValue(scip, minactbound * absval) )
2546  {
2547  assert(consdata->glbminactivityposhuge >= 1);
2548 
2549  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2550  consdata->glbminactivityposhuge - 1, consdata->glbminactivityneghuge, 0.0, TRUE, goodrelax,
2551  minresactivity, minisrelax, isminsettoinfinity);
2552  }
2553  else if( SCIPisHugeValue(scip, -minactbound * absval) )
2554  {
2555  assert(consdata->glbminactivityneghuge >= 1);
2556 
2557  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2558  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge - 1, 0.0, TRUE, goodrelax,
2559  minresactivity, minisrelax, isminsettoinfinity);
2560  }
2561  else
2562  {
2563  getMinActivity(scip, consdata, consdata->glbminactivityposinf, consdata->glbminactivityneginf,
2564  consdata->glbminactivityposhuge, consdata->glbminactivityneghuge, absval * minactbound, TRUE,
2565  goodrelax, minresactivity, minisrelax, isminsettoinfinity);
2566  }
2567  }
2568 
2569  if( maxresactivity != NULL )
2570  {
2571  assert(ismaxsettoinfinity != NULL);
2572  assert(maxisrelax != NULL);
2573 
2574  /* get/compute maxactivity by calling getMaxActivity() with updated counters for infinite and huge values
2575  * and contribution of variable set to zero that has to be subtracted from finite part of activity
2576  */
2577  if( SCIPisInfinity(scip, -maxactbound) )
2578  {
2579  assert(consdata->glbmaxactivityneginf >= 1);
2580 
2581  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf - 1,
2582  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2583  maxresactivity, maxisrelax, ismaxsettoinfinity);
2584  }
2585  else if( SCIPisInfinity(scip, maxactbound) )
2586  {
2587  assert(consdata->glbmaxactivityposinf >= 1);
2588 
2589  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf - 1, consdata->glbmaxactivityneginf,
2590  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2591  maxresactivity, maxisrelax, ismaxsettoinfinity);
2592  }
2593  else if( SCIPisHugeValue(scip, absval * maxactbound) )
2594  {
2595  assert(consdata->glbmaxactivityposhuge >= 1);
2596 
2597  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2598  consdata->glbmaxactivityposhuge - 1, consdata->glbmaxactivityneghuge, 0.0, TRUE, goodrelax,
2599  maxresactivity, maxisrelax, ismaxsettoinfinity);
2600  }
2601  else if( SCIPisHugeValue(scip, -absval * maxactbound) )
2602  {
2603  assert(consdata->glbmaxactivityneghuge >= 1);
2604 
2605  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2606  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge - 1, 0.0, TRUE, goodrelax,
2607  maxresactivity, maxisrelax, ismaxsettoinfinity);
2608  }
2609  else
2610  {
2611  getMaxActivity(scip, consdata, consdata->glbmaxactivityposinf, consdata->glbmaxactivityneginf,
2612  consdata->glbmaxactivityposhuge, consdata->glbmaxactivityneghuge, absval * maxactbound, TRUE,
2613  goodrelax, maxresactivity, maxisrelax, ismaxsettoinfinity);
2614  }
2615  }
2616 }
2617 
2618 /** calculates the activity of the linear constraint for given solution */
2619 static
2621  SCIP* scip, /**< SCIP data structure */
2622  SCIP_CONSDATA* consdata, /**< linear constraint data */
2623  SCIP_SOL* sol /**< solution to get activity for, NULL to current solution */
2624  )
2625 {
2626  SCIP_Real activity;
2627 
2628  assert(scip != NULL);
2629  assert(consdata != NULL);
2630 
2631  if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
2632  activity = consdataComputePseudoActivity(scip, consdata);
2633  else
2634  {
2635  SCIP_Real solval;
2636  int nposinf;
2637  int nneginf;
2638  SCIP_Bool negsign;
2639  int v;
2640 
2641  activity = 0.0;
2642  nposinf = 0;
2643  nneginf = 0;
2644  negsign = 0;
2645 
2646  for( v = 0; v < consdata->nvars; ++v )
2647  {
2648  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
2649 
2650  if( consdata->vals[v] < 0 )
2651  negsign = TRUE;
2652  else
2653  negsign = FALSE;
2654 
2655  if( (SCIPisInfinity(scip, solval) && !negsign) || (SCIPisInfinity(scip, -solval) && negsign) )
2656  ++nposinf;
2657  else if( (SCIPisInfinity(scip, solval) && negsign) || (SCIPisInfinity(scip, -solval) && !negsign) )
2658  ++nneginf;
2659  else
2660  activity += consdata->vals[v] * solval;
2661  }
2662  assert(nneginf >= 0 && nposinf >= 0);
2663 
2664  SCIPdebugMessage("activity of linear constraint: %.15g, %d positive infinity values, %d negative infinity values \n", activity, nposinf, nneginf);
2665 
2666  /* check for amount of infinity values and correct the activity */
2667  if( nposinf > 0 && nneginf > 0 )
2668  activity = (consdata->rhs + consdata->lhs) / 2;
2669  else if( nposinf > 0 )
2670  activity = SCIPinfinity(scip);
2671  else if( nneginf > 0 )
2672  activity = -SCIPinfinity(scip);
2673 
2674  SCIPdebugMessage("corrected activity of linear constraint: %.15g\n", activity);
2675  }
2676 
2677  if( activity < 0 )
2678  activity = MAX(activity, -SCIPinfinity(scip)); /*lint !e666*/
2679  else
2680  activity = MIN(activity, SCIPinfinity(scip)); /*lint !e666*/
2681 
2682  return activity;
2683 }
2684 
2685 /** calculates the feasibility of the linear constraint for given solution */
2686 static
2688  SCIP* scip, /**< SCIP data structure */
2689  SCIP_CONSDATA* consdata, /**< linear constraint data */
2690  SCIP_SOL* sol /**< solution to get feasibility for, NULL to current solution */
2691  )
2692 {
2693  SCIP_Real activity;
2694 
2695  assert(scip != NULL);
2696  assert(consdata != NULL);
2697 
2698  activity = consdataGetActivity(scip, consdata, sol);
2699 
2700  return MIN(consdata->rhs - activity, activity - consdata->lhs);
2701 }
2702 
2703 /** returns the signature bitmask for the given variable */
2704 static
2706  SCIP_VAR* var /**< variable */
2707  )
2708 {
2709  int sigidx;
2710 
2711  assert(var != NULL);
2712 
2713  sigidx = SCIPvarGetIndex(var) % (int)(8*sizeof(SCIP_Longint));
2714  return ((SCIP_Longint)1) << sigidx; /*lint !e703*/
2715 }
2716 
2717 /** updates bit signatures after adding a single coefficient */
2718 static
2720  SCIP_CONSDATA* consdata, /**< linear constraint data */
2721  int pos /**< position of coefficient to update signatures for */
2722  )
2723 {
2724  SCIP_Longint varsignature;
2725  SCIP_Real lb;
2726  SCIP_Real ub;
2727  SCIP_Real val;
2728 
2729  assert(consdata != NULL);
2730  assert(consdata->validsignature);
2731 
2732  varsignature = getVarSignature(consdata->vars[pos]);
2733  lb = SCIPvarGetLbGlobal(consdata->vars[pos]);
2734  ub = SCIPvarGetUbGlobal(consdata->vars[pos]);
2735  val = consdata->vals[pos];
2736  if( (val > 0.0 && ub > 0.0) || (val < 0.0 && lb < 0.0) )
2737  consdata->possignature |= varsignature;
2738  if( (val > 0.0 && lb < 0.0) || (val < 0.0 && ub > 0.0) )
2739  consdata->negsignature |= varsignature;
2740 }
2741 
2742 /** calculates the bit signatures of the given constraint data */
2743 static
2745  SCIP_CONSDATA* consdata /**< linear constraint data */
2746  )
2747 {
2748  assert(consdata != NULL);
2749 
2750  if( !consdata->validsignature )
2751  {
2752  int i;
2753 
2754  consdata->validsignature = TRUE;
2755  consdata->possignature = 0;
2756  consdata->negsignature = 0;
2757  for( i = 0; i < consdata->nvars; ++i )
2758  consdataUpdateSignatures(consdata, i);
2759  }
2760 }
2761 
2762 /** index comparison method of linear constraints: compares two indices of the variable set in the linear constraint */
2763 static
2764 SCIP_DECL_SORTINDCOMP(consdataCompVar)
2765 { /*lint --e{715}*/
2766  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
2767 
2768  assert(consdata != NULL);
2769  assert(0 <= ind1 && ind1 < consdata->nvars);
2770  assert(0 <= ind2 && ind2 < consdata->nvars);
2771 
2772  return SCIPvarCompare(consdata->vars[ind1], consdata->vars[ind2]);
2773 }
2774 
2775 /** permutes the constraint's variables according to a given permutation. */
2776 static
2778  SCIP_CONSDATA* consdata, /**< the constraint data */
2779  int* perm, /**< the target permutation */
2780  int nvars /**< the number of variables */
2781  )
2782 { /*lint --e{715}*/
2783  SCIP_VAR* varv;
2784  SCIP_EVENTDATA* eventdatav;
2785  SCIP_Real valv;
2786  int v;
2787  int i;
2788  int nexti;
2789 
2790  assert(perm != NULL);
2791  assert(consdata != NULL);
2792 
2793  /* permute the variables in the linear constraint according to the target permutation */
2794  eventdatav = NULL;
2795  for( v = 0; v < nvars; ++v )
2796  {
2797  if( perm[v] != v )
2798  {
2799  varv = consdata->vars[v];
2800  valv = consdata->vals[v];
2801  if( consdata->eventdatas != NULL )
2802  eventdatav = consdata->eventdatas[v];
2803  i = v;
2804  do
2805  {
2806  assert(0 <= perm[i] && perm[i] < nvars);
2807  assert(perm[i] != i);
2808  consdata->vars[i] = consdata->vars[perm[i]];
2809  consdata->vals[i] = consdata->vals[perm[i]];
2810  if( consdata->eventdatas != NULL )
2811  {
2812  consdata->eventdatas[i] = consdata->eventdatas[perm[i]];
2813  consdata->eventdatas[i]->varpos = i;
2814  }
2815  nexti = perm[i];
2816  perm[i] = i;
2817  i = nexti;
2818  }
2819  while( perm[i] != v );
2820  consdata->vars[i] = varv;
2821  consdata->vals[i] = valv;
2822  if( consdata->eventdatas != NULL )
2823  {
2824  consdata->eventdatas[i] = eventdatav;
2825  consdata->eventdatas[i]->varpos = i;
2826  }
2827  perm[i] = i;
2828  }
2829  }
2830 #ifdef SCIP_DEBUG
2831  /* check sorting */
2832  for( v = 0; v < nvars; ++v )
2833  {
2834  assert(perm[v] == v);
2835  assert(consdata->eventdatas == NULL || consdata->eventdatas[v]->varpos == v);
2836  }
2837 #endif
2838 }
2839 
2840 /** sorts linear constraint's variables depending on the stage of the solving process:
2841  * - during PRESOLVING
2842  * sorts variables by binaries, integers, implicit integers, and continuous variables,
2843  * and the variables of the same type by non-decreasing variable index
2844  *
2845  * - during SOLVING
2846  * sorts binary variables of the remaining problem w.r.t the absolute of their coefficient.
2847  * This fastens the propagation time of the constraint handler.
2848  */
2849 static
2851  SCIP* scip, /**< SCIP data structure */
2852  SCIP_CONSDATA* consdata /**< linear constraint data */
2853  )
2854 {
2855  assert(scip != NULL);
2856  assert(consdata != NULL);
2857 
2858  /* check if there are variables for sorting */
2859  if( consdata->nvars <= 1 )
2860  {
2861  consdata->sorted = TRUE;
2862  consdata->binvarssorted = TRUE;
2863  }
2864  else if( SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE && !consdata->sorted )
2865  {
2866  int* perm;
2867 
2868  /* get temporary memory to store the sorted permutation */
2869  SCIP_CALL( SCIPallocBufferArray(scip, &perm, consdata->nvars) );
2870 
2871  /* call sorting method */
2872  SCIPsort(perm, consdataCompVar, (void*)consdata, consdata->nvars);
2873 
2874  permSortConsdata(consdata, perm, consdata->nvars);
2875 
2876  /* free temporary memory */
2877  SCIPfreeBufferArray(scip, &perm);
2878 
2879  consdata->sorted = TRUE;
2880  consdata->binvarssorted = FALSE;
2881  }
2882  else if( SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
2883  {
2884  SCIP_EVENTDATA** eventdatas;
2885  SCIP_VAR** vars;
2886  SCIP_Real* vals;
2887  int nvars;
2888  int v;
2889  int lastbin;
2890 
2891  nvars = consdata->nvars;
2892  vars = consdata->vars;
2893  vals = consdata->vals;
2894  eventdatas = consdata->eventdatas;
2895  assert(vars != NULL || nvars == 0);
2896  assert(vals != NULL || nvars == 0);
2897 
2898  lastbin = 0;
2899  /* count binary variables and permute variables such that binaries appear first in the sorted vars array */
2900  for( v = 0; v < nvars; ++v )
2901  {
2902  assert( vars != NULL); /* for flexelint */
2903  assert( vals != NULL); /* for flexelint */
2904  if( SCIPvarIsBinary(vars[v]) )
2905  {
2906  /* swap variable at the end of the binary variables, if necessary */
2907  if( lastbin < v )
2908  {
2909  SCIP_VAR* tmpvar;
2910  SCIP_Real tmpval;
2911 
2912  tmpvar = vars[lastbin];
2913  tmpval = vals[lastbin];
2914 
2915  vars[lastbin] = vars[v];
2916  vals[lastbin] = vals[v];
2917 
2918  vars[v] = tmpvar;
2919  vals[v] = tmpval;
2920 
2921  if( eventdatas != NULL )
2922  {
2923  SCIP_EVENTDATA* tmpeventdata;
2924 
2925  tmpeventdata = eventdatas[lastbin];
2926  eventdatas[lastbin] = eventdatas[v];
2927  eventdatas[lastbin]->varpos = lastbin;
2928  eventdatas[v] = tmpeventdata;
2929  eventdatas[v]->varpos = v;
2930  }
2931  assert(SCIPvarIsBinary(vars[lastbin]));
2932  }
2933 #ifndef NDEBUG
2934  else
2935  assert(lastbin == v);
2936 #endif
2937  ++lastbin;
2938  }
2939  }
2940  consdata->nbinvars = lastbin;
2941 
2942 #ifndef NDEBUG
2943  /* check sorting */
2944  for( v = 0; v < nvars; ++v )
2945  {
2946  assert(vars != NULL); /* for flexelint */
2947  assert(eventdatas == NULL || eventdatas[v]->varpos == v);
2948  assert((v >= consdata->nbinvars && !SCIPvarIsBinary(vars[v])) || (v < consdata->nbinvars && SCIPvarIsBinary(vars[v])));
2949  }
2950 #endif
2951 
2952  if( consdata->nbinvars > 1 )
2953  {
2954  SCIP_Real* absvals;
2955  int* perm;
2956 
2957  assert(lastbin == consdata->nbinvars);
2958  assert(lastbin <= nvars);
2959  assert(vals != NULL);
2960 
2961  /* initialize absolute coefficients and the target permutation for binary variables */
2962  SCIP_CALL( SCIPallocBufferArray(scip, &absvals, lastbin) );
2963  SCIP_CALL( SCIPallocBufferArray(scip, &perm, lastbin) );
2964 
2965  for( v = 0; v < lastbin; ++v )
2966  {
2967  absvals[v] = ABS(vals[v]);
2968  perm[v] = v;
2969  }
2970 
2971  /* execute the sorting */
2972  SCIPsortDownRealInt(absvals, perm, lastbin);
2973 
2974  permSortConsdata(consdata, perm, lastbin);
2975 
2976  /* free temporary arrays */
2977  SCIPfreeBufferArray(scip, &perm);
2978  SCIPfreeBufferArray(scip, &absvals);
2979  }
2980  consdata->binvarssorted = TRUE;
2981 
2982  /* presolve sorting cannot be guaranteed after binary sorting */
2983  consdata->sorted = (consdata->sorted && consdata->nbinvars == 0);
2984  }
2985  assert(SCIPgetStage(scip) < SCIP_STAGE_INITSOLVE || consdata->binvarssorted);
2986  assert(SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE || consdata->sorted);
2987 
2988  return SCIP_OKAY;
2989 }
2990 
2991 
2992 /*
2993  * local linear constraint handler methods
2994  */
2995 
2996 /** sets left hand side of linear constraint */
2997 static
2999  SCIP* scip, /**< SCIP data structure */
3000  SCIP_CONS* cons, /**< linear constraint */
3001  SCIP_Real lhs /**< new left hand side */
3002  )
3003 {
3004  SCIP_CONSDATA* consdata;
3005 
3006  assert(scip != NULL);
3007  assert(cons != NULL);
3008  assert(!SCIPisInfinity(scip, lhs));
3009 
3010  /* adjust value to not be smaller than -inf */
3011  if ( SCIPisInfinity(scip, -lhs) )
3012  lhs = -SCIPinfinity(scip);
3013 
3014  consdata = SCIPconsGetData(cons);
3015  assert(consdata != NULL);
3016  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3017  assert(!SCIPisInfinity(scip, consdata->lhs));
3018 
3019  /* check whether the side is not changed */
3020  if( SCIPisEQ(scip, consdata->lhs, lhs) )
3021  return SCIP_OKAY;
3022 
3023  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3024  if( SCIPisEQ(scip, lhs, consdata->rhs) )
3025  {
3026  consdata->rhs = lhs;
3027  assert(consdata->row == NULL);
3028  }
3029 
3030  /* if necessary, update the rounding locks of variables */
3031  if( SCIPconsIsLocked(cons) )
3032  {
3033  if( SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, -lhs) )
3034  {
3035  SCIP_VAR** vars;
3036  SCIP_Real* vals;
3037  int v;
3038 
3039  /* the left hand side switched from -infinity to a non-infinite value -> install rounding locks */
3040  vars = consdata->vars;
3041  vals = consdata->vals;
3042 
3043  for( v = 0; v < consdata->nvars; ++v )
3044  {
3045  assert(vars[v] != NULL);
3046  assert(!SCIPisZero(scip, vals[v]));
3047 
3048  if( SCIPisPositive(scip, vals[v]) )
3049  {
3050  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3051  }
3052  else
3053  {
3054  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3055  }
3056  }
3057  }
3058  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, -lhs) )
3059  {
3060  SCIP_VAR** vars;
3061  SCIP_Real* vals;
3062  int v;
3063 
3064  /* the left hand side switched from a non-infinite value to -infinity -> remove rounding locks */
3065  vars = consdata->vars;
3066  vals = consdata->vals;
3067 
3068  for( v = 0; v < consdata->nvars; ++v )
3069  {
3070  assert(vars[v] != NULL);
3071  assert(!SCIPisZero(scip, vals[v]));
3072 
3073  if( SCIPisPositive(scip, vals[v]) )
3074  {
3075  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3076  }
3077  else
3078  {
3079  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3080  }
3081  }
3082  }
3083  }
3084 
3085  /* 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 */
3086  if( !SCIPisInfinity(scip, -lhs) && SCIPisGT(scip, lhs, consdata->lhs) )
3087  {
3088  consdata->propagated = FALSE;
3089  consdata->boundstightened = FALSE;
3090  consdata->presolved = FALSE;
3091  consdata->cliquesadded = FALSE;
3092  consdata->implsadded = FALSE;
3093  }
3094 
3095  /* set new left hand side and update constraint data */
3096  consdata->lhs = lhs;
3097  consdata->changed = TRUE;
3098  consdata->normalized = FALSE;
3099  consdata->upgradetried = FALSE;
3100 
3101  /* update the lhs of the LP row */
3102  if( consdata->row != NULL )
3103  {
3104  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, lhs) );
3105  }
3106 
3107  return SCIP_OKAY;
3108 }
3109 
3110 /** sets right hand side of linear constraint */
3111 static
3113  SCIP* scip, /**< SCIP data structure */
3114  SCIP_CONS* cons, /**< linear constraint */
3115  SCIP_Real rhs /**< new right hand side */
3116  )
3117 {
3118  SCIP_CONSDATA* consdata;
3119 
3120  assert(scip != NULL);
3121  assert(cons != NULL);
3122  assert(!SCIPisInfinity(scip, -rhs));
3123 
3124  /* adjust value to not be larger than inf */
3125  if ( SCIPisInfinity(scip, rhs) )
3126  rhs = SCIPinfinity(scip);
3127 
3128  consdata = SCIPconsGetData(cons);
3129  assert(consdata != NULL);
3130  assert(consdata->nvars == 0 || (consdata->vars != NULL && consdata->vals != NULL));
3131  assert(!SCIPisInfinity(scip, -consdata->rhs));
3132 
3133  /* check whether the side is not changed */
3134  if( SCIPisEQ(scip, consdata->rhs, rhs) )
3135  return SCIP_OKAY;
3136 
3137  /* ensure that rhs >= lhs is satisfied without numerical tolerance */
3138  if( SCIPisEQ(scip, rhs, consdata->lhs) )
3139  {
3140  consdata->lhs = rhs;
3141  assert(consdata->row == NULL);
3142  }
3143 
3144  /* if necessary, update the rounding locks of variables */
3145  if( SCIPconsIsLocked(cons) )
3146  {
3147  assert(SCIPconsIsTransformed(cons));
3148 
3149  if( SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, rhs) )
3150  {
3151  SCIP_VAR** vars;
3152  SCIP_Real* vals;
3153  int v;
3154 
3155  /* the right hand side switched from infinity to a non-infinite value -> install rounding locks */
3156  vars = consdata->vars;
3157  vals = consdata->vals;
3158 
3159  for( v = 0; v < consdata->nvars; ++v )
3160  {
3161  assert(vars[v] != NULL);
3162  assert(!SCIPisZero(scip, vals[v]));
3163 
3164  if( SCIPisPositive(scip, vals[v]) )
3165  {
3166  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3167  }
3168  else
3169  {
3170  SCIP_CALL( SCIPlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3171  }
3172  }
3173  }
3174  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, rhs) )
3175  {
3176  SCIP_VAR** vars;
3177  SCIP_Real* vals;
3178  int v;
3179 
3180  /* the right hand side switched from a non-infinite value to infinity -> remove rounding locks */
3181  vars = consdata->vars;
3182  vals = consdata->vals;
3183 
3184  for( v = 0; v < consdata->nvars; ++v )
3185  {
3186  assert(vars[v] != NULL);
3187  assert(!SCIPisZero(scip, vals[v]));
3188 
3189  if( SCIPisPositive(scip, vals[v]) )
3190  {
3191  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, FALSE, TRUE) );
3192  }
3193  else
3194  {
3195  SCIP_CALL( SCIPunlockVarCons(scip, vars[v], cons, TRUE, FALSE) );
3196  }
3197  }
3198  }
3199  }
3200 
3201  /* 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 */
3202  if( !SCIPisInfinity(scip, rhs) && SCIPisLT(scip, rhs, consdata->rhs) )
3203  {
3204  consdata->propagated = FALSE;
3205  consdata->boundstightened = FALSE;
3206  consdata->presolved = FALSE;
3207  consdata->cliquesadded = FALSE;
3208  consdata->implsadded = FALSE;
3209  }
3210 
3211  /* set new right hand side and update constraint data */
3212  consdata->rhs = rhs;
3213  consdata->changed = TRUE;
3214  consdata->normalized = FALSE;
3215  consdata->upgradetried = FALSE;
3216 
3217  /* update the rhs of the LP row */
3218  if( consdata->row != NULL )
3219  {
3220  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, rhs) );
3221  }
3222 
3223  return SCIP_OKAY;
3224 }
3225 
3226 /** adds coefficient in linear constraint */
3227 static
3229  SCIP* scip, /**< SCIP data structure */
3230  SCIP_CONS* cons, /**< linear constraint */
3231  SCIP_VAR* var, /**< variable of constraint entry */
3232  SCIP_Real val /**< coefficient of constraint entry */
3233  )
3234 {
3235  SCIP_CONSDATA* consdata;
3236  SCIP_Bool transformed;
3237 
3238  assert(scip != NULL);
3239  assert(cons != NULL);
3240  assert(var != NULL);
3241 
3242  /* ignore coefficient if it is nearly zero */
3243  if( SCIPisZero(scip, val) )
3244  return SCIP_OKAY;
3245 
3246  consdata = SCIPconsGetData(cons);
3247  assert(consdata != NULL);
3248 
3249  /* are we in the transformed problem? */
3250  transformed = SCIPconsIsTransformed(cons);
3251 
3252  /* always use transformed variables in transformed constraints */
3253  if( transformed )
3254  {
3255  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
3256  }
3257  assert(var != NULL);
3258  assert(transformed == SCIPvarIsTransformed(var));
3259 
3260  SCIP_CALL( consdataEnsureVarsSize(scip, consdata, consdata->nvars+1) );
3261  consdata->vars[consdata->nvars] = var;
3262  consdata->vals[consdata->nvars] = val;
3263  consdata->nvars++;
3264  /* capture variable */
3265  SCIP_CALL( SCIPcaptureVar(scip, var) );
3266 
3267  /* if we are in transformed problem, the variable needs an additional event data */
3268  if( transformed )
3269  {
3270  if( consdata->eventdatas != NULL )
3271  {
3272  SCIP_CONSHDLR* conshdlr;
3273  SCIP_CONSHDLRDATA* conshdlrdata;
3274 
3275  /* get event handler */
3276  conshdlr = SCIPconsGetHdlr(cons);
3277  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3278  assert(conshdlrdata != NULL);
3279  assert(conshdlrdata->eventhdlr != NULL);
3280 
3281  /* initialize eventdatas array */
3282  consdata->eventdatas[consdata->nvars-1] = NULL;
3283 
3284  /* catch bound change events of variable */
3285  SCIP_CALL( consCatchEvent(scip, cons, conshdlrdata->eventhdlr, consdata->nvars-1) );
3286  }
3287 
3288  /* update minimum and maximum activities */
3289  consdataUpdateAddCoef(scip, consdata, var, val, FALSE);
3290  }
3291 
3292  /* install rounding locks for new variable */
3293  SCIP_CALL( lockRounding(scip, cons, var, val) );
3294 
3295  consdata->propagated = FALSE;
3296  consdata->boundstightened = FALSE;
3297  consdata->presolved = FALSE;
3298  consdata->removedfixings = consdata->removedfixings && SCIPvarIsActive(var);
3299 
3300  if( consdata->validsignature )
3301  consdataUpdateSignatures(consdata, consdata->nvars-1);
3302 
3303  consdata->changed = TRUE;
3304  consdata->normalized = FALSE;
3305  consdata->upgradetried = FALSE;
3306  consdata->cliquesadded = FALSE;
3307  consdata->implsadded = FALSE;
3308 
3309  if( consdata->nvars == 1 )
3310  {
3311  consdata->binvarssorted = TRUE;
3312  consdata->sorted = TRUE;
3313  consdata->merged = TRUE;
3314  }
3315  else
3316  {
3317  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3318  consdata->sorted = consdata->sorted
3319  && (SCIPvarCompare(consdata->vars[consdata->nvars-2], consdata->vars[consdata->nvars-1]) <= 0);
3320  consdata->merged = FALSE;
3321  }
3322 
3323  /* add the new coefficient to the LP row */
3324  if( consdata->row != NULL )
3325  {
3326  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, val) );
3327  }
3328 
3329  return SCIP_OKAY;
3330 }
3331 
3332 /** deletes coefficient at given position from linear constraint data */
3333 static
3335  SCIP* scip, /**< SCIP data structure */
3336  SCIP_CONS* cons, /**< linear constraint */
3337  int pos /**< position of coefficient to delete */
3338  )
3339 {
3340  SCIP_CONSDATA* consdata;
3341  SCIP_VAR* var;
3342  SCIP_Real val;
3343 
3344  assert(scip != NULL);
3345  assert(cons != NULL);
3346 
3347  consdata = SCIPconsGetData(cons);
3348  assert(consdata != NULL);
3349  assert(0 <= pos && pos < consdata->nvars);
3350 
3351  var = consdata->vars[pos];
3352  val = consdata->vals[pos];
3353  assert(var != NULL);
3354 
3355  /* remove rounding locks for deleted variable */
3356  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3357 
3358  /* if we are in transformed problem, delete the event data of the variable */
3359  if( SCIPconsIsTransformed(cons) )
3360  {
3361  SCIP_CONSHDLR* conshdlr;
3362  SCIP_CONSHDLRDATA* conshdlrdata;
3363 
3364  /* get event handler */
3365  conshdlr = SCIPconsGetHdlr(cons);
3366  conshdlrdata = SCIPconshdlrGetData(conshdlr);
3367  assert(conshdlrdata != NULL);
3368  assert(conshdlrdata->eventhdlr != NULL);
3369 
3370  /* drop bound change events of variable */
3371  if( consdata->eventdatas != NULL )
3372  {
3373  SCIP_CALL( consDropEvent(scip, cons, conshdlrdata->eventhdlr, pos) );
3374  assert(consdata->eventdatas[pos] == NULL);
3375  }
3376  }
3377 
3378  /* move the last variable to the free slot */
3379  if( pos != consdata->nvars-1 )
3380  {
3381  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(consdata->vars[pos]);
3382 
3383  consdata->vars[pos] = consdata->vars[consdata->nvars-1];
3384  consdata->vals[pos] = consdata->vals[consdata->nvars-1];
3385 
3386  if( consdata->eventdatas != NULL )
3387  {
3388  consdata->eventdatas[pos] = consdata->eventdatas[consdata->nvars-1];
3389  assert(consdata->eventdatas[pos] != NULL);
3390  consdata->eventdatas[pos]->varpos = pos;
3391  }
3392  consdata->sorted = consdata->sorted && (pos + 2 >= consdata->nvars || (SCIPvarCompare(consdata->vars[pos], consdata->vars[pos + 1]) <= 0));
3393  }
3394  consdata->nvars--;
3395 
3396  /* if at most one variable is left, the activities should be recalculated (to correspond exactly to the bounds
3397  * of the remaining variable, or give exactly 0.0)
3398  */
3399  if( consdata->nvars <= 1 )
3400  consdataInvalidateActivities(consdata);
3401  else
3402  {
3403  /* if we are in transformed problem, update minimum and maximum activities */
3404  if( SCIPconsIsTransformed(cons) )
3405  consdataUpdateDelCoef(scip, consdata, var, val, TRUE);
3406  }
3407 
3408  consdata->propagated = FALSE;
3409  consdata->boundstightened = FALSE;
3410  consdata->presolved = FALSE;
3411  consdata->validsignature = FALSE;
3412  consdata->changed = TRUE;
3413  consdata->normalized = FALSE;
3414  consdata->upgradetried = FALSE;
3415  consdata->cliquesadded = FALSE;
3416  consdata->implsadded = FALSE;
3417 
3418  /* delete coefficient from the LP row */
3419  if( consdata->row != NULL )
3420  {
3421  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, -val) );
3422  }
3423 
3424  /* release variable */
3425  SCIP_CALL( SCIPreleaseVar(scip, &var) );
3426 
3427  return SCIP_OKAY;
3428 }
3429 
3430 /** changes coefficient value at given position of linear constraint data */
3431 static
3433  SCIP* scip, /**< SCIP data structure */
3434  SCIP_CONS* cons, /**< linear constraint */
3435  int pos, /**< position of coefficient to delete */
3436  SCIP_Real newval /**< new value of coefficient */
3437  )
3438 {
3439  SCIP_CONSDATA* consdata;
3440  SCIP_VAR* var;
3441  SCIP_Real val;
3442 
3443  assert(scip != NULL);
3444  assert(cons != NULL);
3445  assert(!SCIPisZero(scip, newval));
3446 
3447  consdata = SCIPconsGetData(cons);
3448  assert(consdata != NULL);
3449  assert(0 <= pos && pos < consdata->nvars);
3450  assert(!SCIPisZero(scip, newval));
3451 
3452  var = consdata->vars[pos];
3453  val = consdata->vals[pos];
3454  assert(var != NULL);
3455  assert(SCIPconsIsTransformed(cons) == SCIPvarIsTransformed(var));
3456 
3457  /* if necessary, update the rounding locks of the variable */
3458  if( SCIPconsIsLocked(cons) && newval * val < 0.0 )
3459  {
3460  assert(SCIPconsIsTransformed(cons));
3461 
3462  /* remove rounding locks for variable with old coefficient */
3463  SCIP_CALL( unlockRounding(scip, cons, var, val) );
3464 
3465  /* install rounding locks for variable with new coefficient */
3466  SCIP_CALL( lockRounding(scip, cons, var, newval) );
3467  }
3468 
3469  /* change the value */
3470  consdata->vals[pos] = newval;
3471 
3472  consdata->binvarssorted = consdata->binvarssorted && !SCIPvarIsBinary(var);
3473 
3474  /* update minimum and maximum activities */
3475  if( SCIPconsIsTransformed(cons) )
3476  consdataUpdateChgCoef(scip, consdata, var, val, newval, TRUE);
3477 
3478  consdata->propagated = FALSE;
3479  consdata->boundstightened = FALSE;
3480  consdata->presolved = FALSE;
3481  consdata->validsignature = consdata->validsignature && (newval * val > 0.0);
3482  consdata->changed = TRUE;
3483  consdata->normalized = FALSE;
3484  consdata->upgradetried = FALSE;
3485  consdata->cliquesadded = FALSE;
3486  consdata->implsadded = FALSE;
3487 
3488  return SCIP_OKAY;
3489 }
3490 
3491 /** scales a linear constraint with a constant scalar */
3492 static
3494  SCIP* scip, /**< SCIP data structure */
3495  SCIP_CONS* cons, /**< linear constraint to scale */
3496  SCIP_Real scalar /**< value to scale constraint with */
3497  )
3498 {
3499  SCIP_CONSDATA* consdata;
3500  SCIP_Real newval;
3501  SCIP_Real absscalar;
3502  int i;
3503 
3504  assert(scip != NULL);
3505  assert(cons != NULL);
3506 
3507  consdata = SCIPconsGetData(cons);
3508  assert(consdata != NULL);
3509  assert(consdata->row == NULL);
3510  assert(!SCIPisEQ(scip, scalar, 1.0));
3511 
3512  /* scale the coefficients */
3513  for( i = consdata->nvars - 1; i >= 0; --i )
3514  {
3515  newval = scalar * consdata->vals[i];
3516 
3517  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
3518  * flooring down our new value
3519  */
3520  if( SCIPisScalingIntegral(scip, consdata->vals[i], scalar) )
3521  newval = SCIPfeasFloor(scip, newval + 0.5);
3522 
3523  if( SCIPisZero(scip, newval) )
3524  {
3525  SCIPwarningMessage(scip, "coefficient %.15g of variable <%s> in linear constraint <%s> scaled to zero (scalar: %.15g)\n",
3526  consdata->vals[i], SCIPvarGetName(consdata->vars[i]), SCIPconsGetName(cons), scalar);
3527  SCIP_CALL( delCoefPos(scip, cons, i) );
3528  }
3529  else
3530  consdata->vals[i] = newval;
3531  }
3532 
3533  /* scale the sides */
3534  if( scalar < 0.0 )
3535  {
3536  SCIP_Real lhs;
3537 
3538  lhs = consdata->lhs;
3539  consdata->lhs = -consdata->rhs;
3540  consdata->rhs = -lhs;
3541  }
3542  absscalar = REALABS(scalar);
3543  if( !SCIPisInfinity(scip, -consdata->lhs) )
3544  {
3545  newval = absscalar * consdata->lhs;
3546 
3547  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasFloor, we add an additional 0.5 before
3548  * flooring down our new value
3549  */
3550  if( SCIPisScalingIntegral(scip, consdata->lhs, absscalar) )
3551  consdata->lhs = SCIPfeasFloor(scip, newval + 0.5);
3552  else
3553  consdata->lhs = newval;
3554  }
3555  if( !SCIPisInfinity(scip, consdata->rhs) )
3556  {
3557  newval = absscalar * consdata->rhs;
3558 
3559  /* because SCIPisScalingIntegral uses another integrality check as SCIPfeasCeil, we subtract 0.5 before ceiling up
3560  * our new value
3561  */
3562  if( SCIPisScalingIntegral(scip, consdata->rhs, absscalar) )
3563  consdata->rhs = SCIPfeasCeil(scip, newval - 0.5);
3564  else
3565  consdata->rhs = newval;
3566  }
3567 
3568  consdataInvalidateActivities(consdata);
3569  consdata->cliquesadded = FALSE;
3570  consdata->implsadded = FALSE;
3571 
3572  return SCIP_OKAY;
3573 }
3574 
3575 /* perform deletion of variables in all constraints of the constraint handler */
3576 static
3578  SCIP* scip, /**< SCIP data structure */
3579  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
3580  SCIP_CONS** conss, /**< array of constraints */
3581  int nconss /**< number of constraints */
3582  )
3583 {
3584  SCIP_CONSDATA* consdata;
3585  int i;
3586  int v;
3587 
3588  assert(scip != NULL);
3589  assert(conshdlr != NULL);
3590  assert(conss != NULL);
3591  assert(nconss >= 0);
3592  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
3593 
3594  /* iterate over all constraints */
3595  for( i = 0; i < nconss; i++ )
3596  {
3597  consdata = SCIPconsGetData(conss[i]);
3598 
3599  /* constraint is marked, that some of its variables were deleted */
3600  if( consdata->varsdeleted )
3601  {
3602  /* iterate over all variables of the constraint and delete them from the constraint */
3603  for( v = consdata->nvars - 1; v >= 0; --v )
3604  {
3605  if( SCIPvarIsDeleted(consdata->vars[v]) )
3606  {
3607  SCIP_CALL( delCoefPos(scip, conss[i], v) );
3608  }
3609  }
3610  consdata->varsdeleted = FALSE;
3611  }
3612  }
3613 
3614  return SCIP_OKAY;
3615 }
3616 
3617 
3618 /** normalizes a linear constraint with the following rules:
3619  * - if all coefficients have them same absolute value, change them to (-)1.0
3620  * - multiplication with +1 or -1:
3621  * Apply the following rules in the given order, until the sign of the factor is determined. Later rules only apply,
3622  * if the current rule doesn't determine the sign):
3623  * 1. the right hand side must not be negative
3624  * 2. the right hand side must not be infinite
3625  * 3. the absolute value of the right hand side must be greater than that of the left hand side
3626  * 4. the number of positive coefficients must not be smaller than the number of negative coefficients
3627  * 5. multiply with +1
3628  * - rationals to integrals
3629  * Try to identify a rational representation of the fractional coefficients, and multiply all coefficients
3630  * by the smallest common multiple of all denominators to get integral coefficients.
3631  * Forbid large denominators due to numerical stability.
3632  * - division by greatest common divisor
3633  * If all coefficients are integral, divide them by the greatest common divisor.
3634  */
3635 static
3637  SCIP* scip, /**< SCIP data structure */
3638  SCIP_CONS* cons /**< linear constraint to normalize */
3639  )
3640 {
3641  SCIP_CONSDATA* consdata;
3642  SCIP_VAR** vars;
3643  SCIP_Real* vals;
3644  SCIP_Longint scm;
3645  SCIP_Longint nominator;
3646  SCIP_Longint denominator;
3647  SCIP_Longint gcd;
3648  SCIP_Longint maxmult;
3649  SCIP_Real epsilon;
3650  SCIP_Real feastol;
3651  SCIP_Real maxabsval;
3652  SCIP_Bool success;
3653  SCIP_Bool onlyintegral;
3654  int nvars;
3655  int mult;
3656  int nposcoeffs;
3657  int nnegcoeffs;
3658  int i;
3659  int v;
3660 
3661  assert(scip != NULL);
3662  assert(cons != NULL);
3663 
3664  /* we must not change a modifiable constraint in any way */
3665  if( SCIPconsIsModifiable(cons) )
3666  return SCIP_OKAY;
3667 
3668  /* get constraint data */
3669  consdata = SCIPconsGetData(cons);
3670  assert(consdata != NULL);
3671 
3672  /* check, if the constraint is already normalized */
3673  if( consdata->normalized )
3674  return SCIP_OKAY;
3675 
3676  /* get coefficient arrays */
3677  vals = consdata->vals;
3678  nvars = consdata->nvars;
3679  vars = consdata->vars;
3680  assert(nvars == 0 || vars != NULL);
3681  assert(nvars == 0 || vals != NULL);
3682 
3683  if( nvars == 0 )
3684  {
3685  consdata->normalized = TRUE;
3686  return SCIP_OKAY;
3687  }
3688 
3689  assert(vars != NULL);
3690  assert(vals != NULL);
3691 
3692  /* get maximal absolute coefficient */
3693  maxabsval = consdataGetMaxAbsval(consdata);
3694 
3695  /* check if all coefficients are in absolute value equal, and not 1.0 */
3696  if( !SCIPisEQ(scip, maxabsval, 1.0) )
3697  {
3698  SCIP_Bool abscoefsequ;
3699 
3700  abscoefsequ = TRUE;
3701 
3702  for( v = nvars - 1; v >= 0; --v )
3703  {
3704  if( !SCIPisEQ(scip, REALABS(vals[v]), maxabsval) )
3705  {
3706  abscoefsequ = FALSE;
3707  break;
3708  }
3709  }
3710 
3711  /* all coefficients are in absolute value equal, so change them to (-)1.0 */
3712  if( abscoefsequ )
3713  {
3714  SCIPdebugMessage("divide linear constraint with %g, because all coefficents are in absolute value the same\n", maxabsval);
3715  SCIPdebugPrintCons(scip, cons, NULL);
3716  SCIP_CALL( scaleCons(scip, cons, 1/maxabsval) );
3717 
3718  if( consdata->validmaxabsval )
3719  {
3720  if( !SCIPisEQ(scip, consdata->maxabsval, 1.0) )
3721  consdata->maxabsval = 1.0;
3722 
3723  maxabsval = 1.0;
3724  }
3725  else
3726  {
3727  /* get maximal absolute coefficient */
3728  maxabsval = consdataGetMaxAbsval(consdata);
3729  }
3730 
3731  /* get new consdata information, because scalecons() might have deleted variables */
3732  vals = consdata->vals;
3733  nvars = consdata->nvars;
3734  vars = consdata->vars;
3735 
3736  assert(nvars == 0 || vars != NULL);
3737  assert(nvars == 0 || vals != NULL);
3738  }
3739  }
3740 
3741  /* nvars might have changed */
3742  if( nvars == 0 )
3743  {
3744  consdata->normalized = TRUE;
3745  return SCIP_OKAY;
3746  }
3747 
3748  assert(vars != NULL);
3749  assert(vals != NULL);
3750 
3751  /* calculate the maximal multiplier for common divisor calculation:
3752  * |p/q - val| < epsilon and q < feastol/epsilon => |p - q*val| < feastol
3753  * which means, a value of feastol/epsilon should be used as maximal multiplier;
3754  * additionally, we don't want to scale the constraint if this would lead to too
3755  * large coefficients
3756  */
3757  epsilon = SCIPepsilon(scip) * 0.9; /* slightly decrease epsilon to be safe in rational conversion below */
3758  feastol = SCIPfeastol(scip);
3759  maxmult = (SCIP_Longint)(feastol/epsilon + feastol);
3760  maxmult = MIN(maxmult, (SCIP_Longint)( MAXSCALEDCOEF/MAX(maxabsval, 1.0)));
3761 
3762  /* if all variables are of integral type we will allow a greater multiplier */
3763  if( consdata->sorted )
3764  {
3765  if( SCIPvarGetType(vars[nvars - 1]) != SCIP_VARTYPE_CONTINUOUS )
3766  {
3767  maxmult = (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0)));
3768  }
3769  }
3770  else
3771  {
3772  SCIP_Bool foundcont;
3773 
3774  foundcont = FALSE;
3775 
3776  for( v = nvars - 1; v >= 0; --v )
3777  {
3778  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
3779  {
3780  foundcont = TRUE;
3781  break;
3782  }
3783  }
3784 
3785  if( !foundcont )
3786  {
3787  maxmult = (SCIP_Longint) (MAXSCALEDCOEFINTEGER/(MAX(maxabsval, 1.0)));
3788  }
3789  }
3790 
3791  /*
3792  * multiplication with +1 or -1
3793  */
3794  mult = 0;
3795 
3796  /* 1. the right hand side must not be negative */
3797  if( SCIPisPositive(scip, consdata->lhs) )
3798  mult = +1;
3799  else if( SCIPisNegative(scip, consdata->rhs) )
3800  mult = -1;
3801 
3802  if( mult == 0 )
3803  {
3804  /* 2. the right hand side must not be infinite */
3805  if( SCIPisInfinity(scip, -consdata->lhs) )
3806  mult = +1;
3807  else if( SCIPisInfinity(scip, consdata->rhs) )
3808  mult = -1;
3809  }
3810 
3811  if( mult == 0 )
3812  {
3813  /* 3. the absolute value of the right hand side must be greater than that of the left hand side */
3814  if( SCIPisGT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
3815  mult = +1;
3816  else if( SCIPisLT(scip, REALABS(consdata->rhs), REALABS(consdata->lhs)) )
3817  mult = -1;
3818  }
3819 
3820  if( mult == 0 )
3821  {
3822  /* 4. the number of positive coefficients must not be smaller than the number of negative coefficients */
3823  nposcoeffs = 0;
3824  nnegcoeffs = 0;
3825  for( i = 0; i < nvars; ++i )
3826  {
3827  if( vals[i] > 0.0 )
3828  nposcoeffs++;
3829  else
3830  nnegcoeffs++;
3831  }
3832  if( nposcoeffs > nnegcoeffs )
3833  mult = +1;
3834  else if( nposcoeffs < nnegcoeffs )
3835  mult = -1;
3836  }
3837 
3838  if( mult == 0 )
3839  {
3840  /* 5. multiply with +1 */
3841  mult = +1;
3842  }
3843 
3844  assert(mult == +1 || mult == -1);
3845  if( mult == -1 )
3846  {
3847  /* scale the constraint with -1 */
3848  SCIPdebugMessage("multiply linear constraint with -1.0\n");
3849  SCIPdebugPrintCons(scip, cons, NULL);
3850  SCIP_CALL( scaleCons(scip, cons, -1.0) );
3851 
3852  /* scalecons() can delete variables, but scaling with -1 should not do that */
3853  assert(nvars == consdata->nvars);
3854  }
3855 
3856  /*
3857  * rationals to integrals
3858  *
3859  * @todo try scaling only on behalf of non-continuous variables
3860  */
3861  success = TRUE;
3862  scm = 1;
3863  for( i = 0; i < nvars && success && scm <= maxmult; ++i )
3864  {
3865  if( !SCIPisIntegral(scip, vals[i]) )
3866  {
3867  /* epsilon has been slightly decreased above - to be on the safe side */
3868  success = SCIPrealToRational(vals[i], -epsilon, epsilon , maxmult, &nominator, &denominator);
3869  if( success )
3870  scm = SCIPcalcSmaComMul(scm, denominator);
3871  }
3872  }
3873  assert(scm >= 1);
3874 
3875  /* it might be that we have really big coefficients, but all are integral, in that case we want to divide them by
3876  * their greatest common divisor
3877  */
3878  onlyintegral = TRUE;
3879  if( scm == 1 )
3880  {
3881  for( i = nvars - 1; i >= 0; --i )
3882  {
3883  if( !SCIPisIntegral(scip, vals[i]) )
3884  {
3885  onlyintegral = FALSE;
3886  break;
3887  }
3888  }
3889  }
3890 
3891  success = success && (scm <= maxmult || (scm == 1 && onlyintegral));
3892  if( success && scm != 1 )
3893  {
3894  /* scale the constraint with the smallest common multiple of all denominators */
3895  SCIPdebugMessage("scale linear constraint with %"SCIP_LONGINT_FORMAT" to make coefficients integral\n", scm);
3896  SCIPdebugPrintCons(scip, cons, NULL);
3897  SCIP_CALL( scaleCons(scip, cons, (SCIP_Real)scm) );
3898 
3899  if( consdata->validmaxabsval )
3900  {
3901  consdata->maxabsval *= REALABS((SCIP_Real)scm);
3902  if( !SCIPisIntegral(scip, consdata->maxabsval) )
3903  {
3904  consdata->validmaxabsval = FALSE;
3905  consdata->maxabsval = SCIP_INVALID;
3906  consdataCalcMaxAbsval(consdata);
3907  }
3908  }
3909 
3910  /* get new consdata information, because scalecons() might have deleted variables */
3911  vals = consdata->vals;
3912  nvars = consdata->nvars;
3913  assert(nvars == 0 || vals != NULL);
3914  }
3915 
3916  /*
3917  * division by greatest common divisor
3918  */
3919  if( success && nvars >= 1 )
3920  {
3921  /* all coefficients are integral: divide them by their greatest common divisor */
3922  assert(SCIPisIntegral(scip, vals[0]));
3923  gcd = (SCIP_Longint)(REALABS(vals[0]) + feastol);
3924  assert(gcd >= 1);
3925  for( i = 1; i < nvars && gcd > 1; ++i )
3926  {
3927  assert(SCIPisIntegral(scip, vals[i]));
3928  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[i]) + feastol));
3929  }
3930 
3931  if( gcd > 1 )
3932  {
3933  /* divide the constraint by the greatest common divisor of the coefficients */
3934  SCIPdebugMessage("divide linear constraint by greatest common divisor %"SCIP_LONGINT_FORMAT"\n", gcd);
3935  SCIPdebugPrintCons(scip, cons, NULL);
3936  SCIP_CALL( scaleCons(scip, cons, 1.0/(SCIP_Real)gcd) );
3937 
3938  if( consdata->validmaxabsval )
3939  {
3940  consdata->maxabsval /= REALABS((SCIP_Real)gcd);
3941  }
3942  }
3943  }
3944 
3945  /* mark constraint to be normalized */
3946  consdata->normalized = TRUE;
3947 
3948  SCIPdebugMessage("normalized constraint:\n");
3949  SCIPdebugPrintCons(scip, cons, NULL);
3950 
3951  return SCIP_OKAY;
3952 }
3953 
3954 /** replaces multiple occurrences of a variable by a single coefficient */
3955 static
3957  SCIP* scip, /**< SCIP data structure */
3958  SCIP_CONS* cons /**< linear constraint */
3959  )
3960 {
3961  SCIP_CONSDATA* consdata;
3962  SCIP_VAR* var;
3963  SCIP_Real valsum;
3964  int v;
3965 
3966  assert(scip != NULL);
3967  assert(cons != NULL);
3968 
3969  consdata = SCIPconsGetData(cons);
3970  assert(consdata != NULL);
3971 
3972  if( consdata->merged )
3973  return SCIP_OKAY;
3974 
3975  /* sort the constraint */
3976  SCIP_CALL( consdataSort(scip, consdata) );
3977 
3978  /* go backwards through the constraint looking for multiple occurrences of the same variable;
3979  * backward direction is necessary, since delCoefPos() modifies the given position and
3980  * the subsequent ones
3981  */
3982  v = consdata->nvars-1;
3983  while( v >= 1 )
3984  {
3985  var = consdata->vars[v];
3986  if( consdata->vars[v-1] == var )
3987  {
3988  valsum = consdata->vals[v];
3989  do
3990  {
3991  SCIP_CALL( delCoefPos(scip, cons, v) );
3992  --v;
3993  valsum += consdata->vals[v];
3994  }
3995  while( v >= 1 && consdata->vars[v-1] == var );
3996 
3997  /* modify the last existing occurrence of the variable */
3998  assert(consdata->vars[v] == var);
3999  if( SCIPisZero(scip, valsum) )
4000  {
4001  SCIP_CALL( delCoefPos(scip, cons, v) );
4002  }
4003  else
4004  {
4005  SCIP_CALL( chgCoefPos(scip, cons, v, valsum) );
4006 
4007  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
4008  consdata->maxactdelta = SCIP_INVALID;
4009  }
4010  }
4011  --v;
4012  }
4013 
4014  consdata->merged = TRUE;
4015 
4016  return SCIP_OKAY;
4017 }
4018 
4019 /** replaces all fixed and aggregated variables by their non-fixed counterparts */
4020 static
4022  SCIP* scip, /**< SCIP data structure */
4023  SCIP_CONS* cons, /**< linear constraint */
4024  SCIP_Bool* infeasible /**< pointer to store if infeasibility is detected; or NULL if this
4025  * information is not needed; in this case, we apply all fixings
4026  * instead of stopping after the first infeasible one */
4027  )
4028 {
4029  SCIP_CONSDATA* consdata;
4030  SCIP_VAR* var;
4031  SCIP_VAR** aggrvars;
4032  SCIP_Real val;
4033  SCIP_Real* aggrscalars;
4034  SCIP_Real fixedval;
4035  SCIP_Real aggrconst;
4036  int v;
4037  int naggrvars;
4038  int i;
4039 
4040  assert(scip != NULL);
4041  assert(cons != NULL);
4042 
4043  if( infeasible != NULL )
4044  *infeasible = FALSE;
4045 
4046  consdata = SCIPconsGetData(cons);
4047  assert(consdata != NULL);
4048 
4049  if( !consdata->removedfixings )
4050  {
4051  SCIP_Real lhssubtrahend;
4052  SCIP_Real rhssubtrahend;
4053 
4054  lhssubtrahend = 0.0;
4055  rhssubtrahend = 0.0;
4056 
4057  SCIPdebugMessage("applying fixings:\n");
4058  SCIPdebugPrintCons(scip, cons, NULL);
4059 
4060  v = 0;
4061  while( v < consdata->nvars )
4062  {
4063  var = consdata->vars[v];
4064  val = consdata->vals[v];
4065  assert(SCIPvarIsTransformed(var));
4066 
4067  switch( SCIPvarGetStatus(var) )
4068  {
4070  SCIPerrorMessage("original variable in transformed linear constraint\n");
4071  return SCIP_INVALIDDATA;
4072 
4073  case SCIP_VARSTATUS_LOOSE:
4074  case SCIP_VARSTATUS_COLUMN:
4075  ++v;
4076  break;
4077 
4078  case SCIP_VARSTATUS_FIXED:
4079  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal(var), SCIPvarGetUbGlobal(var)));
4080  fixedval = SCIPvarGetLbGlobal(var);
4081  if( !SCIPisInfinity(scip, -consdata->lhs) )
4082  {
4083  if( SCIPisInfinity(scip, ABS(fixedval)) )
4084  {
4085  if( val * fixedval > 0.0 )
4086  {
4087  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
4088  }
4089  else
4090  {
4091  if( infeasible != NULL )
4092  {
4093  /* if lhs gets infinity it means that the problem is infeasible */
4094  *infeasible = TRUE;
4095  return SCIP_OKAY;
4096  }
4097  else
4098  {
4099  SCIP_CALL( chgLhs(scip, cons, SCIPinfinity(scip)) );
4100  }
4101  }
4102  }
4103  else
4104  lhssubtrahend += val * fixedval;
4105  }
4106  if( !SCIPisInfinity(scip, consdata->rhs) )
4107  {
4108  if( SCIPisInfinity(scip, ABS(fixedval)) )
4109  {
4110  if( val * fixedval > 0.0 )
4111  {
4112  if( infeasible != NULL )
4113  {
4114  /* if rhs gets -infinity it means that the problem is infeasible */
4115  *infeasible = TRUE;
4116  return SCIP_OKAY;
4117  }
4118  else
4119  {
4120  SCIP_CALL( chgRhs(scip, cons, -SCIPinfinity(scip)) );
4121  }
4122  }
4123  else
4124  {
4125  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
4126  }
4127  }
4128  else
4129  rhssubtrahend += val * fixedval;
4130  }
4131  SCIP_CALL( delCoefPos(scip, cons, v) );
4132  break;
4133 
4135  {
4136  SCIP_VAR* activevar = SCIPvarGetAggrVar(var);
4137  SCIP_Real activescalar = val * SCIPvarGetAggrScalar(var);
4138  SCIP_Real activeconstant = val * SCIPvarGetAggrConstant(var);
4139 
4140  assert(activevar != NULL);
4141  SCIP_CALL( SCIPgetProbvarSum(scip, &activevar, &activescalar, &activeconstant) );
4142  assert(activevar != NULL);
4143 
4144  if( !SCIPisZero(scip, activescalar) )
4145  {
4146  SCIP_CALL( addCoef(scip, cons, activevar, activescalar) );
4147  }
4148 
4149  if( !SCIPisZero(scip, activeconstant) )
4150  {
4151  if( !SCIPisInfinity(scip, -consdata->lhs) )
4152  lhssubtrahend += activeconstant;
4153  if( !SCIPisInfinity(scip, consdata->rhs) )
4154  rhssubtrahend += activeconstant;
4155  }
4156 
4157  SCIP_CALL( delCoefPos(scip, cons, v) );
4158  break;
4159  }
4162  naggrvars = SCIPvarGetMultaggrNVars(var);
4163  aggrvars = SCIPvarGetMultaggrVars(var);
4164  aggrscalars = SCIPvarGetMultaggrScalars(var);
4165  for( i = 0; i < naggrvars; ++i )
4166  {
4167  SCIP_CALL( addCoef(scip, cons, aggrvars[i], val * aggrscalars[i]) );
4168  }
4169  aggrconst = SCIPvarGetMultaggrConstant(var);
4170 
4171  if( !SCIPisInfinity(scip, -consdata->lhs) )
4172  lhssubtrahend += val * aggrconst;
4173  if( !SCIPisInfinity(scip, consdata->rhs) )
4174  rhssubtrahend += val * aggrconst;
4175 
4176  SCIP_CALL( delCoefPos(scip, cons, v) );
4177  break;
4178 
4180  SCIP_CALL( addCoef(scip, cons, SCIPvarGetNegationVar(var), -val) );
4181  aggrconst = SCIPvarGetNegationConstant(var);
4182 
4183  if( !SCIPisInfinity(scip, -consdata->lhs) )
4184  lhssubtrahend += val * aggrconst;
4185  if( !SCIPisInfinity(scip, consdata->rhs) )
4186  rhssubtrahend += val * aggrconst;
4187 
4188  SCIP_CALL( delCoefPos(scip, cons, v) );
4189  break;
4190 
4191  default:
4192  SCIPerrorMessage("unknown variable status\n");
4193  SCIPABORT();
4194  return SCIP_INVALIDDATA; /*lint !e527*/
4195  }
4196  }
4197 
4198  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisInfinity(scip, consdata->lhs) )
4199  {
4200  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4201  * causing wrong fixings of other variables --> better use a real zero here;
4202  * for small numbers, polishing the difference might lead to wrong results -->
4203  * better use the exact difference in this case
4204  */
4205  if( SCIPisEQ(scip, lhssubtrahend, consdata->lhs) && SCIPisFeasGE(scip, REALABS(lhssubtrahend), 1.0) )
4206  {
4207  SCIP_CALL( chgLhs(scip, cons, 0.0) );
4208  }
4209  else
4210  {
4211  SCIP_CALL( chgLhs(scip, cons, consdata->lhs - lhssubtrahend) );
4212  }
4213  }
4214  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisInfinity(scip, -consdata->rhs))
4215  {
4216 
4217  /* for large numbers that are relatively equal, substraction can lead to cancellation,
4218  * causing wrong fixings of other variables --> better use a real zero here;
4219  * for small numbers, polishing the difference might lead to wrong results -->
4220  * better use the exact difference in this case
4221  */
4222  if( SCIPisEQ(scip, rhssubtrahend, consdata->rhs ) && SCIPisFeasGE(scip, REALABS(rhssubtrahend), 1.0) )
4223  {
4224  SCIP_CALL( chgRhs(scip, cons, 0.0) );
4225  }
4226  else
4227  {
4228  SCIP_CALL( chgRhs(scip, cons, consdata->rhs - rhssubtrahend) );
4229  }
4230  }
4231 
4232  consdata->removedfixings = TRUE;
4233 
4234  SCIPdebugMessage("after fixings:\n");
4235  SCIPdebugPrintCons(scip, cons, NULL);
4236 
4237  /* if aggregated variables have been replaced, multiple entries of the same variable are possible and we have
4238  * to clean up the constraint
4239  */
4240  SCIP_CALL( mergeMultiples(scip, cons) );
4241 
4242  SCIPdebugMessage("after merging:\n");
4243  SCIPdebugPrintCons(scip, cons, NULL);
4244  }
4245  assert(consdata->removedfixings);
4246 
4247 #ifndef NDEBUG
4248  /* check, if all fixings are applied */
4249  for( v = 0; v < consdata->nvars; ++v )
4250  assert(SCIPvarIsActive(consdata->vars[v]));
4251 #endif
4252 
4253  return SCIP_OKAY;
4254 }
4255 
4256 /** for each variable in the linear constraint, except the inferred variable, adds one bound to the conflict analysis'
4257  * candidate store (bound depends on sign of coefficient and whether the left or right hand side was the reason for the
4258  * inference variable's bound change); the conflict analysis can be initialized with the linear constraint being the
4259  * conflict detecting constraint by using NULL as inferred variable
4260  */
4261 static
4263  SCIP* scip, /**< SCIP data structure */
4264  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4265  SCIP_VAR* infervar, /**< variable that was deduced, or NULL */
4266  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4267  int inferpos, /**< position of the inferred variable in the vars array */
4268  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the bound change? */
4269  )
4270 {
4271  SCIP_CONSDATA* consdata;
4272  SCIP_VAR** vars;
4273  SCIP_Real* vals;
4274  int nvars;
4275  int i;
4276 
4277  assert(scip != NULL);
4278  assert(cons != NULL);
4279 
4280  consdata = SCIPconsGetData(cons);
4281  assert(consdata != NULL);
4282  vars = consdata->vars;
4283  vals = consdata->vals;
4284  nvars = consdata->nvars;
4285  assert(vars != NULL || nvars == 0);
4286  assert(vals != NULL || nvars == 0);
4287  assert(-1 <= inferpos && inferpos < nvars);
4288  assert((infervar == NULL) == (inferpos == -1));
4289  assert(inferpos == -1 || vars[inferpos] == infervar); /*lint !e613*/
4290 
4291  /* for each variable, add the bound to the conflict queue, that is responsible for the minimal or maximal
4292  * residual value, depending on whether the left or right hand side is responsible for the bound change:
4293  * - if the right hand side is the reason, the minimal residual activity is responsible
4294  * - if the left hand side is the reason, the maximal residual activity is responsible
4295  */
4296 
4297  /* if the variable is integral we only need to add reason bounds until the propagation could be applied */
4298  if( infervar == NULL || SCIPvarIsIntegral(infervar) )
4299  {
4300  SCIP_Real minresactivity;
4301  SCIP_Real maxresactivity;
4302  SCIP_Bool minisrelax;
4303  SCIP_Bool maxisrelax;
4304  SCIP_Bool isminsettoinfinity;
4305  SCIP_Bool ismaxsettoinfinity;
4306 
4307  minresactivity = -SCIPinfinity(scip);
4308  maxresactivity = SCIPinfinity(scip);
4309 
4310  /* calculate the minimal and maximal global activity of all other variables involved in the constraint */
4311  if( infervar != NULL )
4312  {
4313  assert(vals != NULL); /* for flexelint */
4314  if( reasonisrhs )
4315  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, &minresactivity, NULL,
4316  &minisrelax, NULL, &isminsettoinfinity, NULL);
4317  else
4318  consdataGetGlbActivityResiduals(scip, consdata, infervar, vals[inferpos], FALSE, NULL, &maxresactivity,
4319  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4320  }
4321  else
4322  {
4323  if( reasonisrhs )
4324  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minresactivity, NULL,
4325  &minisrelax, NULL, &isminsettoinfinity, NULL);
4326  else
4327  consdataGetGlbActivityBounds(scip, consdata, FALSE, NULL, &maxresactivity,
4328  NULL, &maxisrelax, NULL, &ismaxsettoinfinity);
4329  }
4330 
4331  /* we can only do something clever, if the residual activity is finite and not relaxed */
4332  if( (reasonisrhs && !isminsettoinfinity && !minisrelax) || (!reasonisrhs && !ismaxsettoinfinity && !maxisrelax) ) /*lint !e644*/
4333  {
4334  SCIP_Real rescap;
4335  SCIP_Bool resactisinf;
4336 
4337  resactisinf = FALSE;
4338 
4339  /* calculate the residual capacity that would be left, if the variable would be set to one more / one less
4340  * than its inferred bound
4341  */
4342  if( infervar != NULL )
4343  {
4344  assert(vals != NULL); /* for flexelint */
4345 
4346  if( reasonisrhs )
4347  {
4348  if( SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
4349  {
4350  consdataGetReliableResidualActivity(scip, consdata, infervar, &minresactivity, TRUE, TRUE);
4351  if( SCIPisInfinity(scip, -minresactivity) )
4352  resactisinf = TRUE;
4353  }
4354  rescap = consdata->rhs - minresactivity;
4355  }
4356  else
4357  {
4358  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
4359  {
4360  consdataGetReliableResidualActivity(scip, consdata, infervar, &maxresactivity, FALSE, TRUE);
4361  if( SCIPisInfinity(scip, maxresactivity) )
4362  resactisinf = TRUE;
4363  }
4364  rescap = consdata->lhs - maxresactivity;
4365  }
4366 
4367  if( reasonisrhs == (vals[inferpos] > 0.0) )
4368  rescap -= vals[inferpos] * (SCIPvarGetUbAtIndex(infervar, bdchgidx, TRUE) + 1.0);
4369  else
4370  rescap -= vals[inferpos] * (SCIPvarGetLbAtIndex(infervar, bdchgidx, TRUE) - 1.0);
4371  }
4372  else
4373  rescap = (reasonisrhs ? consdata->rhs - minresactivity : consdata->lhs - maxresactivity);
4374 
4375  if( !resactisinf )
4376  {
4377  /* now add bounds as reasons until the residual capacity is exceeded */
4378  for( i = 0; i < nvars; ++i )
4379  {
4380  assert(vars != NULL); /* for flexelint */
4381  assert(vals != NULL); /* for flexelint */
4382 
4383  /* zero coefficients and the infered variable can be ignored */
4384  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4385  continue;
4386 
4387  /* check if the residual capacity is exceeded */
4388  if( (reasonisrhs && SCIPisFeasNegative(scip, rescap))
4389  || (!reasonisrhs && SCIPisFeasPositive(scip, rescap)) )
4390  break;
4391 
4392  /* update the residual capacity due to the local bound of this variable */
4393  if( reasonisrhs == (vals[i] > 0.0) )
4394  {
4395  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound */
4396  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4397  rescap -= vals[i] * (SCIPvarGetLbAtIndex(vars[i], bdchgidx, FALSE) - SCIPvarGetLbGlobal(vars[i]));
4398  }
4399  else
4400  {
4401  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound */
4402  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4403  rescap -= vals[i] * (SCIPvarGetUbAtIndex(vars[i], bdchgidx, FALSE) - SCIPvarGetUbGlobal(vars[i]));
4404  }
4405  }
4406  return SCIP_OKAY;
4407  }
4408  }
4409  }
4410 
4411  /* for a bound change on a continuous variable, all locally changed bounds are responsible */
4412  for( i = 0; i < nvars; ++i )
4413  {
4414  assert(vars != NULL); /* for flexelint */
4415  assert(vals != NULL); /* for flexelint */
4416 
4417  /* zero coefficients and the infered variable can be ignored */
4418  if( vars[i] == infervar || SCIPisZero(scip, vals[i]) )
4419  continue;
4420 
4421  if( reasonisrhs == (vals[i] > 0.0) )
4422  {
4423  /* rhs is reason and coeff is positive, or lhs is reason and coeff is negative -> lower bound is responsible */
4424  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
4425  }
4426  else
4427  {
4428  /* lhs is reason and coeff is positive, or rhs is reason and coeff is negative -> upper bound is responsible */
4429  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
4430  }
4431  }
4432 
4433  return SCIP_OKAY;
4434 }
4435 
4436 /** resolves a propagation on the given variable by supplying the variables needed for applying the corresponding
4437  * propagation rule (see propagateCons()):
4438  * (1) activity residuals of all other variables tighten bounds of single variable
4439  */
4440 static
4442  SCIP* scip, /**< SCIP data structure */
4443  SCIP_CONS* cons, /**< constraint that inferred the bound change */
4444  SCIP_VAR* infervar, /**< variable that was deduced */
4445  INFERINFO inferinfo, /**< inference information */
4446  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
4447  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
4448  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
4449  )
4450 {
4451  SCIP_CONSDATA* consdata;
4452  SCIP_VAR** vars;
4453 #ifndef NDEBUG
4454  SCIP_Real* vals;
4455 #endif
4456  int nvars;
4457  int inferpos;
4458 
4459  assert(scip != NULL);
4460  assert(cons != NULL);
4461  assert(result != NULL);
4462 
4463  consdata = SCIPconsGetData(cons);
4464  assert(consdata != NULL);
4465  vars = consdata->vars;
4466  nvars = consdata->nvars;
4467 #ifndef NDEBUG
4468  vals = consdata->vals;
4469  assert(vars != NULL);
4470  assert(vals != NULL);
4471 #endif
4472 
4473  /* get the position of the inferred variable in the vars array */
4474  inferpos = inferInfoGetPos(inferinfo);
4475  if( inferpos >= nvars || vars[inferpos] != infervar )
4476  {
4477  /* find inference variable in constraint */
4478  /**@todo use a binary search here; the variables can be sorted by variable index */
4479  for( inferpos = 0; inferpos < nvars && vars[inferpos] != infervar; ++inferpos )
4480  {}
4481  }
4482  assert(inferpos < nvars);
4483  assert(vars[inferpos] == infervar);
4484  assert(!SCIPisZero(scip, vals[inferpos]));
4485 
4486  switch( inferInfoGetProprule(inferinfo) )
4487  {
4488  case PROPRULE_1_RHS:
4489  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
4490  * constraint (only taking the other variables into account) didn't leave enough space for a larger
4491  * domain in order to not exceed the right hand side of the inequality
4492  */
4493  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_UPPER));
4494  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, TRUE) );
4495  *result = SCIP_SUCCESS;
4496  break;
4497 
4498  case PROPRULE_1_LHS:
4499  /* the bound of the variable was tightened, because the minimal or maximal residual activity of the linear
4500  * constraint (only taking the other variables into account) didn't leave enough space for a larger
4501  * domain in order to not fall below the left hand side of the inequality
4502  */
4503  assert((vals[inferpos] > 0.0) == (boundtype == SCIP_BOUNDTYPE_LOWER));
4504  SCIP_CALL( addConflictBounds(scip, cons, infervar, bdchgidx, inferpos, FALSE) );
4505  *result = SCIP_SUCCESS;
4506  break;
4507 
4508  case PROPRULE_INVALID:
4509  default:
4510  SCIPerrorMessage("invalid inference information %d in linear constraint <%s> at position %d for %s bound of variable <%s>\n",
4511  inferInfoGetProprule(inferinfo), SCIPconsGetName(cons), inferInfoGetPos(inferinfo),
4512  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", SCIPvarGetName(infervar));
4513  SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
4514  SCIPinfoMessage(scip, NULL, ";\n");
4515  return SCIP_INVALIDDATA;
4516  }
4517 
4518  return SCIP_OKAY;
4519 }
4520 
4521 /** analyzes conflicting bounds on given constraint, and adds conflict constraint to problem */
4522 static
4524  SCIP* scip, /**< SCIP data structure */
4525  SCIP_CONS* cons, /**< conflict detecting constraint */
4526  SCIP_Bool reasonisrhs /**< is the right hand side responsible for the conflict? */
4527  )
4528 {
4529  /* conflict analysis can only be applied in solving stage and if it is turned on */
4531  return SCIP_OKAY;
4532 
4533  /* initialize conflict analysis */
4535 
4536  /* add the conflicting bound for each variable of infeasible constraint to conflict candidate queue */
4537  SCIP_CALL( addConflictBounds(scip, cons, NULL, NULL, -1, reasonisrhs) );
4538 
4539  /* analyze the conflict */
4540  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
4541 
4542  return SCIP_OKAY;
4543 }
4544 
4545 /** check if there is any hope of tightening some bounds */
4546 static
4548  SCIP* scip, /**< SCIP data structure */
4549  SCIP_CONS* cons /**< linear constraint */
4550  )
4551 {
4552  SCIP_CONSDATA* consdata;
4553  int infcountmin;
4554  int infcountmax;
4555 
4556  consdata = SCIPconsGetData(cons);
4557  assert(consdata != NULL);
4558 
4559  infcountmin = consdata->minactivityneginf
4560  + consdata->minactivityposinf
4561  + consdata->minactivityneghuge
4562  + consdata->minactivityposhuge;
4563  infcountmax = consdata->maxactivityneginf
4564  + consdata->maxactivityposinf
4565  + consdata->maxactivityneghuge
4566  + consdata->maxactivityposhuge;
4567 
4568  if( infcountmin > 1 && infcountmax > 1 )
4569  return FALSE;
4570 
4571  return TRUE;
4572 }
4573 
4574 /** tighten upper bound */
4575 static
4577  SCIP* scip, /**< SCIP data structure */
4578  SCIP_CONS* cons, /**< linear constraint */
4579  int pos, /**< variable position */
4580  PROPRULE proprule, /**< propagation rule that deduced the value */
4581  SCIP_Real newub, /**< new upper bound */
4582  SCIP_Real oldub, /**< old upper bound */
4583  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4584  int* nchgbds, /**< pointer to count the total number of tightened bounds */
4585  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
4586  )
4587 {
4588  SCIP_CONSDATA* consdata;
4589  SCIP_VAR* var;
4590  SCIP_Real lb;
4591  SCIP_Bool infeasible;
4592  SCIP_Bool tightened;
4593 
4594  assert(cons != NULL);
4595  assert(!SCIPisInfinity(scip, newub));
4596 
4597  consdata = SCIPconsGetData(cons);
4598  assert(consdata != NULL);
4599  var = consdata->vars[pos];
4600  assert(var != NULL);
4601 
4602  lb = SCIPvarGetLbLocal(var);
4603  newub = SCIPadjustedVarUb(scip, var, newub);
4604 
4605  if( force || SCIPisUbBetter(scip, newub, lb, oldub) )
4606  {
4607  SCIP_VARTYPE vartype;
4608 
4609  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
4610  SCIPconsGetName(cons), SCIPvarGetName(var), lb, oldub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newub);
4611 
4612  vartype = SCIPvarGetType(var);
4613 
4614  /* tighten upper bound */
4615  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
4616 
4617  if( infeasible )
4618  {
4619  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4620  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
4621 
4622  /* analyze conflict */
4623  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
4624 
4625  *cutoff = TRUE;
4626  }
4627  else if( tightened )
4628  {
4629  assert(SCIPisFeasLE(scip, SCIPvarGetUbLocal(var), oldub));
4630  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
4631  SCIPconsGetName(cons), SCIPvarGetName(var), lb, SCIPvarGetUbLocal(var));
4632 
4633  (*nchgbds)++;
4634 
4635  /* if variable type was changed we might be able to upgrade the constraint */
4636  if( vartype != SCIPvarGetType(var) )
4637  consdata->upgradetried = FALSE;
4638  }
4639  }
4640  return SCIP_OKAY;
4641 }
4642 
4643 /** tighten lower bound */
4644 static
4646  SCIP* scip, /**< SCIP data structure */
4647  SCIP_CONS* cons, /**< linear constraint */
4648  int pos, /**< variable position */
4649  PROPRULE proprule, /**< propagation rule that deduced the value */
4650  SCIP_Real newlb, /**< new lower bound */
4651  SCIP_Real oldlb, /**< old lower bound */
4652  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4653  int* nchgbds, /**< pointer to count the total number of tightened bounds */
4654  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
4655  )
4656 {
4657  SCIP_CONSDATA* consdata;
4658  SCIP_VAR* var;
4659  SCIP_Real ub;
4660  SCIP_Bool infeasible;
4661  SCIP_Bool tightened;
4662 
4663  assert(cons != NULL);
4664  assert(!SCIPisInfinity(scip, newlb));
4665 
4666  consdata = SCIPconsGetData(cons);
4667  assert(consdata != NULL);
4668  var = consdata->vars[pos];
4669  assert(var != NULL);
4670 
4671  ub = SCIPvarGetUbLocal(var);
4672  newlb = SCIPadjustedVarLb(scip, var, newlb);
4673 
4674  if( force || SCIPisLbBetter(scip, newlb, oldlb, ub) )
4675  {
4676  SCIP_VARTYPE vartype;
4677 
4678  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, activity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
4679  SCIPconsGetName(cons), SCIPvarGetName(var), oldlb, ub, consdata->vals[pos], consdata->minactivity, consdata->maxactivity, consdata->lhs, consdata->rhs, newlb);
4680 
4681  vartype = SCIPvarGetType(var);
4682 
4683  /* tighten lower bound */
4684  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(proprule, pos), force, &infeasible, &tightened) );
4685 
4686  if( infeasible )
4687  {
4688  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4689  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
4690 
4691  /* analyze conflict */
4692  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
4693 
4694  *cutoff = TRUE;
4695  }
4696  else if( tightened )
4697  {
4698  assert(SCIPisFeasGE(scip, SCIPvarGetLbLocal(var), oldlb));
4699  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
4700  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetLbLocal(var), ub);
4701 
4702  (*nchgbds)++;
4703 
4704  /* if variable type was changed we might be able to upgrade the constraint */
4705  if( vartype != SCIPvarGetType(var) )
4706  consdata->upgradetried = FALSE;
4707  }
4708  }
4709  return SCIP_OKAY;
4710 }
4711 
4712 /** tightens bounds of a single variable due to activity bounds (easy case) */
4713 static
4715  SCIP* scip, /**< SCIP data structure */
4716  SCIP_CONS* cons, /**< linear constraint */
4717  int pos, /**< position of the variable in the vars array */
4718  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4719  int* nchgbds, /**< pointer to count the total number of tightened bounds */
4720  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
4721  )
4722 {
4723  SCIP_CONSDATA* consdata;
4724  SCIP_VAR* var;
4725  SCIP_Real val;
4726  SCIP_Real lb;
4727  SCIP_Real ub;
4728  SCIP_Real lhs;
4729  SCIP_Real rhs;
4730 
4731  assert(scip != NULL);
4732  assert(cons != NULL);
4733  assert(cutoff != NULL);
4734  assert(nchgbds != NULL);
4735 
4736  /* we cannot tighten variables' bounds, if the constraint may be not complete */
4737  if( SCIPconsIsModifiable(cons) )
4738  return SCIP_OKAY;
4739 
4740  consdata = SCIPconsGetData(cons);
4741  assert(consdata != NULL);
4742  assert(0 <= pos && pos < consdata->nvars);
4743 
4744  *cutoff = FALSE;
4745 
4746  var = consdata->vars[pos];
4747  assert(var != NULL);
4748 
4749  /* we cannot tighten bounds of multi-aggregated variables */
4751  return SCIP_OKAY;
4752 
4753  val = consdata->vals[pos];
4754  lhs = consdata->lhs;
4755  rhs = consdata->rhs;
4756  assert(!SCIPisZero(scip, val));
4757  assert(!SCIPisInfinity(scip, lhs));
4758  assert(!SCIPisInfinity(scip, -rhs));
4759 
4760  lb = SCIPvarGetLbLocal(var);
4761  ub = SCIPvarGetUbLocal(var);
4762  assert(SCIPisLE(scip, lb, ub));
4763 
4764  /* recompute activities if needed */
4765  if( !consdata->validactivities )
4766  consdataCalcActivities(scip, consdata);
4767  assert(consdata->validactivities);
4768  if( !consdata->validminact )
4769  consdataRecomputeMinactivity(scip, consdata);
4770  assert(consdata->validminact);
4771  if( !consdata->validmaxact )
4772  consdataRecomputeMaxactivity(scip, consdata);
4773  assert(consdata->validmaxact);
4774 
4775  if( val > 0.0 )
4776  {
4777  /* check, if we can tighten the variable's upper bound */
4778  if( !SCIPisInfinity(scip, rhs) )
4779  {
4780  SCIP_Real slack;
4781  SCIP_Real alpha;
4782 
4783  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
4784  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
4785  {
4786  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
4787  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
4788 
4789  *cutoff = TRUE;
4790  return SCIP_OKAY;
4791  }
4792 
4793  slack = rhs - consdata->minactivity;
4794 
4795  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
4796  * it to zero
4797  */
4798  if( !SCIPisPositive(scip, slack) )
4799  slack = 0.0;
4800 
4801  alpha = val * (ub - lb);
4802  assert(!SCIPisNegative(scip, alpha));
4803 
4804  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
4805  {
4806  SCIP_Real newub;
4807 
4808  /* compute new upper bound */
4809  newub = lb + (slack / val);
4810 
4811  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_RHS, newub, ub, cutoff, nchgbds, force) );
4812 
4813  if( *cutoff )
4814  {
4815  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4816  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
4817 
4818  return SCIP_OKAY;
4819  }
4820 
4821  /* collect the new upper bound which is needed for the lower bound computation */
4822  ub = SCIPvarGetUbLocal(var);
4823  }
4824  }
4825 
4826  /* check, if we can tighten the variable's lower bound */
4827  if( !SCIPisInfinity(scip, -lhs) )
4828  {
4829  SCIP_Real slack;
4830  SCIP_Real alpha;
4831 
4832  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
4833  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
4834  {
4835  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
4836  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
4837 
4838  *cutoff = TRUE;
4839  return SCIP_OKAY;
4840  }
4841 
4842  slack = consdata->maxactivity - lhs;
4843 
4844  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
4845  * it to zero
4846  */
4847  if( !SCIPisPositive(scip, slack) )
4848  slack = 0.0;
4849 
4850  alpha = val * (ub - lb);
4851  assert(!SCIPisNegative(scip, alpha));
4852 
4853  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
4854  {
4855  SCIP_Real newlb;
4856 
4857  /* compute new lower bound */
4858  newlb = ub - (slack / val);
4859 
4860  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_LHS, newlb, lb, cutoff, nchgbds, force) );
4861 
4862  if( *cutoff )
4863  {
4864  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4865  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
4866 
4867  return SCIP_OKAY;
4868  }
4869  }
4870  }
4871  }
4872  else
4873  {
4874  /* check, if we can tighten the variable's lower bound */
4875  if( !SCIPisInfinity(scip, rhs) )
4876  {
4877  SCIP_Real slack;
4878  SCIP_Real alpha;
4879 
4880  /* if the minactivity is larger than the right hand side by feasibility epsilon, the constraint is infeasible */
4881  if( SCIPisFeasLT(scip, rhs, consdata->minactivity) )
4882  {
4883  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, minactivity=%.15g > rhs=%.15g\n",
4884  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->minactivity, rhs);
4885 
4886  *cutoff = TRUE;
4887  return SCIP_OKAY;
4888  }
4889 
4890  slack = rhs - consdata->minactivity;
4891 
4892  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
4893  * it to zero
4894  */
4895  if( !SCIPisPositive(scip, slack) )
4896  slack = 0.0;
4897 
4898  alpha = val * (lb - ub);
4899  assert(!SCIPisNegative(scip, alpha));
4900 
4901  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
4902  {
4903  SCIP_Real newlb;
4904 
4905  /* compute new lower bound */
4906  newlb = ub + slack / val;
4907 
4908  SCIP_CALL( tightenVarLb(scip, cons, pos, PROPRULE_1_RHS, newlb, lb, cutoff, nchgbds, force) );
4909 
4910  if( *cutoff )
4911  {
4912  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4913  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
4914 
4915  return SCIP_OKAY;
4916  }
4917  /* collect the new lower bound which is needed for the upper bound computation */
4918  lb = SCIPvarGetLbLocal(var);
4919  }
4920  }
4921 
4922  /* check, if we can tighten the variable's upper bound */
4923  if( !SCIPisInfinity(scip, -lhs) )
4924  {
4925  SCIP_Real slack;
4926  SCIP_Real alpha;
4927 
4928  /* if the maxactivity is smaller than the left hand side by feasibility epsilon, the constraint is infeasible */
4929  if( SCIPisFeasLT(scip, consdata->maxactivity, lhs) )
4930  {
4931  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, maxactivity=%.15g < lhs=%.15g\n",
4932  SCIPconsGetName(cons), SCIPvarGetName(var), consdata->maxactivity, lhs);
4933 
4934  *cutoff = TRUE;
4935  return SCIP_OKAY;
4936  }
4937 
4938  slack = consdata->maxactivity - lhs;
4939 
4940  /* if the slack is zero in tolerances (or negative, but not enough to make the constraint infeasible), we set
4941  * it to zero
4942  */
4943  if( !SCIPisPositive(scip, slack) )
4944  slack = 0.0;
4945 
4946  alpha = val * (lb - ub);
4947  assert(!SCIPisNegative(scip, alpha));
4948 
4949  if( SCIPisSumGT(scip, alpha, slack) || (force && SCIPisGT(scip, alpha, slack)) )
4950  {
4951  SCIP_Real newub;
4952 
4953  /* compute new upper bound */
4954  newub = lb - (slack / val);
4955 
4956  SCIP_CALL( tightenVarUb(scip, cons, pos, PROPRULE_1_LHS, newub, ub, cutoff, nchgbds, force) );
4957 
4958  if( *cutoff )
4959  {
4960  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
4961  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
4962 
4963  return SCIP_OKAY;
4964  }
4965  }
4966  }
4967  }
4968 
4969  return SCIP_OKAY;
4970 }
4971 
4972 /** tightens bounds of a single variable due to activity bounds */
4973 static
4975  SCIP* scip, /**< SCIP data structure */
4976  SCIP_CONS* cons, /**< linear constraint */
4977  int pos, /**< position of the variable in the vars array */
4978  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
4979  int* nchgbds, /**< pointer to count the total number of tightened bounds */
4980  SCIP_Bool force /**< should a possible bound change be forced even if below bound strengthening tolerance */
4981  )
4982 {
4983  SCIP_CONSDATA* consdata;
4984  SCIP_VAR* var;
4985  SCIP_Real val;
4986  SCIP_Real lb;
4987  SCIP_Real ub;
4988  SCIP_Real minresactivity;
4989  SCIP_Real maxresactivity;
4990  SCIP_Real lhs;
4991  SCIP_Real rhs;
4992  SCIP_Bool infeasible;
4993  SCIP_Bool tightened;
4994  SCIP_Bool minisrelax;
4995  SCIP_Bool maxisrelax;
4996  SCIP_Bool isminsettoinfinity;
4997  SCIP_Bool ismaxsettoinfinity;
4998 
4999  assert(scip != NULL);
5000  assert(cons != NULL);
5001  assert(cutoff != NULL);
5002  assert(nchgbds != NULL);
5003 
5004  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5005  if( SCIPconsIsModifiable(cons) )
5006  return SCIP_OKAY;
5007 
5008  consdata = SCIPconsGetData(cons);
5009  assert(consdata != NULL);
5010  assert(0 <= pos && pos < consdata->nvars);
5011 
5012  *cutoff = FALSE;
5013 
5014  var = consdata->vars[pos];
5015 
5016  /* we cannot tighten bounds of multi-aggregated variables */
5018  return SCIP_OKAY;
5019 
5020  val = consdata->vals[pos];
5021  lhs = consdata->lhs;
5022  rhs = consdata->rhs;
5023  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
5024  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
5025  assert(var != NULL);
5026  assert(!SCIPisZero(scip, val));
5027  assert(!SCIPisInfinity(scip, lhs));
5028  assert(!SCIPisInfinity(scip, -rhs));
5029 
5030  lb = SCIPvarGetLbLocal(var);
5031  ub = SCIPvarGetUbLocal(var);
5032  assert(SCIPisLE(scip, lb, ub));
5033 
5034  if( val > 0.0 )
5035  {
5036  /* check, if we can tighten the variable's bounds */
5037  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
5038  {
5039  SCIP_Real newub;
5040 
5041  newub = (rhs - minresactivity)/val;
5042 
5043  if( !SCIPisInfinity(scip, newub) &&
5044  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
5045  {
5046  SCIP_Bool activityunreliable;
5047  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
5048 
5049  /* check minresactivities for reliability */
5050  if( activityunreliable )
5051  {
5052  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
5053  newub = (rhs - minresactivity)/val;
5054  activityunreliable = SCIPisInfinity(scip, -minresactivity) ||
5055  (!SCIPisUbBetter(scip, newub, lb, ub) && (!SCIPisFeasLT(scip, newub, ub) || !SCIPvarIsIntegral(var))
5056  && (!force || !SCIPisLT(scip, newub, ub)));
5057  }
5058 
5059  if( !activityunreliable )
5060  {
5061  /* tighten upper bound */
5062  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newub=%.15g\n",
5063  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
5064  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_RHS, pos), force,
5065  &infeasible, &tightened) );
5066  if( infeasible )
5067  {
5068  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5069  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5070 
5071  /* analyze conflict */
5072  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5073 
5074  *cutoff = TRUE;
5075  return SCIP_OKAY;
5076  }
5077  if( tightened )
5078  {
5079  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
5080  assert(SCIPisFeasLE(scip, ub, newub));
5081  (*nchgbds)++;
5082 
5083  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5084  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
5085  }
5086  }
5087  }
5088  }
5089 
5090  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
5091  {
5092  SCIP_Real newlb;
5093 
5094  newlb = (lhs - maxresactivity)/val;
5095  if( !SCIPisInfinity(scip, -newlb) &&
5096  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
5097  {
5098  /* check maxresactivities for reliability */
5099  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
5100  {
5101  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
5102  newlb = (lhs - maxresactivity)/val;
5103 
5104  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisLbBetter(scip, newlb, lb, ub)
5105  && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
5106  && (!force || !SCIPisGT(scip, newlb, lb))) )
5107  return SCIP_OKAY;
5108  }
5109 
5110  /* tighten lower bound */
5111  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5112  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
5113  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_LHS, pos), force,
5114  &infeasible, &tightened) );
5115  if( infeasible )
5116  {
5117  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5118  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5119 
5120  /* analyze conflict */
5121  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5122 
5123  *cutoff = TRUE;
5124  return SCIP_OKAY;
5125  }
5126  if( tightened )
5127  {
5128  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
5129  assert(SCIPisFeasGE(scip, lb, newlb));
5130  (*nchgbds)++;
5131  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5132  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
5133  }
5134  }
5135  }
5136  }
5137  else
5138  {
5139  /* check, if we can tighten the variable's bounds */
5140  if( !isminsettoinfinity && !SCIPisInfinity(scip, rhs) && !minisrelax )
5141  {
5142  SCIP_Real newlb;
5143 
5144  newlb = (rhs - minresactivity)/val;
5145  if( !SCIPisInfinity(scip, -newlb) &&
5146  ((force && SCIPisGT(scip, newlb, lb)) || (SCIPvarIsIntegral(var) && SCIPisFeasGT(scip, newlb, lb)) || SCIPisLbBetter(scip, newlb, lb, ub)) )
5147  {
5148  SCIP_Bool activityunreliable;
5149  activityunreliable = SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity);
5150  /* check minresactivities for reliability */
5151  if( activityunreliable )
5152  {
5153  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
5154  newlb = (rhs - minresactivity)/val;
5155 
5156  activityunreliable = SCIPisInfinity(scip, -minresactivity)
5157  || (!SCIPisLbBetter(scip, newlb, lb, ub) && (!SCIPisFeasGT(scip, newlb, lb) || !SCIPvarIsIntegral(var))
5158  && (!force || !SCIPisGT(scip, newlb, lb)));
5159  }
5160 
5161  if( !activityunreliable )
5162  {
5163  /* tighten lower bound */
5164  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g] -> newlb=%.15g\n",
5165  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newlb);
5166  SCIP_CALL( SCIPinferVarLbCons(scip, var, newlb, cons, getInferInt(PROPRULE_1_RHS, pos), force,
5167  &infeasible, &tightened) );
5168  if( infeasible )
5169  {
5170  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5171  SCIPconsGetName(cons), SCIPvarGetName(var), newlb, ub);
5172 
5173  /* analyze conflict */
5174  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5175 
5176  *cutoff = TRUE;
5177  return SCIP_OKAY;
5178  }
5179  if( tightened )
5180  {
5181  lb = SCIPvarGetLbLocal(var); /* get bound again: it may be additionally modified due to integrality */
5182  assert(SCIPisFeasGE(scip, lb, newlb));
5183  (*nchgbds)++;
5184  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5185  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
5186  }
5187  }
5188  }
5189  }
5190 
5191  if( !ismaxsettoinfinity && !SCIPisInfinity(scip, -lhs) && !maxisrelax )
5192  {
5193  SCIP_Real newub;
5194 
5195  newub = (lhs - maxresactivity)/val;
5196  if( !SCIPisInfinity(scip, newub) &&
5197  ((force && SCIPisLT(scip, newub, ub)) || (SCIPvarIsIntegral(var) && SCIPisFeasLT(scip, newub, ub)) || SCIPisUbBetter(scip, newub, lb, ub)) )
5198  {
5199  /* check maxresactivities for reliability */
5200  if( SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
5201  {
5202  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
5203  newub = (lhs - maxresactivity)/val;
5204 
5205  if( SCIPisInfinity(scip, maxresactivity) || (!SCIPisUbBetter(scip, newub, lb, ub)
5206  && (!SCIPisFeasLT(scip, newub, ub) && !SCIPvarIsIntegral(var))
5207  && (!force || !SCIPisLT(scip, newub, ub))) )
5208  return SCIP_OKAY;
5209  }
5210 
5211  /* tighten upper bound */
5212  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, old bds=[%.15g,%.15g], val=%.15g, resactivity=[%.15g,%.15g], sides=[%.15g,%.15g], newub=%.15g\n",
5213  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub, val, minresactivity, maxresactivity, lhs, rhs, newub);
5214  SCIP_CALL( SCIPinferVarUbCons(scip, var, newub, cons, getInferInt(PROPRULE_1_LHS, pos), force,
5215  &infeasible, &tightened) );
5216  if( infeasible )
5217  {
5218  SCIPdebugMessage("linear constraint <%s>: cutoff <%s>, new bds=[%.15g,%.15g]\n",
5219  SCIPconsGetName(cons), SCIPvarGetName(var), lb, newub);
5220 
5221  /* analyze conflict */
5222  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5223 
5224  *cutoff = TRUE;
5225  return SCIP_OKAY;
5226  }
5227  if( tightened )
5228  {
5229  ub = SCIPvarGetUbLocal(var); /* get bound again: it may be additionally modified due to integrality */
5230  assert(SCIPisFeasLE(scip, ub, newub));
5231  (*nchgbds)++;
5232  SCIPdebugMessage("linear constraint <%s>: tighten <%s>, new bds=[%.15g,%.15g]\n",
5233  SCIPconsGetName(cons), SCIPvarGetName(var), lb, ub);
5234  }
5235  }
5236  }
5237  }
5238 
5239  return SCIP_OKAY;
5240 }
5241 
5242 #define MAXTIGHTENROUNDS 10
5243 #define MAXACTIVITYDELTATHR 1e6
5244 
5245 /** tightens bounds of variables in constraint due to activity bounds */
5246 static
5248  SCIP* scip, /**< SCIP data structure */
5249  SCIP_CONS* cons, /**< linear constraint */
5250  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
5251  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5252  int* nchgbds /**< pointer to count the total number of tightened bounds */
5253  )
5254 {
5255  SCIP_CONSDATA* consdata;
5256  int nvars;
5257  int nrounds;
5258  int lastchange;
5259  int oldnchgbds;
5260  int v;
5261  SCIP_Bool force;
5262  SCIP_Bool easycase;
5263 
5264  assert(scip != NULL);
5265  assert(cons != NULL);
5266  assert(nchgbds != NULL);
5267  assert(cutoff != NULL);
5268 
5269  *cutoff = FALSE;
5270 
5271  /* we cannot tighten variables' bounds, if the constraint may be not complete */
5272  if( SCIPconsIsModifiable(cons) )
5273  return SCIP_OKAY;
5274 
5275  /* if a constraint was created after presolve, then it may hold fixed variables
5276  * if there are even multi-aggregated variables, then we cannot do bound tightening on these
5277  * thus, ensure here again that variable fixings have been applied
5278  */
5279  SCIP_CALL( applyFixings(scip, cons, cutoff) );
5280  if( *cutoff )
5281  return SCIP_OKAY;
5282 
5283  /* check if constraint has any chances of tightening bounds */
5284  if( !canTightenBounds(scip, cons) )
5285  return SCIP_OKAY;
5286 
5287  consdata = SCIPconsGetData(cons);
5288  assert(consdata != NULL);
5289 
5290  nvars = consdata->nvars;
5291  force = (nvars == 1) && !SCIPconsIsModifiable(cons);
5292 
5293  /* ensure that the variables are properly sorted */
5294  if( sortvars && SCIPgetStage(scip) >= SCIP_STAGE_INITSOLVE && !consdata->binvarssorted )
5295  {
5296  SCIP_CALL( consdataSort(scip, consdata) );
5297  assert(consdata->binvarssorted);
5298  }
5299 
5300  /* update maximal activity delta if necessary */
5301  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
5302  consdataRecomputeMaxActivityDelta(scip, consdata);
5303 
5304  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
5305  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
5306 
5307  /* this may happen if all variables are fixed */
5308  if( SCIPisFeasZero(scip, consdata->maxactdelta) )
5309  return SCIP_OKAY;
5310 
5311  if( !SCIPisInfinity(scip, consdata->maxactdelta) )
5312  {
5313  SCIP_Real slack;
5314  SCIP_Real surplus;
5315  SCIP_Real minactivity;
5316  SCIP_Real maxactivity;
5317  SCIP_Bool minisrelax;
5318  SCIP_Bool maxisrelax;
5319 
5320  /* use maximal activity delta to skip propagation (cannot deduce anything) */
5321  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minisrelax, &maxisrelax);
5322  assert(!SCIPisInfinity(scip, minactivity));
5323  assert(!SCIPisInfinity(scip, -maxactivity));
5324 
5325  slack = (SCIPisInfinity(scip, consdata->rhs) || SCIPisInfinity(scip, -minactivity)) ? SCIPinfinity(scip) : (consdata->rhs - minactivity);
5326  surplus = (SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, maxactivity)) ? SCIPinfinity(scip) : (maxactivity - consdata->lhs);
5327 
5328  /* check if the constraint will propagate */
5329  if( SCIPisLE(scip, consdata->maxactdelta, MIN(slack, surplus)) )
5330  return SCIP_OKAY;
5331  }
5332 
5333  /* check if we can use fast implementation for easy and numerically well behaved cases */
5334  easycase = SCIPisLT(scip, consdata->maxactdelta, MAXACTIVITYDELTATHR);
5335 
5336  /* as long as the bounds might be tightened again, try to tighten them; abort after a maximal number of rounds */
5337  lastchange = -1;
5338  for( nrounds = 0; (force || !consdata->boundstightened) && nrounds < MAXTIGHTENROUNDS; ++nrounds )
5339  {
5340  /* mark the constraint to have the variables' bounds tightened */
5341  consdata->boundstightened = TRUE;
5342 
5343  /* try to tighten the bounds of each variable in the constraint. During solving process, the binary variable
5344  * sorting enables skipping variables
5345  */
5346  v = 0;
5347  while( v < nvars && v != lastchange && !(*cutoff) )
5348  {
5349  oldnchgbds = *nchgbds;
5350 
5351  assert(!sortvars || SCIPgetStage(scip) < SCIP_STAGE_SOLVING || consdata->binvarssorted);
5352 
5353  if( easycase )
5354  {
5355  SCIP_CALL( tightenVarBoundsEasy(scip, cons, v, cutoff, nchgbds, force) );
5356  }
5357  else
5358  {
5359  SCIP_CALL( tightenVarBounds(scip, cons, v, cutoff, nchgbds, force) );
5360  }
5361 
5362  /* if there was no progress, skip the rest of the binary variables */
5363  if( *nchgbds > oldnchgbds )
5364  {
5365  lastchange = v;
5366  ++v;
5367  }
5368  else if( consdata->binvarssorted && v < consdata->nbinvars - 1
5369  && !SCIPisFeasEQ(scip, SCIPvarGetUbLocal(consdata->vars[v]), SCIPvarGetLbLocal(consdata->vars[v])) )
5370  v = consdata->nbinvars;
5371  else
5372  ++v;
5373  }
5374  }
5375 #ifndef NDEBUG
5376  if( force && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
5377  assert(*cutoff || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(consdata->vars[0]), SCIPvarGetUbLocal(consdata->vars[0])));
5378 #endif
5379 
5380  return SCIP_OKAY;
5381 }
5382 
5383 /** checks linear constraint for feasibility of given solution or current solution */
5384 static
5386  SCIP* scip, /**< SCIP data structure */
5387  SCIP_CONS* cons, /**< linear constraint */
5388  SCIP_SOL* sol, /**< solution to be checked, or NULL for current solution */
5389  SCIP_Bool checklprows, /**< has linear constraint to be checked, if it is already in current LP? */
5390  SCIP_Bool checkrelmaxabs, /**< should the violation for a constraint with side 0.0 be checked relative
5391  * to 1.0 (FALSE) or to the maximum absolute value in the activity (TRUE)? */
5392  SCIP_Bool* violated /**< pointer to store whether the constraint is violated */
5393  )
5394 {
5395  SCIP_CONSDATA* consdata;
5396  SCIP_Real activity;
5397 
5398  assert(scip != NULL);
5399  assert(cons != NULL);
5400  assert(violated != NULL);
5401 
5402  SCIPdebugMessage("checking linear constraint <%s>\n", SCIPconsGetName(cons));
5403  SCIPdebugPrintCons(scip, cons, NULL);
5404 
5405  consdata = SCIPconsGetData(cons);
5406  assert(consdata != NULL);
5407 
5408  *violated = FALSE;
5409 
5410  if( consdata->row != NULL )
5411  {
5412  if( !checklprows && SCIProwIsInLP(consdata->row) )
5413  return SCIP_OKAY;
5414  else if( sol == NULL && !SCIPhasCurrentNodeLP(scip) )
5415  activity = consdataComputePseudoActivity(scip, consdata);
5416  else
5417  activity = SCIPgetRowSolActivity(scip, consdata->row, sol);
5418  }
5419  else
5420  activity = consdataGetActivity(scip, consdata, sol);
5421 
5422  SCIPdebugMessage(" consdata activity=%.15g (lhs=%.15g, rhs=%.15g, row=%p, checklprows=%u, rowinlp=%u, sol=%p, hascurrentnodelp=%u)\n",
5423  activity, consdata->lhs, consdata->rhs, (void*)consdata->row, checklprows,
5424  consdata->row == NULL ? 0 : SCIProwIsInLP(consdata->row), (void*)sol,
5425  consdata->row == NULL ? FALSE : SCIPhasCurrentNodeLP(scip));
5426 
5427  if( SCIPisFeasLT(scip, activity, consdata->lhs) || SCIPisFeasGT(scip, activity, consdata->rhs) )
5428  {
5429  /* the "normal" check: one of the two sides is violated */
5430  if( !checkrelmaxabs )
5431  {
5432  *violated = TRUE;
5433 
5434  /* only reset constraint age if we are in enforcement */
5435  if( sol == NULL )
5436  {
5437  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5438  }
5439  }
5440  /* the (much) more complicated check: we try to disregard random noise and violations of a 0.0 side which are
5441  * small compared to the absolute values occuring in the activity
5442  */
5443  else
5444  {
5445  SCIP_Real maxabs;
5446  SCIP_Real coef;
5447  SCIP_Real absval;
5448  SCIP_Real solval;
5449  int v;
5450 
5451  maxabs = 1.0;
5452 
5453  /* compute maximum absolute value */
5454  for( v = 0; v < consdata->nvars; ++v )
5455  {
5456  if( consdata->vals != NULL )
5457  {
5458  coef = consdata->vals[v];
5459  }
5460  else
5461  coef = 1.0;
5462 
5463  solval = SCIPgetSolVal(scip, sol, consdata->vars[v]);
5464  absval = REALABS( coef * solval );
5465  maxabs = MAX( maxabs, absval );
5466  }
5467 
5468  /* regard left hand side, first */
5469  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
5470  {
5471  /* check whether violation is random noise */
5472  if( (consdata->lhs - activity) <= (1e-15 * maxabs) )
5473  {
5474  SCIPdebugMessage(" lhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
5475  consdata->lhs - activity, maxabs);
5476  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
5477 
5478  /* only increase constraint age if we are in enforcement */
5479  if( sol == NULL )
5480  {
5481  SCIP_CALL( SCIPincConsAge(scip, cons) );
5482  }
5483  }
5484  /* lhs is violated and lhs is 0.0: use relative tolerance w.r.t. largest absolute value */
5485  else if( SCIPisZero(scip, consdata->lhs) )
5486  {
5487  if( (consdata->lhs - activity) <= (SCIPfeastol(scip) * maxabs) )
5488  {
5489  SCIPdebugMessage(" lhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
5490  consdata->lhs - activity, maxabs);
5491  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
5492 
5493  /* only increase constraint age if we are in enforcement */
5494  if( sol == NULL )
5495  {
5496  SCIP_CALL( SCIPincConsAge(scip, cons) );
5497  }
5498  }
5499  else
5500  {
5501  *violated = TRUE;
5502 
5503  /* only reset constraint age if we are in enforcement */
5504  if( sol == NULL )
5505  {
5506  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5507  }
5508  }
5509  }
5510  else
5511  {
5512  *violated = TRUE;
5513 
5514  /* only reset constraint age if we are in enforcement */
5515  if( sol == NULL )
5516  {
5517  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5518  }
5519  }
5520  }
5521 
5522  /* now regard right hand side */
5523  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
5524  {
5525  /* check whether violation is random noise */
5526  if( (activity - consdata->rhs) <= (1e-15 * maxabs) )
5527  {
5528  SCIPdebugMessage(" rhs violated due to random noise: violation=%16.9g, maxabs=%16.9g\n",
5529  activity - consdata->rhs, maxabs);
5530  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
5531 
5532  /* only increase constraint age if we are in enforcement */
5533  if( sol == NULL )
5534  {
5535  SCIP_CALL( SCIPincConsAge(scip, cons) );
5536  }
5537  }
5538  /* rhs is violated and rhs is 0.0, use relative tolerance w.r.t. largest absolute value */
5539  else if( SCIPisZero(scip, consdata->rhs) )
5540  {
5541  if( (activity - consdata->rhs) <= (SCIPfeastol(scip) * maxabs) )
5542  {
5543  SCIPdebugMessage(" rhs violated absolutely (violation=%16.9g), but feasible when using relative tolerance w.r.t. maximum absolute value (%16.9g)\n",
5544  activity - consdata->rhs, maxabs);
5545  SCIPdebug( SCIP_CALL( SCIPprintCons(scip, cons, NULL) ) );
5546 
5547  /* only increase constraint age if we are in enforcement */
5548  if( sol == NULL )
5549  {
5550  SCIP_CALL( SCIPincConsAge(scip, cons) );
5551  }
5552  }
5553  else
5554  {
5555  *violated = TRUE;
5556 
5557  /* only reset constraint age if we are in enforcement */
5558  if( sol == NULL )
5559  {
5560  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5561  }
5562  }
5563  }
5564  else
5565  {
5566  *violated = TRUE;
5567 
5568  /* only reset constraint age if we are in enforcement */
5569  if( sol == NULL )
5570  {
5571  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5572  }
5573  }
5574  }
5575  }
5576  }
5577  else
5578  {
5579  /* only increase constraint age if we are in enforcement */
5580  if( sol == NULL )
5581  {
5582  SCIP_CALL( SCIPincConsAge(scip, cons) );
5583  }
5584  }
5585 
5586  return SCIP_OKAY;
5587 }
5588 
5589 /** creates an LP row in a linear constraint data */
5590 static
5592  SCIP* scip, /**< SCIP data structure */
5593  SCIP_CONS* cons /**< linear constraint */
5594  )
5595 {
5596  SCIP_CONSDATA* consdata;
5597 
5598  assert(scip != NULL);
5599  assert(cons != NULL);
5600 
5601  consdata = SCIPconsGetData(cons);
5602  assert(consdata != NULL);
5603  assert(consdata->row == NULL);
5604 
5605  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row, SCIPconsGetHdlr(cons), SCIPconsGetName(cons), consdata->lhs, consdata->rhs,
5607 
5608  SCIP_CALL( SCIPaddVarsToRow(scip, consdata->row, consdata->nvars, consdata->vars, consdata->vals) );
5609 
5610  return SCIP_OKAY;
5611 }
5612 
5613 /** adds linear constraint as cut to the LP */
5614 static
5616  SCIP* scip, /**< SCIP data structure */
5617  SCIP_CONS* cons, /**< linear constraint */
5618  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
5619  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
5620  )
5621 {
5622  SCIP_CONSDATA* consdata;
5623 
5624  assert(scip != NULL);
5625  assert(cons != NULL);
5626 
5627  consdata = SCIPconsGetData(cons);
5628  assert(consdata != NULL);
5629 
5630  if( consdata->row == NULL )
5631  {
5632  /* convert consdata object into LP row */
5633  SCIP_CALL( createRow(scip, cons) );
5634  }
5635  assert(consdata->row != NULL);
5636 
5637  /* insert LP row as cut */
5638  if( !SCIProwIsInLP(consdata->row) )
5639  {
5640  SCIPdebugMessage("adding relaxation of linear constraint <%s>: ", SCIPconsGetName(cons));
5641  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL)) );
5642  /* if presolving is turned off, the row might be trivial */
5643  if ( ! SCIPisInfinity(scip, -consdata->lhs) || ! SCIPisInfinity(scip, consdata->rhs) )
5644  {
5645  SCIP_CALL( SCIPaddCut(scip, sol, consdata->row, FALSE, cutoff) );
5646  }
5647 #ifndef NDEBUG
5648  else
5649  {
5650  int r;
5651  SCIP_CALL( SCIPgetIntParam(scip, "constraints/linear/maxprerounds", &r) );
5652  assert( r == 0 );
5653  }
5654 #endif
5655  }
5656 
5657  return SCIP_OKAY;
5658 }
5659 
5660 /** separates linear constraint: adds linear constraint as cut, if violated by given solution */
5661 static
5663  SCIP* scip, /**< SCIP data structure */
5664  SCIP_CONS* cons, /**< linear constraint */
5665  SCIP_CONSHDLRDATA* conshdlrdata, /**< constraint handler data */
5666  SCIP_SOL* sol, /**< primal CIP solution, NULL for current LP solution */
5667  SCIP_Bool separatecards, /**< should knapsack cardinality cuts be generated? */
5668  SCIP_Bool separateall, /**< should all constraints be subject to cardinality cut generation instead of only
5669  * the ones with non-zero dual value? */
5670  int* ncuts, /**< pointer to add up the number of found cuts */
5671  SCIP_Bool* cutoff /**< pointer to store whether a cutoff was found */
5672  )
5673 {
5674  SCIP_CONSDATA* consdata;
5675  SCIP_Bool violated;
5676  int oldncuts;
5677 
5678  assert(scip != NULL);
5679  assert(conshdlrdata != NULL);
5680  assert(cons != NULL);
5681  assert(cutoff != NULL);
5682 
5683  consdata = SCIPconsGetData(cons);
5684  assert(ncuts != NULL);
5685  assert(consdata != NULL);
5686 
5687  oldncuts = *ncuts;
5688  *cutoff = FALSE;
5689 
5690  SCIP_CALL( checkCons(scip, cons, sol, (sol != NULL), conshdlrdata->checkrelmaxabs, &violated) );
5691 
5692  if( violated )
5693  {
5694  /* insert LP row as cut */
5695  SCIP_CALL( addRelaxation(scip, cons, sol, cutoff) );
5696  (*ncuts)++;
5697  }
5698  else if( !SCIPconsIsModifiable(cons) && separatecards )
5699  {
5700  /* relax linear constraint into knapsack constraint and separate lifted cardinality cuts */
5701  if( !separateall && sol == NULL )
5702  {
5703  /* we only want to call the knapsack cardinality cut separator for rows that have a non-zero dual solution */
5704  if( consdata->row != NULL && SCIProwIsInLP(consdata->row) )
5705  {
5706  SCIP_Real dualsol;
5707 
5708  dualsol = SCIProwGetDualsol(consdata->row);
5709  if( SCIPisFeasNegative(scip, dualsol) )
5710  {
5711  if( !SCIPisInfinity(scip, consdata->rhs) )
5712  {
5713  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
5714  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
5715  }
5716  }
5717  else if( SCIPisFeasPositive(scip, dualsol) )
5718  {
5719  if( !SCIPisInfinity(scip, -consdata->lhs) )
5720  {
5721  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
5722  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
5723  }
5724  }
5725  }
5726  }
5727  else
5728  {
5729  if( !SCIPisInfinity(scip, consdata->rhs) )
5730  {
5731  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
5732  consdata->vals, +1.0, consdata->rhs, sol, cutoff, ncuts) );
5733  }
5734  if( !SCIPisInfinity(scip, -consdata->lhs) )
5735  {
5736  SCIP_CALL( SCIPseparateRelaxedKnapsack(scip, cons, NULL, consdata->nvars, consdata->vars,
5737  consdata->vals, -1.0, -consdata->lhs, sol, cutoff, ncuts) );
5738  }
5739  }
5740  }
5741 
5742  if( *ncuts > oldncuts )
5743  {
5744  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5745  }
5746 
5747  return SCIP_OKAY;
5748 }
5749 
5750 /** propagation method for linear constraints */
5751 static
5753  SCIP* scip, /**< SCIP data structure */
5754  SCIP_CONS* cons, /**< linear constraint */
5755  SCIP_Bool tightenbounds, /**< should the variable's bounds be tightened? */
5756  SCIP_Bool sortvars, /**< should variable sorting for faster propagation be used? */
5757  SCIP_Bool* cutoff, /**< pointer to store whether the node can be cut off */
5758  int* nchgbds /**< pointer to count the total number of tightened bounds */
5759  )
5760 {
5761  SCIP_CONSDATA* consdata;
5762  SCIP_Real minactivity;
5763  SCIP_Real maxactivity;
5764  SCIP_Bool minactisrelax;
5765  SCIP_Bool maxactisrelax;
5766 
5767  assert(scip != NULL);
5768  assert(cons != NULL);
5769  assert(cutoff != NULL);
5770  assert(nchgbds != NULL);
5771 
5772  /*SCIPdebugMessage("propagating linear constraint <%s>\n", SCIPconsGetName(cons));*/
5773 
5774  consdata = SCIPconsGetData(cons);
5775  assert(consdata != NULL);
5776 
5777  *cutoff = FALSE;
5778 
5779  /* check, if constraint is already propagated */
5780  if( consdata->propagated && (!tightenbounds || consdata->boundstightened) )
5781  return SCIP_OKAY;
5782 
5783  /* mark constraint as propagated */
5784  consdata->propagated = TRUE;
5785 
5786  /* we can only infer activity bounds of the linear constraint, if it is not modifiable */
5787  if( !SCIPconsIsModifiable(cons) )
5788  {
5789  /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
5790  if( !SCIPinRepropagation(scip) )
5791  {
5792  SCIP_CALL( SCIPincConsAge(scip, cons) );
5793  }
5794 
5795  /* tighten the variable's bounds */
5796  if( tightenbounds )
5797  {
5798  int oldnchgbds;
5799 
5800  oldnchgbds = *nchgbds;
5801 
5802  SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
5803 
5804  if( *nchgbds > oldnchgbds )
5805  {
5806  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5807  }
5808  }
5809 
5810  /* check constraint for infeasibility and redundancy */
5811  if( !(*cutoff) )
5812  {
5813  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
5814 
5815  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) )
5816  {
5817  SCIPdebugMessage("linear constraint <%s> is infeasible (rhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
5818  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
5819 
5820  /* analyze conflict */
5821  SCIP_CALL( analyzeConflict(scip, cons, TRUE) );
5822 
5823  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5824  *cutoff = TRUE;
5825  }
5826  else if( SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
5827  {
5828  SCIPdebugMessage("linear constraint <%s> is infeasible (lhs): activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
5829  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
5830 
5831  /* analyze conflict */
5832  SCIP_CALL( analyzeConflict(scip, cons, FALSE) );
5833 
5834  SCIP_CALL( SCIPresetConsAge(scip, cons) );
5835  *cutoff = TRUE;
5836  }
5837  else if( SCIPisGE(scip, minactivity, consdata->lhs) && SCIPisLE(scip, maxactivity, consdata->rhs) )
5838  {
5839  SCIPdebugMessage("linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
5840  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
5841  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
5842  }
5843  }
5844  }
5845 
5846  return SCIP_OKAY;
5847 }
5848 
5849 
5850 /*
5851  * Presolving methods
5852  */
5853 
5854 /** converts all variables with fixed domain into FIXED variables */
5855 static
5857  SCIP* scip, /**< SCIP data structure */
5858  SCIP_CONS* cons, /**< linear constraint */
5859  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
5860  int* nfixedvars /**< pointer to count the total number of fixed variables */
5861  )
5862 {
5863  SCIP_CONSDATA* consdata;
5864  SCIP_VAR* var;
5865  SCIP_VARSTATUS varstatus;
5866  SCIP_Real lb;
5867  SCIP_Real ub;
5868  SCIP_Bool fixed;
5869  SCIP_Bool infeasible;
5870  int v;
5871 
5872  assert(scip != NULL);
5873  assert(cons != NULL);
5874  assert(cutoff != NULL);
5875  assert(nfixedvars != NULL);
5876 
5877  consdata = SCIPconsGetData(cons);
5878  assert(consdata != NULL);
5879 
5880  for( v = 0; v < consdata->nvars; ++v )
5881  {
5882  assert(consdata->vars != NULL);
5883  var = consdata->vars[v];
5884  varstatus = SCIPvarGetStatus(var);
5885 
5886  if( varstatus != SCIP_VARSTATUS_FIXED )
5887  {
5888  lb = SCIPvarGetLbGlobal(var);
5889  ub = SCIPvarGetUbGlobal(var);
5890  if( SCIPisEQ(scip, lb, ub) )
5891  {
5892  SCIP_Real fixval;
5893 
5894  fixval = SCIPselectSimpleValue(lb - 0.9 * SCIPepsilon(scip), ub + 0.9 * SCIPepsilon(scip), MAXDNOM);
5895  SCIPdebugMessage("converting variable <%s> with fixed bounds [%.15g,%.15g] into fixed variable fixed at %.15g\n",
5896  SCIPvarGetName(var), lb, ub, fixval);
5897  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
5898  if( infeasible )
5899  {
5900  SCIPdebugMessage(" -> infeasible fixing\n");
5901  *cutoff = TRUE;
5902  return SCIP_OKAY;
5903  }
5904  if( fixed )
5905  (*nfixedvars)++;
5906  }
5907  }
5908  }
5909 
5910  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
5911 
5912  if( infeasible )
5913  {
5914  SCIPdebugMessage(" -> infeasible fixing\n");
5915  *cutoff = TRUE;
5916  return SCIP_OKAY;
5917  }
5918 
5919  assert(consdata->removedfixings);
5920 
5921  return SCIP_OKAY;
5922 }
5923 
5924 #define MAX_CLIQUE_NONZEROS_PER_CONS 1000000
5925 
5926 /** extracts cliques of the constraint and adds them to SCIP
5927  *
5928  * The following clique extraction mechanism are implemeneted
5929  *
5930  * 1. collect binary variables and sort them in non increasing order, then
5931  *
5932  * a) if the constraint has a finite right hand side and the negative infinity counters for the minactivity are zero
5933  * then add the variables as a clique for which all successive pairs of coefficients fullfill the following
5934  * condition
5935  *
5936  * minactivity + vals[i] + vals[i+1] > rhs
5937  *
5938  * and also add the binary to binary implication also for non-successive variables for which the same argument
5939  * holds
5940  *
5941  * minactivity + vals[i] + vals[j] > rhs
5942  *
5943  * 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
5944  * binary to binary implications x1 = 1 => x4 = 0 and x2 = 1 => x4 = 0
5945  *
5946  * b) if the constraint has a finite left hand side and the positive infinity counters for the maxactivity are zero
5947  * then add the variables as a clique for which all successive pairs of coefficients fullfill the follwoing
5948  * condition
5949  *
5950  * maxactivity + vals[i] + vals[i-1] < lhs
5951  *
5952  * and also add the binary to binary implication also for non-successive variables for which the same argument
5953  * holds
5954  *
5955  * maxactivity + vals[i] + vals[j] < lhs
5956  *
5957  * e.g. you could multiply the above example by -1
5958  *
5959  * c) the constraint has a finite right hand side and a finite minactivity then add the variables as a negated
5960  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
5961  * condition
5962  *
5963  * minactivity - vals[i] - vals[i-1] > rhs
5964  *
5965  * and also add the binary to binary implication also for non-successive variables for which the
5966  * same argument holds
5967  *
5968  * minactivity - vals[i] - vals[j] > rhs
5969  *
5970  * e.g. -4 x1 -3 x2 - 2 x3 + 2 x4 <= -4 would lead to the (negated) clique (~x1, ~x2) and the binary to binary
5971  * implication x1 = 0 => x3 = 1
5972  *
5973  * d) the constraint has a finite left hand side and a finite maxactivity then add the variables as a negated
5974  * clique(clique on the negated variables) for which all successive pairs of coefficients fullfill the following
5975  * condition
5976  *
5977  * maxactivity - vals[i] - vals[i+1] < lhs
5978  *
5979  * and also add the binary to binary implication also for non-successive variables for which the same argument
5980  * holds
5981  *
5982  * maxactivity - vals[i] - vals[j] < lhs
5983  *
5984  * e.g. you could multiply the above example by -1
5985  *
5986  * 2. if the linear constraint represents a set-packing or set-partitioning constraint, the whole constraint is added
5987  * as clique, (this part is done at the end of the method)
5988  *
5989  */
5990 static
5992  SCIP* scip, /**< SCIP data structure */
5993  SCIP_CONS* cons, /**< linear constraint */
5994  SCIP_Bool sortvars, /**< should variables be used in sorted order? */
5995  int* nfixedvars, /**< pointer to count number of fixed variables */
5996  int* nchgbds, /**< pointer to count the total number of tightened bounds */
5997  SCIP_Bool* cutoff /**< pointer to store TRUE, if a cutoff was found */
5998  )
5999 {
6000  SCIP_VAR** vars;
6001  SCIP_Real* vals;
6002  SCIP_CONSDATA* consdata;
6003  SCIP_Bool lhsclique;
6004  SCIP_Bool rhsclique;
6005  SCIP_Bool finitelhs;
6006  SCIP_Bool finiterhs;
6007  SCIP_Bool finiteminact;
6008  SCIP_Bool finitemaxact;
6009  SCIP_Bool finitenegminact;
6010  SCIP_Bool finitenegmaxact;
6011  SCIP_Bool finiteposminact;
6012  SCIP_Bool finiteposmaxact;
6013  SCIP_Bool infeasible;
6014  SCIP_Bool stopped;
6015  int cliquenonzerosadded;
6016  int v;
6017  int i;
6018  int nposcoefs;
6019  int nnegcoefs;
6020  int nvars;
6021 
6022  assert(scip != NULL);
6023  assert(cons != NULL);
6024  assert(nfixedvars != NULL);
6025  assert(nchgbds != NULL);
6026  assert(cutoff != NULL);
6027  assert(!SCIPconsIsDeleted(cons));
6028 
6029  consdata = SCIPconsGetData(cons);
6030  assert(consdata != NULL);
6031 
6032  if( consdata->nvars < 2 )
6033  return SCIP_OKAY;
6034 
6035  /* add implications if posibble
6036  *
6037  * for now we only add binary to non-binary implications, and this is only done for the binary variable with the
6038  * maximal absolute contribution and also only if this variable would force all other variables to their bound
6039  * corresponding to the global minimal activity of the constraint
6040  */
6041  if( !consdata->implsadded )
6042  {
6043  /* sort variables by variable type */
6044  SCIP_CALL( consdataSort(scip, consdata) );
6045 
6046  /* @todo we might extract implications/cliques if SCIPvarIsBinary() variables exist and we have integer variables
6047  * up front, might change sorting correspondingly
6048  */
6049  /* fast abort if no binaries exist */
6050  if( !SCIPvarIsBinary(consdata->vars[0]) )
6051  return SCIP_OKAY;
6052 
6053  nvars = consdata->nvars;
6054  vars = consdata->vars;
6055  vals = consdata->vals;
6056 
6057  /* recompute activities if needed */
6058  if( !consdata->validactivities )
6059  consdataCalcActivities(scip, consdata);
6060  assert(consdata->validactivities);
6061 
6062  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
6063  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
6064  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
6065  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
6066  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
6067  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
6068  finiteminact = (finitenegminact && finiteposminact);
6069  finitemaxact = (finitenegmaxact && finiteposmaxact);
6070 
6071  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
6072  {
6073  SCIP_Real maxabscontrib = -1.0;
6074  SCIP_Bool posval = FALSE;
6075  SCIP_Bool allbinary = TRUE;
6076  int oldnchgbds = *nchgbds;
6077  int nbdchgs = 0;
6078  int nimpls = 0;
6079  int position = -1;
6080 
6081  /* we need a valid minimal/maximal activity to add cliques */
6082  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
6083  {
6084  consdataRecomputeGlbMinactivity(scip, consdata);
6085  assert(consdata->validglbminact);
6086  }
6087 
6088  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
6089  {
6090  consdataRecomputeGlbMaxactivity(scip, consdata);
6091  assert(consdata->validglbmaxact);
6092  }
6093  assert(consdata->validglbminact || consdata->validglbmaxact);
6094 
6095  /* @todo extend this to local/constraint probing */
6096 
6097  /* determine maximal contribution to the activity */
6098  for( v = nvars - 1; v >= 0; --v )
6099  {
6100  if( SCIPvarIsBinary(vars[v]) )
6101  {
6102  if( vals[v] > 0 )
6103  {
6104  SCIP_Real value = vals[v] * SCIPvarGetUbGlobal(vars[v]);
6105 
6106  if( value > maxabscontrib )
6107  {
6108  maxabscontrib = value;
6109  position = v;
6110  posval = TRUE;
6111  }
6112  }
6113  else
6114  {
6115  SCIP_Real value = vals[v] * SCIPvarGetLbGlobal(vars[v]);
6116 
6117  value = REALABS(value);
6118 
6119  if( value > maxabscontrib )
6120  {
6121  maxabscontrib = value;
6122  position = v;
6123  posval = FALSE;
6124  }
6125  }
6126  }
6127  else
6128  allbinary = FALSE;
6129  }
6130  assert(0 <= position && position < nvars);
6131 
6132  if( !SCIPisEQ(scip, maxabscontrib, 1.0) && !allbinary )
6133  {
6134  /* if the right hand side and the minimal activity are finite and changing the variable with the biggest
6135  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
6136  * implications
6137  */
6138  if( finiterhs && finiteminact && SCIPisEQ(scip, consdata->glbminactivity, consdata->rhs - maxabscontrib) )
6139  {
6140  for( v = nvars - 1; v >= 0; --v )
6141  {
6142  /* binary to binary implications will be collected when extrating cliques */
6143  if( !SCIPvarIsBinary(vars[v]) )
6144  {
6145  if( v != position )
6146  {
6147  if( vals[v] > 0 )
6148  {
6149  /* add implications */
6150  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
6151  ++nimpls;
6152  *nchgbds += nbdchgs;
6153  }
6154  else
6155  {
6156  /* add implications */
6157  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
6158  ++nimpls;
6159  *nchgbds += nbdchgs;
6160  }
6161 
6162  if( infeasible )
6163  {
6164  *cutoff = TRUE;
6165  break;
6166  }
6167  }
6168  }
6169  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
6170  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
6171  break;
6172  }
6173  }
6174 
6175  /* if the left hand side and the maximal activity are finite and changing the variable with the biggest
6176  * influence to their bound forces all other variables to be at their minimal contribution, we can add these
6177  * implications
6178  */
6179  if( finitelhs && finitemaxact && SCIPisEQ(scip, consdata->glbmaxactivity, consdata->lhs - maxabscontrib) )
6180  {
6181  for( v = nvars - 1; v >= 0; --v )
6182  {
6183  /* binary to binary implications will be collected when extrating cliques */
6184  if( !SCIPvarIsBinary(vars[v]) )
6185  {
6186  if( v != position )
6187  {
6188  if( vals[v] > 0 )
6189  {
6190  /* add implications */
6191  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_LOWER, SCIPvarGetUbGlobal(vars[v]), &infeasible, &nbdchgs) );
6192  ++nimpls;
6193  *nchgbds += nbdchgs;
6194  }
6195  else
6196  {
6197  /* add implications */
6198  SCIP_CALL( SCIPaddVarImplication(scip, vars[position], posval, vars[v], SCIP_BOUNDTYPE_UPPER, SCIPvarGetLbGlobal(vars[v]), &infeasible, &nbdchgs) );
6199  ++nimpls;
6200  *nchgbds += nbdchgs;
6201  }
6202 
6203  if( infeasible )
6204  {
6205  *cutoff = TRUE;
6206  break;
6207  }
6208  }
6209  }
6210  /* stop when reaching a 'real' binary variable because the variables are sorted after their type */
6211  else if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_BINARY )
6212  break;
6213  }
6214  }
6215 
6216  /* did we find some implications */
6217  if( nimpls > 0 )
6218  {
6219  SCIPdebugMessage("extracted %d implications from constraint %s which led to %d bound changes, %scutoff detetcted\n", nimpls, SCIPconsGetName(cons), *nchgbds - oldnchgbds, *cutoff ? "" : "no ");
6220 
6221  if( *cutoff )
6222  return SCIP_OKAY;
6223 
6224  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
6225  if( *nchgbds - oldnchgbds > 0 )
6226  {
6227  /* check for fixed variables */
6228  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6229  if( *cutoff )
6230  return SCIP_OKAY;
6231 
6232  /* tighten variable's bounds */
6233  SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
6234  if( *cutoff )
6235  return SCIP_OKAY;
6236 
6237  /* check for fixed variables */
6238  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6239  if( *cutoff )
6240  return SCIP_OKAY;
6241  }
6242  }
6243  }
6244  }
6245 
6246  consdata->implsadded = TRUE;
6247  }
6248 
6249  /* check if we already added the cliques of this constraint */
6250  if( consdata->cliquesadded )
6251  return SCIP_OKAY;
6252 
6253  consdata->cliquesadded = TRUE;
6254  cliquenonzerosadded = 0;
6255  stopped = FALSE;
6256 
6257  /* sort variables by variable type */
6258  SCIP_CALL( consdataSort(scip, consdata) );
6259 
6260  nvars = consdata->nvars;
6261  vars = consdata->vars;
6262  vals = consdata->vals;
6263 
6264  /**@todo extract more cliques, implications and variable bounds from linear constraints */
6265 
6266  /* recompute activities if needed */
6267  if( !consdata->validactivities )
6268  consdataCalcActivities(scip, consdata);
6269  assert(consdata->validactivities);
6270 
6271  finitelhs = !SCIPisInfinity(scip, -consdata->lhs);
6272  finiterhs = !SCIPisInfinity(scip, consdata->rhs);
6273  finitenegminact = (consdata->glbminactivityneginf == 0 && consdata->glbminactivityneghuge == 0);
6274  finitenegmaxact = (consdata->glbmaxactivityneginf == 0 && consdata->maxactivityneghuge == 0);
6275  finiteposminact = (consdata->glbminactivityposinf == 0 && consdata->glbminactivityposhuge == 0);
6276  finiteposmaxact = (consdata->glbmaxactivityposinf == 0 && consdata->glbmaxactivityposhuge == 0);
6277  finiteminact = (finitenegminact && finiteposminact);
6278  finitemaxact = (finitenegmaxact && finiteposmaxact);
6279 
6280  /* 1. we wheck whether some variables do not fit together into this constraint and add the corresponding clique
6281  * information
6282  */
6283  if( (finiterhs || finitelhs) && (finitenegminact || finiteposminact || finitenegmaxact || finiteposmaxact) )
6284  {
6285  SCIP_VAR** binvars;
6286  SCIP_Real* binvarvals;
6287  int nposbinvars = 0;
6288  int nnegbinvars = 0;
6289  int allonebinary = 0;
6290 
6291  SCIP_CALL( SCIPallocBufferArray(scip, &binvars, nvars) );
6292  SCIP_CALL( SCIPallocBufferArray(scip, &binvarvals, nvars) );
6293 
6294  /* collect binary variables */
6295  for( i = 0; i < nvars; ++i )
6296  {
6297  if( SCIPvarIsBinary(vars[i]) )
6298  {
6299  assert(!SCIPisZero(scip, vals[i]));
6300 
6301  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
6302  ++allonebinary;
6303 
6304  binvars[nposbinvars + nnegbinvars] = vars[i];
6305  binvarvals[nposbinvars + nnegbinvars] = vals[i];
6306 
6307  if( SCIPisPositive(scip, vals[i]) )
6308  ++nposbinvars;
6309  else
6310  ++nnegbinvars;
6311 
6312  assert(nposbinvars + nnegbinvars <= nvars);
6313  }
6314  /* stop searching for binary variables, because the constraint data is sorted */
6315  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
6316  break;
6317  }
6318  assert(nposbinvars + nnegbinvars <= nvars);
6319 
6320  /* setppc constraints will be handled later; we need at least two binary variables with same sign to extract
6321  * cliques
6322  */
6323  if( allonebinary < nvars && (nposbinvars >= 2 || nnegbinvars >= 2) )
6324  {
6325  SCIP_Real threshold;
6326  int oldnchgbds = *nchgbds;
6327  int nbdchgs;
6328  int jstart;
6329  int j;
6330 
6331  /* we need a valid minimal/maximal activity to add cliques */
6332  if( (finitenegminact || finiteposminact) && !consdata->validglbminact )
6333  {
6334  consdataRecomputeGlbMinactivity(scip, consdata);
6335  assert(consdata->validglbminact);
6336  }
6337 
6338  if( (finitenegmaxact || finiteposmaxact) && !consdata->validglbmaxact )
6339  {
6340  consdataRecomputeGlbMaxactivity(scip, consdata);
6341  assert(consdata->validglbmaxact);
6342  }
6343  assert(consdata->validglbminact || consdata->validglbmaxact);
6344 
6345  /* sort coefficients non-increasing to be faster in the clique search */
6346  SCIPsortDownRealPtr(binvarvals, (void**) binvars, nposbinvars + nnegbinvars);
6347 
6348  /* case a) */
6349  if( finiterhs && finitenegminact && nposbinvars >= 2 )
6350  {
6351  /* compute value that needs to be exceeded */
6352  threshold = consdata->rhs - consdata->glbminactivity;
6353 
6354  i = 0;
6355  j = i + 1;
6356 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
6357  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
6358  assert(SCIPisFeasLE(scip, binvarvals[i], threshold));
6359 #endif
6360  /* check if at least two variables are in a clique */
6361  if( SCIPisFeasGT(scip, binvarvals[i] + binvarvals[j], threshold) )
6362  {
6363  ++j;
6364  /* check for extending the clique */
6365  while( j < nposbinvars )
6366  {
6367  if( !SCIPisFeasGT(scip, binvarvals[j-1] + binvarvals[j], threshold) )
6368  break;
6369  ++j;
6370  }
6371  assert(j >= 2);
6372 
6373  /* add clique with at least two variables */
6374  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), NULL, j - i, &infeasible, &nbdchgs) );
6375 
6376  if( infeasible )
6377  *cutoff = TRUE;
6378 
6379  *nchgbds += nbdchgs;
6380 
6381  cliquenonzerosadded += j;
6382  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6383  stopped = TRUE;
6384 
6385  /* exchange the last variable in the clique if possible and add all new ones */
6386  if( !stopped && !(*cutoff) && j < nposbinvars )
6387  {
6388  SCIP_VAR** clqvars;
6389  int lastfit = j - 2;
6390  assert(lastfit >= i);
6391 
6392  /* copy all 'main'-clique variables */
6393  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
6394 
6395  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
6396  while( lastfit >= i && j < nposbinvars )
6397  {
6398  /* check if two variables are in a clique */
6399  if( SCIPisFeasGT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
6400  {
6401  clqvars[lastfit + 1] = binvars[j];
6402 
6403  /* add clique with at least two variables */
6404  SCIP_CALL( SCIPaddClique(scip, clqvars, NULL, lastfit - i + 2, &infeasible, &nbdchgs) );
6405 
6406  if( infeasible )
6407  {
6408  *cutoff = TRUE;
6409  break;
6410  }
6411 
6412  *nchgbds += nbdchgs;
6413 
6414  cliquenonzerosadded += (lastfit - i + 2);
6415  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6416  {
6417  stopped = TRUE;
6418  break;
6419  }
6420 
6421  ++j;
6422  }
6423  else
6424  --lastfit;
6425  }
6426 
6427  SCIPfreeBufferArray(scip, &clqvars);
6428  }
6429  }
6430  }
6431 
6432  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
6433  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
6434  {
6435  /* check for fixed variables */
6436  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6437 
6438  if( !*cutoff )
6439  {
6440  /* tighten variable's bounds */
6441  SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
6442 
6443  if( !*cutoff )
6444  {
6445  /* check for fixed variables */
6446  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6447 
6448  if( !*cutoff )
6449  {
6450  /* sort variables by variable type */
6451  SCIP_CALL( consdataSort(scip, consdata) );
6452 
6453  /* recompute activities if needed */
6454  if( !consdata->validactivities )
6455  consdataCalcActivities(scip, consdata);
6456  assert(consdata->validactivities);
6457 
6458  nvars = consdata->nvars;
6459  vars = consdata->vars;
6460  vals = consdata->vals;
6461  nposbinvars = 0;
6462  nnegbinvars = 0;
6463  allonebinary = 0;
6464 
6465  /* update binary variables */
6466  for( i = 0; i < nvars; ++i )
6467  {
6468  if( SCIPvarIsBinary(vars[i]) )
6469  {
6470  assert(!SCIPisZero(scip, vals[i]));
6471 
6472  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
6473  ++allonebinary;
6474 
6475  binvars[nposbinvars + nnegbinvars] = vars[i];
6476  binvarvals[nposbinvars + nnegbinvars] = vals[i];
6477 
6478  if( SCIPisPositive(scip, vals[i]) )
6479  ++nposbinvars;
6480  else
6481  ++nnegbinvars;
6482 
6483  assert(nposbinvars + nnegbinvars <= nvars);
6484  }
6485  /* stop searching for binary variables, because the constraint data is sorted */
6486  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
6487  break;
6488  }
6489  assert(nposbinvars + nnegbinvars <= nvars);
6490  }
6491  }
6492  }
6493 
6494  oldnchgbds = *nchgbds;
6495  }
6496 
6497  /* case b) */
6498  if( !stopped && !(*cutoff) && finitelhs && finiteposmaxact && nnegbinvars >= 2 )
6499  {
6500  /* compute value that needs to be deceeded */
6501  threshold = consdata->lhs - consdata->glbmaxactivity;
6502 
6503  i = nposbinvars + nnegbinvars - 1;
6504  j = i - 1;
6505 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
6506  /* check that it is possible to choose binvar[i], otherwise it should have been fixed to zero */
6507  assert(SCIPisFeasGE(scip, binvarvals[i], threshold));
6508 #endif
6509  /* check if two variables are in a clique */
6510  if( SCIPisFeasLT(scip, binvarvals[i] + binvarvals[j], threshold) )
6511  {
6512  --j;
6513  /* check for extending the clique */
6514  while( j >= nposbinvars )
6515  {
6516  if( !SCIPisFeasLT(scip, binvarvals[j+1] + binvarvals[j], threshold) )
6517  break;
6518  --j;
6519  }
6520  jstart = j;
6521 
6522  assert(i - j >= 2);
6523  /* add clique with at least two variables */
6524  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), NULL, i - j, &infeasible, &nbdchgs) );
6525 
6526  if( infeasible )
6527  *cutoff = TRUE;
6528 
6529  *nchgbds += nbdchgs;
6530 
6531  cliquenonzerosadded += (i - j);
6532  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6533  stopped = TRUE;
6534 
6535  /* exchange the last variable in the clique if possible and add all new ones */
6536  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
6537  {
6538  SCIP_VAR** clqvars;
6539  int lastfit = jstart + 1;
6540  assert(lastfit < i);
6541 
6542  /* copy all 'main'-clique variables */
6543  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
6544  ++lastfit;
6545 
6546  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
6547  while( lastfit <= i && j >= nposbinvars )
6548  {
6549  /* check if two variables are in a clique */
6550  if( SCIPisFeasLT(scip, binvarvals[lastfit] + binvarvals[j], threshold) )
6551  {
6552  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
6553  clqvars[lastfit - jstart - 2] = binvars[j];
6554 
6555  assert(i - lastfit + 2 >= 2);
6556  /* add clique with at least two variables */
6557  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), NULL, i - lastfit + 2, &infeasible, &nbdchgs) );
6558 
6559  if( infeasible )
6560  {
6561  *cutoff = TRUE;
6562  break;
6563  }
6564 
6565  *nchgbds += nbdchgs;
6566 
6567  cliquenonzerosadded += (i - lastfit + 2);
6568  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6569  {
6570  stopped = TRUE;
6571  break;
6572  }
6573 
6574  --j;
6575  }
6576  else
6577  ++lastfit;
6578  }
6579 
6580  SCIPfreeBufferArray(scip, &clqvars);
6581  }
6582  }
6583  }
6584 
6585  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
6586  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
6587  {
6588  /* check for fixed variables */
6589  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6590 
6591  if( !*cutoff )
6592  {
6593  /* tighten variable's bounds */
6594  SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
6595 
6596  if( !*cutoff )
6597  {
6598  /* check for fixed variables */
6599  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6600 
6601  if( !*cutoff )
6602  {
6603  /* sort variables by variable type */
6604  SCIP_CALL( consdataSort(scip, consdata) );
6605 
6606  /* recompute activities if needed */
6607  if( !consdata->validactivities )
6608  consdataCalcActivities(scip, consdata);
6609  assert(consdata->validactivities);
6610 
6611  nvars = consdata->nvars;
6612  vars = consdata->vars;
6613  vals = consdata->vals;
6614  nposbinvars = 0;
6615  nnegbinvars = 0;
6616  allonebinary = 0;
6617 
6618  /* update binary variables */
6619  for( i = 0; i < nvars; ++i )
6620  {
6621  if( SCIPvarIsBinary(vars[i]) )
6622  {
6623  assert(!SCIPisZero(scip, vals[i]));
6624 
6625  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
6626  ++allonebinary;
6627 
6628  binvars[nposbinvars + nnegbinvars] = vars[i];
6629  binvarvals[nposbinvars + nnegbinvars] = vals[i];
6630 
6631  if( SCIPisPositive(scip, vals[i]) )
6632  ++nposbinvars;
6633  else
6634  ++nnegbinvars;
6635 
6636  assert(nposbinvars + nnegbinvars <= nvars);
6637  }
6638  /* stop searching for binary variables, because the constraint data is sorted */
6639  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
6640  break;
6641  }
6642  assert(nposbinvars + nnegbinvars <= nvars);
6643  }
6644  }
6645  }
6646 
6647  oldnchgbds = *nchgbds;
6648  }
6649 
6650  /* case c) */
6651  if( !(*cutoff) && finiterhs && finiteminact && nnegbinvars >= 2 )
6652  {
6653  SCIP_Bool* values;
6654 
6655  /* initialize clique values array for adding a negated clique */
6656  SCIP_CALL( SCIPallocBufferArray(scip, &values, nnegbinvars) );
6657  BMSclearMemoryArray(values, nnegbinvars);
6658 
6659  /* compute value that needs to be exceeded */
6660  threshold = consdata->rhs - consdata->glbminactivity;
6661 
6662  i = nposbinvars + nnegbinvars - 1;
6663  j = i - 1;
6664 
6665 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
6666  /* check if the variable should not have already been fixed to one */
6667  assert(!SCIPisFeasGT(scip, binvarvals[i], threshold));
6668 #endif
6669 
6670  if( SCIPisFeasGT(scip, -binvarvals[i] - binvarvals[j], threshold) )
6671  {
6672  --j;
6673  /* check for extending the clique */
6674  while( j >= nposbinvars )
6675  {
6676  if( !SCIPisFeasGT(scip, -binvarvals[j+1] - binvarvals[j], threshold) )
6677  break;
6678  --j;
6679  }
6680  jstart = j;
6681 
6682  assert(i - j >= 2);
6683  /* add negated clique with at least two variables */
6684  SCIP_CALL( SCIPaddClique(scip, &(binvars[j+1]), values, i - j, &infeasible, &nbdchgs) );
6685 
6686  if( infeasible )
6687  *cutoff = TRUE;
6688 
6689  *nchgbds += nbdchgs;
6690 
6691  cliquenonzerosadded += (i - j);
6692  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6693  stopped = TRUE;
6694 
6695  /* exchange the last variable in the clique if possible and add all new ones */
6696  if( !stopped && !(*cutoff) && jstart >= nposbinvars )
6697  {
6698  SCIP_VAR** clqvars;
6699  int lastfit = j + 1;
6700  assert(lastfit < i);
6701 
6702  /* copy all 'main'-clique variables */
6703  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[lastfit]), i - j) );
6704  ++lastfit;
6705 
6706  /* iterate up to the front with j and up to the end with lastfit, and check for different cliques */
6707  while( lastfit <= i && j >= nposbinvars )
6708  {
6709  /* check if two variables are in a negated clique */
6710  if( SCIPisFeasGT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
6711  {
6712  assert(lastfit - jstart - 2 >= 0 && lastfit - jstart - 2 < i);
6713  clqvars[lastfit - jstart - 2] = binvars[j];
6714 
6715  assert(i - lastfit + 2 >= 2);
6716  /* add clique with at least two variables */
6717  SCIP_CALL( SCIPaddClique(scip, &(clqvars[lastfit - jstart - 2]), values, i - lastfit + 2, &infeasible, &nbdchgs) );
6718 
6719  if( infeasible )
6720  {
6721  *cutoff = TRUE;
6722  break;
6723  }
6724 
6725  *nchgbds += nbdchgs;
6726 
6727  cliquenonzerosadded += (i - lastfit + 2);
6728  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6729  {
6730  stopped = TRUE;
6731  break;
6732  }
6733 
6734  --j;
6735  }
6736  else
6737  ++lastfit;
6738  }
6739 
6740  SCIPfreeBufferArray(scip, &clqvars);
6741  }
6742  }
6743 
6744  SCIPfreeBufferArray(scip, &values);
6745  }
6746 
6747  /* did we find some boundchanges, then we need to remove fixings and tighten the bounds further */
6748  if( !stopped && !*cutoff && *nchgbds - oldnchgbds > 0 )
6749  {
6750  /* check for fixed variables */
6751  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6752 
6753  if( !*cutoff )
6754  {
6755  /* tighten variable's bounds */
6756  SCIP_CALL( tightenBounds(scip, cons, sortvars, cutoff, nchgbds) );
6757 
6758  if( !*cutoff )
6759  {
6760  /* check for fixed variables */
6761  SCIP_CALL( fixVariables(scip, cons, cutoff, nfixedvars) );
6762 
6763  if( !*cutoff )
6764  {
6765  /* sort variables by variable type */
6766  SCIP_CALL( consdataSort(scip, consdata) );
6767 
6768  /* recompute activities if needed */
6769  if( !consdata->validactivities )
6770  consdataCalcActivities(scip, consdata);
6771  assert(consdata->validactivities);
6772 
6773  nvars = consdata->nvars;
6774  vars = consdata->vars;
6775  vals = consdata->vals;
6776  nposbinvars = 0;
6777  nnegbinvars = 0;
6778  allonebinary = 0;
6779 
6780  /* update binary variables */
6781  for( i = 0; i < nvars; ++i )
6782  {
6783  if( SCIPvarIsBinary(vars[i]) )
6784  {
6785  assert(!SCIPisZero(scip, vals[i]));
6786 
6787  if( SCIPisEQ(scip, REALABS(vals[i]), 1.0) )
6788  ++allonebinary;
6789 
6790  binvars[nposbinvars + nnegbinvars] = vars[i];
6791  binvarvals[nposbinvars + nnegbinvars] = vals[i];
6792 
6793  if( SCIPisPositive(scip, vals[i]) )
6794  ++nposbinvars;
6795  else
6796  ++nnegbinvars;
6797 
6798  assert(nposbinvars + nnegbinvars <= nvars);
6799  }
6800  /* stop searching for binary variables, because the constraint data is sorted */
6801  else if( SCIPvarGetType(vars[i]) == SCIP_VARTYPE_CONTINUOUS )
6802  break;
6803  }
6804  assert(nposbinvars + nnegbinvars <= nvars);
6805  }
6806  }
6807  }
6808  }
6809 
6810  /* case d) */
6811  if( !stopped && !(*cutoff) && finitelhs && finitemaxact && nposbinvars >= 2 )
6812  {
6813  SCIP_Bool* values;
6814 
6815  /* initialize clique values array for adding a negated clique */
6816  SCIP_CALL( SCIPallocBufferArray(scip, &values, nposbinvars) );
6817  BMSclearMemoryArray(values, nposbinvars);
6818 
6819  /* compute value that needs to be exceeded */
6820  threshold = consdata->lhs - consdata->glbmaxactivity;
6821 
6822  i = 0;
6823  j = i + 1;
6824 
6825 #if 0 /* assertion should only holds when constraints were fully propagated and boundstightened */
6826  /* check if the variable should not have already been fixed to one */
6827  assert(!SCIPisFeasLT(scip, -binvarvals[i], threshold));
6828 #endif
6829 
6830  if( SCIPisFeasLT(scip, -binvarvals[i] - binvarvals[j], threshold) )
6831  {
6832  ++j;
6833  /* check for extending the clique */
6834  while( j < nposbinvars )
6835  {
6836  if( !SCIPisFeasLT(scip, -binvarvals[j-1] - binvarvals[j], threshold) )
6837  break;
6838  ++j;
6839  }
6840  assert(j >= 2);
6841 
6842  /* add negated clique with at least two variables */
6843  SCIP_CALL( SCIPaddClique(scip, &(binvars[i]), values, j - i, &infeasible, &nbdchgs) );
6844 
6845  if( infeasible )
6846  *cutoff = TRUE;
6847 
6848  *nchgbds += nbdchgs;
6849 
6850  cliquenonzerosadded += j;
6851  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6852  stopped = TRUE;
6853 
6854  /* exchange the last variable in the clique if possible and add all new ones */
6855  if( !stopped && !(*cutoff) && j < nposbinvars )
6856  {
6857  SCIP_VAR** clqvars;
6858  int lastfit = j - 2;
6859  assert(lastfit >= i);
6860 
6861  /* copy all 'main'-clique variables */
6862  SCIP_CALL( SCIPduplicateBufferArray(scip, &clqvars, &(binvars[i]), j - i) );
6863 
6864  /* iterate up to the end with j and up to the front with lastfit, and check for different cliques */
6865  while( lastfit >= i && j < nposbinvars )
6866  {
6867  /* check if two variables are in a negated clique */
6868  if( SCIPisFeasLT(scip, -binvarvals[lastfit] - binvarvals[j], threshold) )
6869  {
6870  clqvars[lastfit + 1] = binvars[j];
6871 
6872  /* add clique with at least two variables */
6873  SCIP_CALL( SCIPaddClique(scip, clqvars, values, lastfit - i + 2, &infeasible, &nbdchgs) );
6874 
6875  if( infeasible )
6876  {
6877  *cutoff = TRUE;
6878  break;
6879  }
6880 
6881  *nchgbds += nbdchgs;
6882 
6883  cliquenonzerosadded += (lastfit - i + 2);
6884  if( cliquenonzerosadded >= MAX_CLIQUE_NONZEROS_PER_CONS )
6885  break;
6886 
6887  ++j;
6888  }
6889  else
6890  --lastfit;
6891  }
6892 
6893  SCIPfreeBufferArray(scip, &clqvars);
6894  }
6895  }
6896 
6897  SCIPfreeBufferArray(scip, &values);
6898  }
6899  }
6900 
6901  SCIPfreeBufferArray(scip, &binvarvals);
6902  SCIPfreeBufferArray(scip, &binvars);
6903 
6904  if( *cutoff )
6905  return SCIP_OKAY;
6906  }
6907 
6908  /* 2. we only check if the constraint is a set packing / partitioning constraint */
6909 
6910  /* check if all variables are binary, if the coefficients are +1 or -1, and if the right hand side is equal
6911  * to 1 - number of negative coefficients, or if the left hand side is equal to number of positive coefficients - 1
6912  */
6913  nposcoefs = 0;
6914  nnegcoefs = 0;
6915  for( i = 0; i < nvars; ++i )
6916  {
6917  if( !SCIPvarIsBinary(vars[i]) )
6918  return SCIP_OKAY;
6919  else if( SCIPisEQ(scip, vals[i], +1.0) )
6920  nposcoefs++;
6921  else if( SCIPisEQ(scip, vals[i], -1.0) )
6922  nnegcoefs++;
6923  else
6924  return SCIP_OKAY;
6925  }
6926 
6927  lhsclique = SCIPisEQ(scip, consdata->lhs, (SCIP_Real)nposcoefs - 1.0);
6928  rhsclique = SCIPisEQ(scip, consdata->rhs, 1.0 - (SCIP_Real)nnegcoefs);
6929 
6930  if( lhsclique || rhsclique )
6931  {
6932  SCIP_Bool* values;
6933  int nbdchgs;
6934 
6935  SCIPdebugMessage("linear constraint <%s>: adding clique with %d vars (%d pos, %d neg)\n",
6936  SCIPconsGetName(cons), nvars, nposcoefs, nnegcoefs);
6937  SCIP_CALL( SCIPallocBufferArray(scip, &values, nvars) );
6938 
6939  for( i = 0; i < nvars; ++i )
6940  values[i] = (rhsclique == (vals[i] > 0.0));
6941 
6942  SCIP_CALL( SCIPaddClique(scip, vars, values, nvars, &infeasible, &nbdchgs) );
6943 
6944  if( infeasible )
6945  *cutoff = TRUE;
6946 
6947  *nchgbds += nbdchgs;
6948  SCIPfreeBufferArray(scip, &values);
6949  }
6950 
6951  return SCIP_OKAY;
6952 }
6953 
6954 /** tightens left and right hand side of constraint due to integrality */
6955 static
6957  SCIP* scip, /**< SCIP data structure */
6958  SCIP_CONS* cons, /**< linear constraint */
6959  int* nchgsides /**< pointer to count number of side changes */
6960  )
6961 {
6962  SCIP_CONSDATA* consdata;
6963  SCIP_Bool integral;
6964  int i;
6965 
6966  assert(scip != NULL);
6967  assert(cons != NULL);
6968  assert(nchgsides != NULL);
6969 
6970  consdata = SCIPconsGetData(cons);
6971  assert(consdata != NULL);
6972 
6973  if( !SCIPisIntegral(scip, consdata->lhs) || !SCIPisIntegral(scip, consdata->rhs) )
6974  {
6975  integral = TRUE;
6976  for( i = 0; i < consdata->nvars && integral; ++i )
6977  {
6978  integral = SCIPisIntegral(scip, consdata->vals[i])
6979  && (SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS);
6980  }
6981  if( integral )
6982  {
6983  SCIPdebugMessage("linear constraint <%s>: make sides integral: sides=[%.15g,%.15g]\n",
6984  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
6985  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisIntegral(scip, consdata->lhs) )
6986  {
6987  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
6988  if( !consdata->upgraded )
6989  (*nchgsides)++;
6990  }
6991  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisIntegral(scip, consdata->rhs) )
6992  {
6993  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
6994  if( !consdata->upgraded )
6995  (*nchgsides)++;
6996  }
6997  SCIPdebugMessage("linear constraint <%s>: new integral sides: sides=[%.15g,%.15g]\n",
6998  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
6999  }
7000  }
7001 
7002  return SCIP_OKAY;
7003 }
7004 
7005 #define MAXVALRECOMP 1e+06
7006 
7007 /** tightens coefficients of binary, integer, and implicit integer variables due to activity bounds in presolving:
7008  * given an inequality lhs <= a*x + ai*xi <= rhs, with a non-continuous variable li <= xi <= ui
7009  * let minact := min{a*x + ai*xi}, maxact := max{a*x + ai*xi}
7010  * (i) ai >= 0:
7011  * if minact + ai >= lhs and maxact - ai <= rhs: (**)
7012  * - a deviation from the lower/upper bound of xi would make the left/right hand side redundant
7013  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
7014  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
7015  * - change coefficients:
7016  * ai' := max(lhs - minact, maxact - rhs)
7017  * lhs' := lhs - (ai - ai')*li
7018  * rhs' := rhs - (ai - ai')*ui
7019  * (ii) ai < 0:
7020  * if minact - ai >= lhs and maxact + ai <= rhs: (***)
7021  * - a deviation from the upper/lower bound of xi would make the left/right hand side redundant
7022  * - ai, lhs and rhs can be changed to have the same redundancy effect and the same results for
7023  * xi fixed to its bounds, but with a reduced ai and tightened sides to tighten the LP relaxation
7024  * - change coefficients:
7025  * ai' := min(rhs - maxact, minact - lhs)
7026  * lhs' := lhs - (ai - ai')*ui
7027  * rhs' := rhs - (ai - ai')*li
7028  *
7029  * We further try to remove redundant variable from the constraint;
7030  * Variables which fulfill conditions (**) or (***) are called surely non-redundant variables.
7031  * A deviation of only one from their bound makes the lhs/rhs feasible (i.e., redundant), even if all other
7032  * variables are set to their "worst" bound. If all variables which are not surely non-redundant cannot make
7033  * the lhs/rhs redundant, even if they are set to their "best" bound, they can be removed from the constraint.
7034  * 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
7035  * suffices to fulfill the inequality, whereas the x_i do not contribute to feasibility and can be removed.
7036  *
7037  * @todo use also some tightening procedures for (knapsack) constraints with non-integer coefficients, see
7038  * cons_knapsack.c the following methods detectRedundantVars() and tightenWeights()
7039  */
7040 static
7042  SCIP* scip, /**< SCIP data structure */
7043  SCIP_CONS* cons, /**< linear constraint */
7044  int* nchgcoefs, /**< pointer to count total number of changed coefficients */
7045  int* nchgsides /**< pointer to count number of side changes */
7046  )
7047 {
7048  SCIP_CONSDATA* consdata;
7049  SCIP_VAR* var;
7050  SCIP_Real minactivity; /* minimal value w.r.t. the variable's local bounds for the constraint's
7051  * activity, ignoring the coefficients contributing with infinite value */
7052  SCIP_Real maxactivity; /* maximal value w.r.t. the variable's local bounds for the constraint's
7053  * activity, ignoring the coefficients contributing with infinite value */
7054  SCIP_Bool minactisrelax; /* do huge finite values contribute to the minactivity? */
7055  SCIP_Bool maxactisrelax; /* do huge finite values contribute to the maxactivity? */
7056  SCIP_Real minleftactivity; /* minimal activity without surely non-redundant variables. */
7057  SCIP_Real maxleftactivity; /* maximal activity without surely non-redundant variables. */
7058  SCIP_Real aggrlhs; /* lhs without minimal activity of surely non-redundant variables. */
7059  SCIP_Real aggrrhs; /* rhs without maximal activity of surely non-redundant variables. */
7060  SCIP_Real lval; /* candidate for new value arising from considering the left hand side */
7061  SCIP_Real rval; /* candidate for new value arising from considering the left hand side */
7062  SCIP_Real val;
7063  SCIP_Real newval;
7064  SCIP_Real newlhs;
7065  SCIP_Real newrhs;
7066  SCIP_Real lb;
7067  SCIP_Real ub;
7068  int i;
7069 
7070  assert(scip != NULL);
7071  assert(cons != NULL);
7072  assert(nchgcoefs != NULL);
7073  assert(nchgsides != NULL);
7074 
7075  consdata = SCIPconsGetData(cons);
7076  assert(consdata != NULL);
7077 
7078  /* @todo Is this still needed with automatic recomputation of activities? */
7079  /* if the maximal coefficient is too large, recompute the activities */
7080  if( consdata->validmaxabsval && consdata->maxabsval > MAXVALRECOMP )
7081  {
7082  consdataRecomputeMinactivity(scip, consdata);
7083  consdataRecomputeMaxactivity(scip, consdata);
7084  }
7085 
7086  /* get the minimal and maximal activity of the constraint */
7087  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7088 
7089  minleftactivity = 0.0;
7090  maxleftactivity = 0.0;
7091 
7092  /* try to tighten each coefficient */
7093  i = 0;
7094  while( i < consdata->nvars )
7095  {
7096  var = consdata->vars[i];
7097 
7098  /* get coefficient and variable's bounds */
7099  lb = SCIPvarGetLbLocal(var);
7100  ub = SCIPvarGetUbLocal(var);
7101  val = consdata->vals[i];
7102  assert(!SCIPisZero(scip, val));
7103 
7104  /* check sign of coefficient */
7105  if( val >= 0.0 )
7106  {
7107  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
7109  SCIPisGE(scip, minactivity + val, consdata->lhs) && SCIPisLE(scip, maxactivity - val, consdata->rhs) )
7110  {
7111  /* change coefficients:
7112  * ai' := max(lhs - minact, maxact - rhs)
7113  * lhs' := lhs - (ai - ai')*li
7114  * rhs' := rhs - (ai - ai')*ui
7115  */
7116 
7117  lval = consdata->lhs - minactivity;
7118  rval = maxactivity - consdata->rhs;
7119 
7120  /* Try to avoid cancellation, if there are only two variables */
7121  if( consdata->nvars == 2 )
7122  {
7123  SCIP_Real otherval;
7124  otherval = consdata->vals[1-i];
7125 
7126  if( !SCIPisInfinity(scip, -consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
7127  {
7128  lval = consdata->lhs - val*lb;
7129  lval -= otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
7130  }
7131 
7132  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
7133  {
7134  rval = val*ub - consdata->rhs;
7135  rval += otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
7136  }
7137  }
7138 
7139  newval = MAX(lval, rval);
7140  assert(SCIPisSumRelLE(scip, newval, val));
7141 
7142  /* Try to avoid cancellation in computation of lhs/rhs */
7143  newlhs = consdata->lhs - val * lb;
7144  newlhs += newval * lb;
7145  newrhs = consdata->rhs - val * ub;
7146  newrhs += newval * ub;
7147 
7148  if( !SCIPisSumRelEQ(scip, newval, val) )
7149  {
7150  SCIPdebugMessage("linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
7151  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
7152  minactivity, maxactivity, consdata->lhs, consdata->rhs);
7153 
7154  /* update the coefficient and the activity bounds */
7155  if( SCIPisZero(scip, newval) )
7156  {
7157  SCIP_CALL( delCoefPos(scip, cons, i) );
7158  i--;
7159  }
7160  else
7161  {
7162  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
7163  }
7164  (*nchgcoefs)++;
7165 
7166  /* get the new minimal and maximal activity of the constraint */
7167  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7168 
7169  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
7170  {
7171  SCIPdebugMessage("linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
7172 
7173  SCIP_CALL( chgLhs(scip, cons, newlhs) );
7174  (*nchgsides)++;
7175  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
7176  }
7177 
7178  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
7179  {
7180  SCIPdebugMessage("linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
7181 
7182  SCIP_CALL( chgRhs(scip, cons, newrhs) );
7183  (*nchgsides)++;
7184  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
7185  }
7186  }
7187  }
7188  else
7189  {
7190  if( !SCIPisInfinity(scip, -minleftactivity) )
7191  {
7192  assert(!SCIPisInfinity(scip, val));
7193  assert(!SCIPisInfinity(scip, lb));
7194  if( SCIPisInfinity(scip, -lb) )
7195  minleftactivity = -SCIPinfinity(scip);
7196  else
7197  minleftactivity += val * lb;
7198  }
7199 
7200  if( !SCIPisInfinity(scip, maxleftactivity) )
7201  {
7202  assert(!SCIPisInfinity(scip, val));
7203  assert(!SCIPisInfinity(scip, -ub));
7204  if( SCIPisInfinity(scip,ub) )
7205  maxleftactivity = SCIPinfinity(scip);
7206  else
7207  maxleftactivity += val * ub;
7208  }
7209  }
7210  }
7211  else
7212  {
7213  /* check, if a deviation from lower/upper bound would make lhs/rhs redundant */
7215  SCIPisGE(scip, minactivity - val, consdata->lhs) && SCIPisLE(scip, maxactivity + val, consdata->rhs) )
7216  {
7217  /* change coefficients:
7218  * ai' := min(rhs - maxact, minact - lhs)
7219  * lhs' := lhs - (ai - ai')*ui
7220  * rhs' := rhs - (ai - ai')*li
7221  */
7222 
7223  lval = minactivity - consdata->lhs;
7224  rval = consdata->rhs - maxactivity;
7225 
7226  /* Try to avoid cancellation, if there are only two variables */
7227  if( consdata->nvars == 2 )
7228  {
7229  SCIP_Real otherval;
7230  otherval = consdata->vals[1-i];
7231 
7232  if( !SCIPisInfinity(scip,-consdata->lhs) && consdata->minactivityneginf + consdata->minactivityneginf == 0 )
7233  {
7234  lval = val*ub - consdata->lhs;
7235  lval += otherval > 0.0 ? otherval * SCIPvarGetLbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetUbLocal(consdata->vars[1-i]);
7236  }
7237 
7238  if( !SCIPisInfinity(scip,consdata->rhs) && consdata->maxactivityneginf + consdata->maxactivityneginf == 0 )
7239  {
7240  rval = consdata->rhs - val*lb;
7241  rval -= otherval > 0.0 ? otherval * SCIPvarGetUbLocal(consdata->vars[1-i]) : otherval * SCIPvarGetLbLocal(consdata->vars[1-i]);
7242  }
7243  }
7244 
7245  newval = MIN(lval, rval);
7246  assert(SCIPisSumRelGE(scip, newval, val));
7247 
7248  /* Try to avoid cancellation in computation of lhs/rhs */
7249  newlhs = consdata->lhs - val * ub;
7250  newlhs += newval * ub;
7251  newrhs = consdata->rhs - val * lb;
7252  newrhs += newval * lb;
7253 
7254  if( !SCIPisSumRelEQ(scip, newval, val) )
7255  {
7256  SCIPdebugMessage("linear constraint <%s>: change coefficient %+.15g<%s> to %+.15g<%s>, act=[%.15g,%.15g], side=[%.15g,%.15g]\n",
7257  SCIPconsGetName(cons), val, SCIPvarGetName(var), newval, SCIPvarGetName(var),
7258  minactivity, maxactivity, consdata->lhs, consdata->rhs);
7259 
7260  /* update the coefficient and the activity bounds */
7261  if( SCIPisZero(scip, newval) )
7262  {
7263  SCIP_CALL( delCoefPos(scip, cons, i) );
7264  i--;
7265  }
7266  else
7267  {
7268  SCIP_CALL( chgCoefPos(scip, cons, i, newval) );
7269  }
7270  (*nchgcoefs)++;
7271 
7272  /* get the new minimal and maximal activity of the constraint */
7273  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7274 
7275  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisEQ(scip, newlhs, consdata->lhs) )
7276  {
7277  SCIPdebugMessage("linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
7278 
7279  SCIP_CALL( chgLhs(scip, cons, newlhs) );
7280  (*nchgsides)++;
7281  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
7282  }
7283 
7284  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisEQ(scip, newrhs, consdata->rhs) )
7285  {
7286  SCIPdebugMessage("linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
7287 
7288  SCIP_CALL( chgRhs(scip, cons, newrhs) );
7289  (*nchgsides)++;
7290  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
7291  }
7292  }
7293  }
7294  else
7295  {
7296  if( !SCIPisInfinity(scip, -minleftactivity) )
7297  {
7298  assert(!SCIPisInfinity(scip, -val));
7299  assert(!SCIPisInfinity(scip, -ub));
7300  if( SCIPisInfinity(scip, ub) )
7301  minleftactivity = -SCIPinfinity(scip);
7302  else
7303  minleftactivity += val * ub;
7304  }
7305 
7306  if( !SCIPisInfinity(scip, maxleftactivity) )
7307  {
7308  assert(!SCIPisInfinity(scip, -val));
7309  assert(!SCIPisInfinity(scip, lb));
7310  if( SCIPisInfinity(scip, -lb) )
7311  maxleftactivity = SCIPinfinity(scip);
7312  else
7313  maxleftactivity += val * lb;
7314  }
7315  }
7316  }
7317  ++i;
7318  }
7319 
7320  SCIPdebugMessage("minleftactivity = %.15g, rhs = %.15g\n",
7321  minleftactivity, consdata->rhs);
7322  SCIPdebugMessage("maxleftactivity = %.15g, lhs = %.15g\n",
7323  maxleftactivity, consdata->lhs);
7324 
7325  /* minleft == \infty ==> minactivity == \infty */
7326  assert(!SCIPisInfinity(scip, -minleftactivity) || SCIPisInfinity(scip, -minactivity));
7327  assert(!SCIPisInfinity(scip, maxleftactivity) || SCIPisInfinity(scip, maxactivity));
7328 
7329  /* if the lhs is finite, we will check in the following whether the not non-redundant variables can make lhs feasible;
7330  * this is not valid, if the minactivity is -\infty (aggrlhs would be minus infinity in the following computation)
7331  * or if huge values contributed to the minactivity, because the minactivity is then just a relaxation
7332  * (<= the exact minactivity), and we might falsely claim variables to be redundant in the following
7333  */
7334  assert(!SCIPisInfinity(scip, minactivity));
7335  if( !SCIPisInfinity(scip, -consdata->lhs) && (SCIPisInfinity(scip, -minactivity) || minactisrelax) )
7336  return SCIP_OKAY;
7337 
7338  /* if the rhs is finite, we will check in the following whether the not non-redundant variables can make rhs feasible;
7339  * this is not valid, if the maxactivity is \infty (aggrrhs would be infinity in the following computation)
7340  * or if huge values contributed to the maxactivity, because the maxactivity is then just a relaxation
7341  * (>= the exact maxactivity), and we might falsely claim variables to be redundant in the following
7342  */
7343  assert(!SCIPisInfinity(scip, -maxactivity));
7344  if( !SCIPisInfinity(scip, consdata->rhs) && (SCIPisInfinity(scip, maxactivity) || maxactisrelax) )
7345  return SCIP_OKAY;
7346 
7347  /* correct lhs and rhs by min/max activity of surely non-redundant variables
7348  * surely non-redundant variables are all those where a deviation from the bound makes the lhs/rhs redundant
7349  */
7350  aggrlhs = consdata->lhs - minactivity + minleftactivity;
7351  aggrrhs = consdata->rhs - maxactivity + maxleftactivity;
7352 
7353  /* check if the constraint contains variables which are redundant. The reasoning is the following:
7354  * Each non-redundant variable can make the lhs/rhs feasible with a deviation of only one in the bound.
7355  * If _all_ variables which are not non-redundant together cannot make lhs/rhs feasible,
7356  * they can be removed from the constraint.
7357  * aggrrhs may contain some near-infinity value, but only if rhs is infinity.
7358  */
7359  if( (SCIPisInfinity(scip, -consdata->lhs) || SCIPisFeasLT(scip, maxleftactivity, aggrlhs))
7360  && (SCIPisInfinity(scip, consdata->rhs) || SCIPisFeasGT(scip, minleftactivity, aggrrhs)) )
7361  {
7362  SCIP_Real minleftactivitypart;
7363  SCIP_Real maxleftactivitypart;
7364 
7365  assert(!SCIPisInfinity(scip, -consdata->lhs) || !SCIPisInfinity(scip, consdata->rhs));
7366 
7367  /* try to remove redundant variables from constraint */
7368  i = 0;
7369  while( i < consdata->nvars )
7370  {
7371  var = consdata->vars[i];
7372  minleftactivitypart = 0.0;
7373  maxleftactivitypart = 0.0;
7374  lb = SCIPvarGetLbLocal(var);
7375  ub = SCIPvarGetUbLocal(var);
7376 
7377  /* get coefficient and variable's bounds */
7378  val = consdata->vals[i];
7379  assert(!SCIPisZero(scip, val));
7380 
7381  /* check sign of coefficient */
7382  if( val >= 0.0 )
7383  {
7384  /* negation of condition above in case of positive val */
7385  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
7386  SCIPisLT(scip, minactivity + val, consdata->lhs) || SCIPisGT(scip, maxactivity - val, consdata->rhs) )
7387  {
7388  SCIPdebugMessage("minactivity = %g\tval = %g\tlhs = %g\n", minactivity, val, consdata->lhs);
7389  SCIPdebugMessage("maxactivity = %g\tval = %g\trhs = %g\n", maxactivity, val, consdata->rhs);
7390  SCIPdebugMessage("linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
7391  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
7392 
7393  minleftactivitypart = val * lb;
7394  maxleftactivitypart = val * ub;
7395 
7396  SCIP_CALL( delCoefPos(scip, cons, i) );
7397  i--;
7398 
7399  /* get the new minimal and maximal activity of the constraint */
7400  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7401 
7402  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
7403  * huge contributions
7404  */
7405  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
7406  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
7407  }
7408  }
7409  else
7410  {
7411  /* negation of condition above in case of negative val */
7412  if( SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ||
7413  SCIPisLT(scip, minactivity - val, consdata->lhs) || SCIPisGT(scip, maxactivity + val, consdata->rhs) )
7414  {
7415  SCIPdebugMessage("linear constraint <%s>: remove variable <%s> with coefficient <%g> from constraint since it is redundant\n",
7416  SCIPconsGetName(cons), SCIPvarGetName(consdata->vars[i]), val);
7417 
7418  minleftactivitypart = val * ub;
7419  maxleftactivitypart = val * lb;
7420 
7421  SCIP_CALL( delCoefPos(scip, cons, i) );
7422  i--;
7423 
7424  /* get the new minimal and maximal activity of the constraint */
7425  consdataGetActivityBounds(scip, consdata, FALSE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
7426 
7427  /* we return above if the condition does not hold and deleting a variable cannot increase the number of
7428  * huge contributions
7429  */
7430  assert(!minactisrelax || SCIPisInfinity(scip, -consdata->lhs));
7431  assert(!maxactisrelax || SCIPisInfinity(scip, consdata->rhs));
7432  }
7433  }
7434 
7435  /* the following update step is needed in every iteration cause otherwise it is possible that the surely none-
7436  * redundant variables could get deleted,
7437  * e.g. y_1 + 16y_2 >= 25, y1 with bounds [9,12], y2 with bounds [0,2], minactivity would be 9, it follows that
7438  * y_2 is surely not redundant and y_1 is redundant so we would first delete y1 and without updating the sides
7439  * we would also delete y2 and as a result we would have gotten infeasibility */
7440  /* adjust lhs and right hand side */
7441  newlhs = consdata->lhs - minleftactivitypart;
7442  newrhs = consdata->rhs - maxleftactivitypart;
7443 
7444  if( !SCIPisInfinity(scip, -consdata->lhs) && !SCIPisFeasEQ(scip, newlhs, consdata->lhs) )
7445  {
7446  SCIPdebugMessage("linear constraint <%s>: change lhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->lhs, newlhs);
7447  SCIP_CALL( chgLhs(scip, cons, newlhs) );
7448  ++(*nchgsides);
7449  assert(SCIPisEQ(scip, consdata->lhs, newlhs));
7450  }
7451  if( !SCIPisInfinity(scip, consdata->rhs) && !SCIPisFeasEQ(scip, newrhs, consdata->rhs) )
7452  {
7453  SCIPdebugMessage("linear constraint <%s>: change rhs %.15g to %.15g\n", SCIPconsGetName(cons), consdata->rhs, newrhs);
7454  SCIP_CALL( chgRhs(scip, cons, newrhs) );
7455  ++(*nchgsides);
7456  assert(SCIPisEQ(scip, consdata->rhs, newrhs));
7457  }
7458  ++i;
7459  }
7460  }
7461 
7462  return SCIP_OKAY;
7463 }
7464 
7465 /* processes equality with only one variable by fixing the variable and deleting the constraint */
7466 static
7468  SCIP* scip, /**< SCIP data structure */
7469  SCIP_CONS* cons, /**< linear constraint */
7470  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7471  int* nfixedvars, /**< pointer to count number of fixed variables */
7472  int* ndelconss /**< pointer to count number of deleted constraints */
7473  )
7474 {
7475  SCIP_CONSDATA* consdata;
7476  SCIP_VAR* var;
7477  SCIP_Real val;
7478  SCIP_Real fixval;
7479  SCIP_Bool infeasible;
7480  SCIP_Bool fixed;
7481 
7482  assert(scip != NULL);
7483  assert(cons != NULL);
7484  assert(cutoff != NULL);
7485  assert(nfixedvars != NULL);
7486  assert(ndelconss != NULL);
7487 
7488  consdata = SCIPconsGetData(cons);
7489  assert(consdata != NULL);
7490  assert(consdata->nvars == 1);
7491  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
7492 
7493  /* calculate the value to fix the variable to */
7494  var = consdata->vars[0];
7495  val = consdata->vals[0];
7496  assert(!SCIPisZero(scip, val));
7497  fixval = SCIPselectSimpleValue(consdata->lhs/val - 0.9 * SCIPepsilon(scip),
7498  consdata->rhs/val + 0.9 * SCIPepsilon(scip), MAXDNOM);
7499  SCIPdebugMessage("linear equality <%s>: fix <%s> == %.15g\n",
7500  SCIPconsGetName(cons), SCIPvarGetName(var), fixval);
7501 
7502  /* fix variable */
7503  SCIP_CALL( SCIPfixVar(scip, var, fixval, &infeasible, &fixed) );
7504  if( infeasible )
7505  {
7506  SCIPdebugMessage(" -> infeasible fixing\n");
7507  *cutoff = TRUE;
7508  return SCIP_OKAY;
7509  }
7510  if( fixed )
7511  (*nfixedvars)++;
7512 
7513  /* disable constraint */
7514  SCIP_CALL( SCIPdelCons(scip, cons) );
7515  if( !consdata->upgraded )
7516  (*ndelconss)++;
7517 
7518  return SCIP_OKAY;
7519 }
7520 
7521 /* processes equality with exactly two variables by aggregating one of the variables and deleting the constraint */
7522 static
7524  SCIP* scip, /**< SCIP data structure */
7525  SCIP_CONS* cons, /**< linear constraint */
7526  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7527  int* naggrvars, /**< pointer to count number of aggregated variables */
7528  int* ndelconss /**< pointer to count number of deleted constraints */
7529  )
7530 {
7531  SCIP_CONSDATA* consdata;
7532  SCIP_Bool infeasible;
7533  SCIP_Bool redundant;
7534  SCIP_Bool aggregated;
7535 
7536  assert(scip != NULL);
7537  assert(cons != NULL);
7538  assert(cutoff != NULL);
7539  assert(naggrvars != NULL);
7540  assert(ndelconss != NULL);
7541 
7542  consdata = SCIPconsGetData(cons);
7543  assert(consdata != NULL);
7544  assert(consdata->nvars == 2);
7545  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
7546 
7547  SCIPdebugMessage("linear constraint <%s>: aggregate %.15g<%s> + %.15g<%s> == %.15g\n",
7548  SCIPconsGetName(cons), consdata->vals[0], SCIPvarGetName(consdata->vars[0]),
7549  consdata->vals[1], SCIPvarGetName(consdata->vars[1]), consdata->rhs);
7550 
7551  /* aggregate the equality */
7552  SCIP_CALL( SCIPaggregateVars(scip, consdata->vars[0], consdata->vars[1], consdata->vals[0], consdata->vals[1],
7553  consdata->rhs, &infeasible, &redundant, &aggregated) );
7554 
7555  /* check for infeasibility of aggregation */
7556  if( infeasible )
7557  {
7558  SCIPdebugMessage(" -> infeasible aggregation\n");
7559  *cutoff = TRUE;
7560  return SCIP_OKAY;
7561  }
7562 
7563  /* count the aggregation */
7564  if( aggregated )
7565  (*naggrvars)++;
7566 
7567  /* delete the constraint, if it is redundant */
7568  if( redundant )
7569  {
7570  SCIP_CALL( SCIPdelCons(scip, cons) );
7571 
7572  if( !consdata->upgraded )
7573  (*ndelconss)++;
7574  }
7575 
7576  return SCIP_OKAY;
7577 }
7578 
7579 /** calculates the new lhs and rhs of the constraint after the given variable is aggregated out */
7580 static
7582  SCIP* scip, /**< SCIP data structure */
7583  SCIP_CONSDATA* consdata, /**< linear constraint data */
7584  SCIP_VAR* slackvar, /**< variable to be aggregated out */
7585  SCIP_Real slackcoef, /**< coefficient of variable in constraint */
7586  SCIP_Real* newlhs, /**< pointer to store new lhs of constraint */
7587  SCIP_Real* newrhs /**< pointer to store new rhs of constraint */
7588  )
7589 {
7590  SCIP_Real slackvarlb;
7591  SCIP_Real slackvarub;
7592 
7593  assert(scip != NULL);
7594  assert(consdata != NULL);
7595  assert(newlhs != NULL);
7596  assert(newrhs != NULL);
7597  assert(!SCIPisInfinity(scip, -consdata->lhs));
7598  assert(!SCIPisInfinity(scip, consdata->rhs));
7599 
7600  slackvarlb = SCIPvarGetLbGlobal(slackvar);
7601  slackvarub = SCIPvarGetUbGlobal(slackvar);
7602  if( slackcoef > 0.0 )
7603  {
7604  if( SCIPisInfinity(scip, -slackvarlb) )
7605  *newrhs = SCIPinfinity(scip);
7606  else
7607  *newrhs = consdata->rhs - slackcoef * slackvarlb;
7608  if( SCIPisInfinity(scip, slackvarub) )
7609  *newlhs = -SCIPinfinity(scip);
7610  else
7611  *newlhs = consdata->lhs - slackcoef * slackvarub;
7612  }
7613  else
7614  {
7615  if( SCIPisInfinity(scip, -slackvarlb) )
7616  *newlhs = -SCIPinfinity(scip);
7617  else
7618  *newlhs = consdata->rhs - slackcoef * slackvarlb;
7619  if( SCIPisInfinity(scip, slackvarub) )
7620  *newrhs = SCIPinfinity(scip);
7621  else
7622  *newrhs = consdata->lhs - slackcoef * slackvarub;
7623  }
7624  assert(SCIPisLE(scip, *newlhs, *newrhs));
7625 }
7626 
7627 #define MAXMULTIAGGRQUOTIENT 1e+03
7628 
7629 /* processes equality with more than two variables by multi-aggregating one of the variables and converting the equality
7630  * into an inequality; if multi-aggregation is not possible, tries to identify one continuous or integer variable that
7631  * is implicitly integral by this constraint
7632  *
7633  * @todo Check whether a more clever way of avoiding aggregation of variables containing implicitly integer variables
7634  * can help.
7635  */
7636 static
7638  SCIP* scip, /**< SCIP data structure */
7639  SCIP_CONS* cons, /**< linear constraint */
7640  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
7641  int* naggrvars, /**< pointer to count number of aggregated variables */
7642  int* ndelconss /**< pointer to count number of deleted constraints */
7643  )
7644 {
7645  SCIP_CONSDATA* consdata;
7646  SCIP_VAR** vars;
7647  SCIP_Real* vals;
7648  SCIP_VARTYPE bestslacktype;
7649  SCIP_VARTYPE slacktype;
7650  SCIP_Real lhs;
7651  SCIP_Real rhs;
7652  SCIP_Real bestslackdomrng;
7653  SCIP_Real minabsval;
7654  SCIP_Real maxabsval;
7655  SCIP_Bool bestremovescons;
7656  SCIP_Bool coefszeroone;
7657  SCIP_Bool coefsintegral;
7658  SCIP_Bool varsintegral;
7659  SCIP_Bool infeasible;
7660  SCIP_Bool samevar;
7661  int supinf; /* counter for infinite contributions to the supremum of a possible
7662  * multi-aggregation
7663  */
7664  int infinf; /* counter for infinite contributions to the infimum of a possible
7665  * multi-aggregation
7666  */
7667  int maxnlocksstay;
7668  int maxnlocksremove;
7669  int bestslackpos;
7670  int bestnlocks;
7671  int ncontvars;
7672  int contvarpos;
7673  int nintvars;
7674  int nimplvars;
7675  int intvarpos;
7676  int v;
7677 
7678  assert(scip != NULL);
7679  assert(cons != NULL);
7680  assert(cutoff != NULL);
7681  assert(naggrvars != NULL);
7682 
7683  consdata = SCIPconsGetData(cons);
7684  assert(consdata != NULL);
7685  assert(consdata->nvars > 2);
7686  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
7687 
7688  SCIPdebugMessage("linear constraint <%s>: try to multi-aggregate equality\n", SCIPconsGetName(cons));
7689 
7690  /* We do not want to increase the total number of non-zeros due to the multi-aggregation.
7691  * Therefore, we have to restrict the number of locks of a variable that is aggregated out.
7692  * maxnlocksstay: maximal sum of lock numbers if the constraint does not become redundant after the aggregation
7693  * maxnlocksremove: maximal sum of lock numbers if the constraint can be deleted after the aggregation
7694  */
7695  lhs = consdata->lhs;
7696  rhs = consdata->rhs;
7697  maxnlocksstay = 0;
7698  if( consdata->nvars == 3 )
7699  {
7700  /* If the constraint becomes redundant, 3 non-zeros are removed, and we get 1 additional non-zero for each
7701  * constraint the variable appears in. Thus, the variable must appear in at most 3 other constraints.
7702  */
7703  maxnlocksremove = 3;
7704  }
7705  else if( consdata->nvars == 4 )
7706  {
7707  /* If the constraint becomes redundant, 4 non-zeros are removed, and we get 2 additional non-zeros for each
7708  * constraint the variable appears in. Thus, the variable must appear in at most 2 other constraints.
7709  */
7710  maxnlocksremove = 2;
7711  }
7712  else
7713  {
7714  /* If the constraint is redundant but has more than 4 variables, we can only accept one other constraint. */
7715  maxnlocksremove = 1;
7716  }
7717 
7718  /* the locks on this constraint can be ignored */
7719  if( SCIPconsIsChecked(cons) )
7720  {
7721  if( !SCIPisInfinity(scip, -lhs) )
7722  {
7723  maxnlocksstay++;
7724  maxnlocksremove++;
7725  }
7726  if( !SCIPisInfinity(scip, rhs) )
7727  {
7728  maxnlocksstay++;
7729  maxnlocksremove++;
7730  }
7731  }
7732 
7733  /* look for a slack variable s to convert a*x + s == b into lhs <= a*x <= rhs */
7734  vars = consdata->vars;
7735  vals = consdata->vals;
7736  bestslackpos = -1;
7737  bestslacktype = SCIP_VARTYPE_BINARY;
7738  bestnlocks = INT_MAX;
7739  bestremovescons = FALSE;
7740  bestslackdomrng = 0.0;
7741  coefszeroone = TRUE;
7742  coefsintegral = TRUE;
7743  varsintegral = TRUE;
7744  ncontvars = 0;
7745  contvarpos = -1;
7746  nintvars = 0;
7747  nimplvars = 0;
7748  intvarpos = -1;
7749  minabsval = SCIPinfinity(scip);
7750  maxabsval = -1.0;
7751  for( v = 0; v < consdata->nvars; ++v )
7752  {
7753  SCIP_VAR* var;
7754  SCIP_Real val;
7755  SCIP_Real absval;
7756  SCIP_Real varlb;
7757  SCIP_Real varub;
7758  SCIP_Bool iscont;
7759  int nlocks;
7760 
7761  assert(vars != NULL);
7762  assert(vals != NULL);
7763 
7764  var = vars[v];
7765  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksDown(var) >= 1); /* because variable is locked in this equality */
7766  assert(!SCIPconsIsChecked(cons) || SCIPvarGetNLocksUp(var) >= 1);
7767  varlb = SCIPvarGetLbGlobal(var);
7768  varub = SCIPvarGetUbGlobal(var);
7769 
7770  val = vals[v];
7771  absval = REALABS(val);
7772  assert(SCIPisPositive(scip, absval));
7773 
7774  /* calculate minimal and maximal absolute value */
7775  if( absval < minabsval )
7776  minabsval = absval;
7777  if( absval > maxabsval )
7778  maxabsval = absval;
7779 
7780  /* do not try to multi aggregate, when numerical bad */
7781  if( maxabsval / minabsval > MAXMULTIAGGRQUOTIENT )
7782  return SCIP_OKAY;
7783 
7784  slacktype = SCIPvarGetType(var);
7785  coefszeroone = coefszeroone && SCIPisEQ(scip, absval, 1.0);
7786  coefsintegral = coefsintegral && SCIPisIntegral(scip, val);
7787  varsintegral = varsintegral && (slacktype != SCIP_VARTYPE_CONTINUOUS);
7788  iscont = (slacktype == SCIP_VARTYPE_CONTINUOUS || slacktype == SCIP_VARTYPE_IMPLINT);
7789 
7790  /* update candidates for continuous -> implint and integer -> implint conversion */
7791  if( slacktype == SCIP_VARTYPE_CONTINUOUS )
7792  {
7793  ncontvars++;
7794  contvarpos = v;
7795  }
7796  else if( slacktype == SCIP_VARTYPE_IMPLINT )
7797  {
7798  ++nimplvars;
7799  }
7800  else if( slacktype == SCIP_VARTYPE_INTEGER )
7801  {
7802  nintvars++;
7803  intvarpos = v;
7804  }
7805 
7806  /* check, if variable is already fixed or aggregated */
7807  if( !SCIPvarIsActive(var) )
7808  continue;
7809 
7810  /* check, if variable is used in too many other constraints, even if this constraint could be deleted */
7811  nlocks = SCIPvarGetNLocksDown(var) + SCIPvarGetNLocksUp(var);
7812 
7813  if( nlocks > maxnlocksremove )
7814  continue;
7815 
7816  /* check, if variable can be used as a slack variable */
7817  if( (iscont || (coefsintegral && varsintegral && SCIPisEQ(scip, absval, 1.0))) &&
7818  !SCIPdoNotMultaggrVar(scip, var) )
7819  {
7820  SCIP_Bool better;
7821  SCIP_Bool equal;
7822  SCIP_Real slackdomrng;
7823 
7824  if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
7825  slackdomrng = SCIPinfinity(scip);
7826  /* we do not want to perform multi-aggregation due to numerics, if the bounds are huge */
7827  else if( SCIPisHugeValue(scip, varub) || SCIPisHugeValue(scip, -varlb) )
7828  return SCIP_OKAY;
7829  else
7830  {
7831  slackdomrng = (varub - varlb)*absval;
7832  assert(!SCIPisInfinity(scip, slackdomrng));
7833  }
7834  equal = FALSE;
7835  better = (slacktype > bestslacktype) || (bestslackpos == -1);
7836  if( !better && slacktype == bestslacktype )
7837  {
7838  better = (nlocks < bestnlocks);
7839  if( nlocks == bestnlocks && !bestremovescons )
7840  {
7841  better = SCIPisGT(scip, slackdomrng, bestslackdomrng);
7842  equal = !better && SCIPisGE(scip, slackdomrng, bestslackdomrng);
7843  }
7844  }
7845 
7846  if( better || equal )
7847  {
7848  SCIP_Real minresactivity;
7849  SCIP_Real maxresactivity;
7850  SCIP_Real newlhs;
7851  SCIP_Real newrhs;
7852  SCIP_Bool removescons;
7853  SCIP_Bool minisrelax;
7854  SCIP_Bool maxisrelax;
7855  SCIP_Bool isminsettoinfinity;
7856  SCIP_Bool ismaxsettoinfinity;
7857 
7858  /* check if the constraint becomes redundant after multi-aggregation */
7859  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
7860  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
7861 
7862  /* do not perform the multi-aggregation due to numerics, if we have huge contributions in the residual
7863  * activity
7864  */
7865  if( minisrelax || maxisrelax )
7866  continue;
7867 
7868  getNewSidesAfterAggregation(scip, consdata, var, val, &newlhs, &newrhs);
7869  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
7870 
7871  /* check resactivities for reliability */
7872  if( removescons )
7873  {
7874  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
7875  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
7876 
7877  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity)
7878  && SCIPisFeasLE(scip, newlhs, minresactivity))
7879  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
7880 
7881  removescons = (SCIPisFeasLE(scip, newlhs, minresactivity) && SCIPisFeasLE(scip, maxresactivity, newrhs));
7882  }
7883 
7884  /* prefer variables that make the constraints redundant */
7885  if( bestremovescons && !removescons )
7886  continue;
7887 
7888  /* if the constraint does not become redundant, only accept the variable if it does not appear in
7889  * other constraints
7890  */
7891  if( !removescons && nlocks > maxnlocksstay )
7892  continue;
7893 
7894  better = better || (!bestremovescons && removescons);
7895  if( better )
7896  {
7897  bestslackpos = v;
7898  bestslacktype = slacktype;
7899  bestnlocks = nlocks;
7900  bestslackdomrng = slackdomrng;
7901  bestremovescons = removescons;
7902  }
7903  }
7904  }
7905  }
7906 
7907  /* if all coefficients and variables are integral, the right hand side must also be integral */
7908  if( coefsintegral && varsintegral && !SCIPisFeasIntegral(scip, consdata->rhs) )
7909  {
7910  SCIPdebugMessage("linear equality <%s> is integer infeasible\n", SCIPconsGetName(cons));
7911  SCIPdebugPrintCons(scip, cons, NULL);
7912  *cutoff = TRUE;
7913  return SCIP_OKAY;
7914  }
7915 
7916  supinf = 0;
7917  infinf = 0;
7918  samevar = FALSE;
7919 
7920  /* check whether the the infimum and the supremum of the multi-aggregation can be get infinite */
7921  for( v = 0; v < consdata->nvars; ++v )
7922  {
7923  if( v != bestslackpos )
7924  {
7925  if( SCIPisPositive(scip, consdata->vals[v]) )
7926  {
7927  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
7928  {
7929  ++supinf;
7930  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
7931  {
7932  ++infinf;
7933  samevar = TRUE;
7934  }
7935  }
7936  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
7937  ++infinf;
7938 
7939  }
7940  else if( SCIPisNegative(scip, consdata->vals[v]) )
7941  {
7942  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[v])) )
7943  {
7944  ++supinf;
7945  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
7946  {
7947  ++infinf;
7948  samevar = TRUE;
7949  }
7950  }
7951  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[v])) )
7952  ++infinf;
7953  }
7954  }
7955  }
7956  assert(!samevar || (supinf > 0 && infinf > 0));
7957 
7958  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
7959  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
7960  if( (samevar && (supinf > 1 || infinf > 1)) || (!samevar && supinf > 0 && infinf > 0) )
7961  {
7962  SCIPdebugMessage("do not perform multi-aggregation: infimum and supremum are both infinite\n");
7963  return SCIP_OKAY;
7964  }
7965 
7966  /* if the slack variable is of integer type, and the constraint itself may take fractional values,
7967  * we cannot aggregate the variable, because the integrality condition would get lost
7968  * Similarly, if there are implicitly integral variables we cannot aggregate, since we might
7969  * loose the integrality condition for this variable.
7970  */
7971  if( bestslackpos >= 0
7972  && (bestslacktype == SCIP_VARTYPE_CONTINUOUS || bestslacktype == SCIP_VARTYPE_IMPLINT
7973  || (coefsintegral && varsintegral && nimplvars == 0)) )
7974  {
7975  SCIP_VAR* slackvar;
7976  SCIP_Real* scalars;
7977  SCIP_Real slackcoef;
7978  SCIP_Real aggrconst;
7979  SCIP_Real newlhs;
7980  SCIP_Real newrhs;
7981  SCIP_Bool aggregated;
7982 
7983  /* we found a slack variable that only occurs in at most one other constraint:
7984  * a_1*x_1 + ... + a_k*x_k + a'*s == rhs -> s == rhs - a_1/a'*x_1 - ... - a_k/a'*x_k
7985  */
7986  assert(bestslackpos < consdata->nvars);
7987 
7988  /* do not multi aggregate binary variables */
7989  if( SCIPvarIsBinary(vars[bestslackpos]) )
7990  return SCIP_OKAY;
7991 
7992  /* convert equality into inequality by deleting the slack variable:
7993  * x + a*s == b, l <= s <= u -> b - a*u <= x <= b - a*l
7994  */
7995  slackvar = vars[bestslackpos];
7996  slackcoef = vals[bestslackpos];
7997  assert(!SCIPisZero(scip, slackcoef));
7998  aggrconst = consdata->rhs/slackcoef;
7999 
8000  getNewSidesAfterAggregation(scip, consdata, slackvar, slackcoef, &newlhs, &newrhs);
8001  assert(SCIPisLE(scip, newlhs, newrhs));
8002  SCIP_CALL( chgLhs(scip, cons, newlhs) );
8003  SCIP_CALL( chgRhs(scip, cons, newrhs) );
8004  SCIP_CALL( delCoefPos(scip, cons, bestslackpos) );
8005 
8006  /* allocate temporary memory */
8007  SCIP_CALL( SCIPallocBufferArray(scip, &scalars, consdata->nvars) );
8008 
8009  /* set up the multi-aggregation */
8010  SCIPdebugMessage("linear constraint <%s>: multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(slackvar));
8011  for( v = 0; v < consdata->nvars; ++v )
8012  {
8013  scalars[v] = -consdata->vals[v]/slackcoef;
8014  SCIPdebugPrintf(" %+.15g<%s>", scalars[v], SCIPvarGetName(vars[v]));
8015  }
8016  SCIPdebugPrintf(" %+.15g, bounds of <%s>: [%.15g,%.15g], nlocks=%d, maxnlocks=%d, removescons=%u\n",
8017  aggrconst, SCIPvarGetName(slackvar), SCIPvarGetLbGlobal(slackvar), SCIPvarGetUbGlobal(slackvar),
8018  bestnlocks, bestremovescons ? maxnlocksremove : maxnlocksstay, bestremovescons);
8019 
8020  /* perform the multi-aggregation */
8021  SCIP_CALL( SCIPmultiaggregateVar(scip, slackvar, consdata->nvars, vars, scalars, aggrconst,
8022  &infeasible, &aggregated) );
8023  assert(aggregated);
8024 
8025  /* free temporary memory */
8026  SCIPfreeBufferArray(scip, &scalars);
8027 
8028  /* check for infeasible aggregation */
8029  if( infeasible )
8030  {
8031  SCIPdebugMessage("linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
8032  *cutoff = TRUE;
8033  return SCIP_OKAY;
8034  }
8035 
8036  (*naggrvars)++;
8037 
8038  /* delete the constraint if it became redundant */
8039  if( bestremovescons )
8040  {
8041  SCIPdebugMessage("linear constraint <%s>: redundant after multi-aggregation\n", SCIPconsGetName(cons));
8042  SCIP_CALL( SCIPdelCons(scip, cons) );
8043 
8044  if( !consdata->upgraded )
8045  (*ndelconss)++;
8046  }
8047  }
8048  else if( ncontvars == 1 )
8049  {
8050  SCIP_VAR* var;
8051 
8052  assert(0 <= contvarpos && contvarpos < consdata->nvars);
8053  var = vars[contvarpos];
8054  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
8055 
8056  if( coefsintegral && SCIPisFeasIntegral(scip, consdata->rhs) )
8057  {
8058  /* upgrade continuous variable to an implicit one, if the absolute value of the coefficient is one */
8059  if( SCIPisEQ(scip, REALABS(vals[contvarpos]), 1.0) )
8060  {
8061  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
8062  SCIPdebugMessage("linear constraint <%s>: converting continuous variable <%s> to implicit integer variable\n",
8063  SCIPconsGetName(cons), SCIPvarGetName(var));
8064  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
8065  if( infeasible )
8066  {
8067  SCIPdebugMessage("infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
8068  *cutoff = TRUE;
8069 
8070  return SCIP_OKAY;
8071  }
8072  }
8073  /* aggregate continuous variable to an implicit one, if the absolute value of the coefficient is unequal to one */
8074  /* @todo check if the aggregation coefficient should be in some range(, which is not too big) */
8075  else if( !SCIPdoNotAggr(scip) )
8076  {
8077  SCIP_VAR* newvar;
8078  SCIP_Real absval;
8079  char newvarname[SCIP_MAXSTRLEN];
8080  SCIP_Bool redundant;
8081  SCIP_Bool aggregated;
8082 
8083  absval = REALABS(vals[contvarpos]);
8084 
8085  (void) SCIPsnprintf(newvarname, SCIP_MAXSTRLEN, "%s_impl", SCIPvarGetName(var));
8086 
8087  /* create new implicit variable for aggregation */
8088  SCIP_CALL( SCIPcreateVar(scip, &newvar, newvarname, -SCIPinfinity(scip), SCIPinfinity(scip), 0.0,
8090 
8091  /* add new variable to problem */
8092  SCIP_CALL( SCIPaddVar(scip, newvar) );
8093 
8094 #ifdef SCIP_DEBUG_SOLUTION
8095  if( SCIPdebugIsMainscip(scip) )
8096  {
8097  SCIP_Real varval;
8098  SCIP_CALL( SCIPdebugGetSolVal(scip, var, &varval) );
8099  SCIP_CALL( SCIPdebugAddSolVal(scip, newvar, absval * varval) );
8100  }
8101 #endif
8102 
8103  /* convert the continuous variable with coefficient 1.0 into an implicit integer variable */
8104  SCIPdebugMessage("linear constraint <%s>: aggregating continuous variable <%s> to newly created implicit integer variable <%s>, aggregation factor = %g\n",
8105  SCIPconsGetName(cons), SCIPvarGetName(var), SCIPvarGetName(newvar), absval);
8106 
8107  /* aggregate continuous and implicit variable */
8108  SCIP_CALL( SCIPaggregateVars(scip, var, newvar, absval, -1.0, 0.0, &infeasible, &redundant, &aggregated) );
8109 
8110  if( infeasible )
8111  {
8112  SCIPdebugMessage("infeasible aggregation of variable <%s> to implicit variable <%s>, domain is empty\n",
8113  SCIPvarGetName(var), SCIPvarGetName(newvar));
8114  *cutoff = TRUE;
8115 
8116  /* release implicit variable */
8117  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
8118 
8119  return SCIP_OKAY;
8120  }
8121 
8122  if( aggregated )
8123  (*naggrvars)++;
8124 
8125  /* release implicit variable */
8126  SCIP_CALL( SCIPreleaseVar(scip, &newvar) );
8127  }
8128 
8129  /* we do not have any event on vartype changes, so we need to manually force this constraint to be presolved
8130  * again
8131  */
8132  consdata->boundstightened = FALSE;
8133  consdata->presolved = FALSE;
8134  }
8135  }
8136  else if( ncontvars == 0 && nimplvars == 0 && nintvars == 1 && !coefszeroone )
8137  {
8138  SCIP_VAR* var;
8139 
8140  /* this seems to help for rococo instances, but does not for rout (where all coefficients are +/- 1.0)
8141  * -> we don't convert integers into implints if the row is a 0/1-row
8142  */
8143  assert(varsintegral);
8144  assert(0 <= intvarpos && intvarpos < consdata->nvars);
8145  var = vars[intvarpos];
8146  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
8147 
8148  if( coefsintegral
8149  && SCIPisEQ(scip, REALABS(vals[intvarpos]), 1.0)
8150  && SCIPisFeasIntegral(scip, consdata->rhs) )
8151  {
8152  /* convert the integer variable with coefficient 1.0 into an implicit integer variable */
8153  SCIPdebugMessage("linear constraint <%s>: converting integer variable <%s> to implicit integer variable\n",
8154  SCIPconsGetName(cons), SCIPvarGetName(var));
8155  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
8156  if( infeasible )
8157  {
8158  SCIPdebugMessage("infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
8159  *cutoff = TRUE;
8160 
8161  return SCIP_OKAY;
8162  }
8163  }
8164  }
8165 
8166  return SCIP_OKAY;
8167 }
8168 
8169 /** checks if the given variables and their coefficient are equal (w.r.t. scaling factor) to the objective function */
8170 static
8172  SCIP* scip, /**< SCIP data structure */
8173  SCIP_CONSDATA* consdata, /**< linear constraint data */
8174  SCIP_Real* scale, /**< pointer to store the scaling factor between the constraint and the
8175  * objective function
8176  */
8177  SCIP_Real* offset /**< pointer to store the offset of the objective function resulting by
8178  * this constraint
8179  */
8180  )
8181 {
8182  SCIP_VAR** vars;
8183  SCIP_VAR* var;
8184  SCIP_Real objval;
8185  SCIP_Bool negated;
8186  int nvars;
8187  int v;
8188 
8189  vars = consdata->vars;
8190  nvars = consdata->nvars;
8191  assert(vars != NULL);
8192 
8193  for( v = 0; v < nvars; ++v )
8194  {
8195  negated = FALSE;
8196  var = vars[v];
8197  assert(vars != NULL);
8198 
8199  if( SCIPvarIsNegated(var) )
8200  {
8201  negated = TRUE;
8202  var = SCIPvarGetNegatedVar(var);
8203  assert(var != NULL);
8204  }
8205 
8206  objval = SCIPvarGetObj(var);
8207 
8208  /* if a variable has a zero objective coefficient the linear constraint is not a subset of the objective
8209  * function
8210  */
8211  if( SCIPisZero(scip, objval) )
8212  return FALSE;
8213  else
8214  {
8215  SCIP_Real val;
8216 
8217  val = consdata->vals[v];
8218 
8219  if( negated )
8220  {
8221  if( v == 0 )
8222  {
8223  /* the first variable defines the scale */
8224  (*scale) = val / -objval;
8225 
8226  (*offset) += val;
8227  }
8228  else if( SCIPisEQ(scip, -objval * (*scale), val) )
8229  (*offset) += val;
8230  else
8231  return FALSE;
8232  }
8233  else if( v == 0 )
8234  {
8235  /* the first variable defines the scale */
8236  (*scale) = val / objval;
8237  }
8238  else if( !SCIPisEQ(scip, objval * (*scale), val) )
8239  return FALSE;
8240  }
8241  }
8242 
8243  return TRUE;
8244 }
8245 
8246 /** check if the linear equality constraint is equal to a subset of the objective function; if so we can remove the
8247  * objective coefficients and add an objective offset
8248  */
8249 static
8251  SCIP* scip, /**< SCIP data structure */
8252  SCIP_CONS* cons, /**< linear equation constraint */
8253  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
8254  )
8255 {
8256  SCIP_CONSDATA* consdata;
8257  SCIP_Real offset;
8258  SCIP_Real scale;
8259  SCIP_Bool applicable;
8260  int nobjvars;
8261  int nvars;
8262  int v;
8263 
8264  assert(scip != NULL);
8265  assert(cons != NULL);
8266  assert(conshdlrdata != NULL);
8267 
8268  consdata = SCIPconsGetData(cons);
8269  assert(consdata != NULL);
8270  assert(SCIPisEQ(scip, consdata->lhs, consdata->rhs));
8271 
8272  nvars = consdata->nvars;
8273  nobjvars = SCIPgetNObjVars(scip);
8274 
8275  /* check if the linear equality constraints does not have more variables than the objective function */
8276  if( nvars > nobjvars || nvars == 0 )
8277  return SCIP_OKAY;
8278 
8279  /* check for allowance of algorithm */
8280  if( (nvars < nobjvars && !conshdlrdata->detectpartialobjective) ||
8281  (nvars == nobjvars && (!conshdlrdata->detectcutoffbound || !conshdlrdata->detectlowerbound)) )
8282  return SCIP_OKAY;
8283 
8284  offset = consdata->rhs;
8285  scale = 1.0;
8286 
8287  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
8288  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
8289 
8290  if( applicable )
8291  {
8292  SCIP_VAR** vars;
8293 
8294  vars = consdata->vars;
8295  assert(vars != NULL);
8296 
8297  offset /= scale;
8298 
8299  SCIPdebugMessage("linear equality constraint <%s> == %g (offset %g) is a subset of the objective function\n",
8300  SCIPconsGetName(cons), consdata->rhs, offset);
8301 
8302  /* set all objective coefficient to zero */
8303  for( v = 0; v < nvars; ++v )
8304  {
8305  SCIP_CALL( SCIPchgVarObj(scip, vars[v], 0.0) );
8306  }
8307 
8308  /* add an objective offset */
8309  SCIP_CALL( SCIPaddObjoffset(scip, offset) );
8310  }
8311 
8312  return SCIP_OKAY;
8313 }
8314 
8315 /** updates the cutoff if the given primal bound (which is implied by the given constraint) is better */
8316 static
8318  SCIP* scip, /**< SCIP data structure */
8319  SCIP_CONS* cons, /**< constraint */
8320  SCIP_Real primalbound /**< feasible primal bound */
8321  )
8322 {
8323  SCIP_Real cutoffbound;
8324 
8325  /* increase the cutoff bound value by an epsilon to ensue that solution with the value of the cutoff bound are still
8326  * accepted
8327  */
8328  cutoffbound = primalbound + SCIPcutoffbounddelta(scip);
8329 
8330  if( cutoffbound < SCIPgetCutoffbound(scip) )
8331  {
8332  SCIPdebugMessage("update cutoff bound <%g>\n", cutoffbound);
8333 
8334  SCIP_CALL( SCIPupdateCutoffbound(scip, cutoffbound) );
8335  }
8336  else
8337  {
8338  SCIP_CONSDATA* consdata;
8339 
8340  consdata = SCIPconsGetData(cons);
8341  assert(consdata != NULL);
8342 
8343  /* we cannot disable the enforcement and propagation on ranged rows, because the cutoffbound could only have
8344  * resulted from one side
8345  */
8346  if( SCIPisInfinity(scip, -consdata->lhs) || SCIPisInfinity(scip, consdata->rhs) )
8347  {
8348  /* in case the cutoff bound is worse then the currently known one, we additionally avoid enforcement and
8349  * propagation
8350  */
8351  SCIP_CALL( SCIPsetConsEnforced(scip, cons, FALSE) );
8352  SCIP_CALL( SCIPsetConsPropagated(scip, cons, FALSE) );
8353  }
8354  }
8355 
8356  return SCIP_OKAY;
8357 }
8358 
8359 /** check if the linear constraint is parallel to objective function; if so update the cutoff bound and avoid that the
8360  * constraint enters the LP by setting the initial and separated flag to FALSE
8361  */
8362 static
8364  SCIP* scip, /**< SCIP data structure */
8365  SCIP_CONS* cons, /**< linear constraint */
8366  SCIP_CONSHDLRDATA* conshdlrdata /**< linear constraint handler data */
8367  )
8368 {
8369  SCIP_CONSDATA* consdata;
8370  SCIP_Real offset;
8371  SCIP_Real scale;
8372  SCIP_Bool applicable;
8373  int nobjvars;
8374  int nvars;
8375 
8376  assert(scip != NULL);
8377  assert(cons != NULL);
8378  assert(conshdlrdata != NULL);
8379 
8380  consdata = SCIPconsGetData(cons);
8381  assert(consdata != NULL);
8382 
8383  /* ignore equalities since these are covert by the method checkPartialObjective() */
8384  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
8385  return SCIP_OKAY;
8386 
8387  nvars = consdata->nvars;
8388  nobjvars = SCIPgetNObjVars(scip);
8389 
8390  /* check if the linear inequality constraints has the same number of variables as the objective function and if the
8391  * initial and/or separated flag is set to FALSE
8392  */
8393  if( nvars != nobjvars || (!SCIPconsIsInitial(cons) && !SCIPconsIsSeparated(cons)) )
8394  return SCIP_OKAY;
8395 
8396  offset = 0.0;
8397  scale = 1.0;
8398 
8399  /* checks if the variables and their coefficients are equal (w.r.t. scaling factor) to the objective function */
8400  applicable = checkEqualObjective(scip, consdata, &scale, &offset);
8401 
8402  if( applicable )
8403  {
8404  SCIP_Bool rhsfinite = !SCIPisInfinity(scip, consdata->rhs);
8405  SCIP_Bool lhsfinite = !SCIPisInfinity(scip, -consdata->lhs);
8406 
8407  if( SCIPisPositive(scip, scale) )
8408  {
8409  if( conshdlrdata->detectcutoffbound && rhsfinite )
8410  {
8411  SCIP_Real primalbound;
8412 
8413  primalbound = (consdata->rhs - offset) / scale;
8414 
8415  SCIPdebugMessage("constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
8416  SCIPconsGetName(cons), primalbound);
8417 
8418  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
8419  }
8420 
8421  if( conshdlrdata->detectlowerbound && lhsfinite )
8422  {
8423  SCIP_Real lowerbound;
8424 
8425  lowerbound = (consdata->lhs - offset) / scale;
8426 
8427  SCIPdebugMessage("constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
8428  SCIPconsGetName(cons), lowerbound);
8429 
8430  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
8431  }
8432 
8433  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !lhsfinite)) ||
8434  (conshdlrdata->detectlowerbound && !rhsfinite) )
8435  {
8436  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
8437  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
8438  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
8439  }
8440  }
8441  else
8442  {
8443  if( conshdlrdata->detectlowerbound && rhsfinite )
8444  {
8445  SCIP_Real lowerbound;
8446 
8447  lowerbound = (consdata->rhs - offset) / scale;
8448 
8449  SCIPdebugMessage("constraint <%s> is parallel to objective function and provides a lower bound <%g>\n",
8450  SCIPconsGetName(cons), lowerbound);
8451 
8452  SCIP_CALL( SCIPupdateLocalLowerbound(scip, lowerbound) );
8453  }
8454 
8455  if( conshdlrdata->detectcutoffbound && lhsfinite )
8456  {
8457  SCIP_Real primalbound;
8458 
8459  primalbound = (consdata->lhs - offset) / scale;
8460 
8461  SCIPdebugMessage("constraint <%s> is parallel to objective function and provides a cutoff bound <%g>\n",
8462  SCIPconsGetName(cons), primalbound);
8463 
8464  SCIP_CALL( updateCutoffbound(scip, cons, primalbound) );
8465  }
8466 
8467  if( (conshdlrdata->detectcutoffbound && (conshdlrdata->detectlowerbound || !rhsfinite)) ||
8468  (conshdlrdata->detectlowerbound && !lhsfinite) )
8469  {
8470  /* avoid that the linear constraint enters the LP since it is parallel to the objective function */
8471  SCIP_CALL( SCIPsetConsInitial(scip, cons, FALSE) );
8472  SCIP_CALL( SCIPsetConsSeparated(scip, cons, FALSE) );
8473  }
8474  }
8475  }
8476 
8477  return SCIP_OKAY;
8478 }
8479 
8480 /** converts special equalities */
8481 static
8483  SCIP* scip, /**< SCIP data structure */
8484  SCIP_CONS* cons, /**< linear constraint */
8485  SCIP_CONSHDLRDATA* conshdlrdata, /**< linear constraint handler data */
8486  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
8487  int* nfixedvars, /**< pointer to count number of fixed variables */
8488  int* naggrvars, /**< pointer to count number of aggregated variables */
8489  int* ndelconss /**< pointer to count number of deleted constraints */
8490  )
8491 {
8492  SCIP_CONSDATA* consdata;
8493 
8494  assert(scip != NULL);
8495  assert(cons != NULL);
8496  assert(conshdlrdata != NULL);
8497  assert(cutoff != NULL);
8498  assert(nfixedvars != NULL);
8499  assert(naggrvars != NULL);
8500  assert(ndelconss != NULL);
8501 
8502  consdata = SCIPconsGetData(cons);
8503  assert(consdata != NULL);
8504  assert(consdata->removedfixings);
8505 
8506  /* do nothing on inequalities */
8507  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
8508  return SCIP_OKAY;
8509 
8510  /* depending on the number of variables, call a special conversion method */
8511  if( consdata->nvars == 1 )
8512  {
8513  /* fix variable */
8514  SCIP_CALL( convertUnaryEquality(scip, cons, cutoff, nfixedvars, ndelconss) );
8515  }
8516  else if( consdata->nvars == 2 )
8517  {
8518  /* aggregate one of the variables */
8519  SCIP_CALL( convertBinaryEquality(scip, cons, cutoff, naggrvars, ndelconss) );
8520  }
8521  else
8522  {
8523  /* check if the equality is part of the objective function */
8524  SCIP_CALL( checkPartialObjective(scip, cons, conshdlrdata) );
8525 
8526  /* try to multi-aggregate one of the variables */
8527  SCIP_CALL( convertLongEquality(scip, cons, cutoff, naggrvars, ndelconss) );
8528  }
8529 
8530  return SCIP_OKAY;
8531 }
8532 
8533 /** returns whether the linear sum of all variables/coefficients except the given one divided by the given value is always
8534  * integral
8535  */
8536 static
8538  SCIP* scip, /**< SCIP data structure */
8539  SCIP_CONSDATA* consdata, /**< linear constraint */
8540  int pos, /**< position of variable to be left out */
8541  SCIP_Real val /**< value to divide the coefficients by */
8542  )
8543 {
8544  int v;
8545 
8546  assert(scip != NULL);
8547  assert(consdata != NULL);
8548  assert(0 <= pos && pos < consdata->nvars);
8549 
8550  for( v = 0; v < consdata->nvars; ++v )
8551  {
8552  if( v != pos && (!SCIPvarIsIntegral(consdata->vars[v]) || !SCIPisIntegral(scip, consdata->vals[v]/val)) )
8553  return FALSE;
8554  }
8555 
8556  return TRUE;
8557 }
8558 
8559 /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
8560  * check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i
8561  */
8562 static
8564  SCIP* scip, /**< SCIP data structure */
8565  SCIP_Real side, /**< lhs or rhs */
8566  SCIP_Real val, /**< coefficient */
8567  SCIP_Real minresactivity, /**< minimal residual activity */
8568  SCIP_Real maxresactivity, /**< maximal residual activity */
8569  SCIP_Real* minval, /**< pointer to store calculated minval */
8570  SCIP_Real* maxval /**< pointer to store calculated maxval */
8571  )
8572 {
8573  assert(scip != NULL);
8574  assert(minval != NULL);
8575  assert(maxval != NULL);
8576 
8577  if( val > 0.0 )
8578  {
8579  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
8580  *minval = -maxresactivity;
8581  else
8582  *minval = (side - maxresactivity)/val;
8583 
8584  if( SCIPisInfinity(scip, ABS(minresactivity)) )
8585  *maxval = -minresactivity;
8586  else
8587  *maxval = (side - minresactivity)/val;
8588  }
8589  else
8590  {
8591  if( SCIPisInfinity(scip, ABS(minresactivity)) )
8592  *minval = minresactivity;
8593  else
8594  *minval = (side - minresactivity)/val;
8595 
8596  if( SCIPisInfinity(scip, ABS(maxresactivity)) )
8597  *maxval = maxresactivity;
8598  else
8599  *maxval = (side - maxresactivity)/val;
8600  }
8601 }
8602 
8603 
8604 /* applies dual presolving for variables that are locked only once in a direction, and this locking is due to a
8605  * linear inequality
8606  */
8607 static
8609  SCIP* scip, /**< SCIP data structure */
8610  SCIP_CONS* cons, /**< linear constraint */
8611  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
8612  int* nfixedvars, /**< pointer to count number of fixed variables */
8613  int* naggrvars, /**< pointer to count number of aggregated variables */
8614  int* ndelconss /**< pointer to count number of deleted constraints */
8615  )
8616 {
8617  SCIP_CONSDATA* consdata;
8618  SCIP_Bool lhsexists;
8619  SCIP_Bool rhsexists;
8620  SCIP_Bool bestisint;
8621  SCIP_Bool bestislhs;
8622  int bestpos;
8623  int i;
8624  int maxotherlocks;
8625 
8626  assert(scip != NULL);
8627  assert(cons != NULL);
8628  assert(cutoff != NULL);
8629  assert(nfixedvars != NULL);
8630  assert(naggrvars != NULL);
8631  assert(ndelconss != NULL);
8632 
8633  /* only process checked constraints (for which the locks are increased);
8634  * otherwise we would have to check for variables with nlocks == 0, and these are already processed by the
8635  * dualfix presolver
8636  */
8637  if( !SCIPconsIsChecked(cons) )
8638  return SCIP_OKAY;
8639 
8640  consdata = SCIPconsGetData(cons);
8641  assert(consdata != NULL);
8642 
8643  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
8644  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
8645 
8646  /* search for a single-locked variable which can be multi-aggregated; if a valid continuous variable was found, we
8647  * can use it safely for aggregation and break the search loop
8648  */
8649  bestpos = -1;
8650  bestisint = TRUE;
8651  bestislhs = FALSE;
8652 
8653  /* We only want to multi-aggregate variables, if they appear in maximal one additional constraint,
8654  * everything else would produce fill-in. Exceptions:
8655  * - If there are only two variables in the constraint from which the multi-aggregation arises, no fill-in will be
8656  * produced.
8657  * - If there are three variables in the constraint, multi-aggregation in three additional constraints will remove
8658  * six nonzeros (three from the constraint and the three entries of the multi-aggregated variable) and add
8659  * six nonzeros (two variables per substitution).
8660  * - If there at most four variables in the constraint, multi-aggregation in two additional constraints will remove
8661  * six nonzeros (four from the constraint and the two entries of the multi-aggregated variable) and add
8662  * six nonzeros (three variables per substitution). God exists!
8663  */
8664  if( consdata->nvars <= 2 )
8665  maxotherlocks = INT_MAX;
8666  else if( consdata->nvars == 3 )
8667  maxotherlocks = 3;
8668  else if( consdata->nvars == 4 )
8669  maxotherlocks = 2;
8670  else
8671  maxotherlocks = 1;
8672 
8673  /* if this constraint has both sides, it also provides a lock for the other side and thus we can allow one more lock */
8674  if( lhsexists && rhsexists )
8675  maxotherlocks++;
8676 
8677  for( i = 0; i < consdata->nvars && bestisint; ++i )
8678  {
8679  SCIP_VAR* var;
8680  SCIP_Bool isint;
8681  SCIP_Real val;
8682  SCIP_Real obj;
8683  SCIP_Real lb;
8684  SCIP_Real ub;
8685  SCIP_Bool agglhs;
8686  SCIP_Bool aggrhs;
8687 
8688  var = consdata->vars[i];
8690 
8691  /* if we already found a candidate, skip integers */
8692  if( bestpos >= 0 && isint )
8693  continue;
8694 
8695  /* better do not multi-aggregate binary variables, since most plugins rely on their binary variables to be either
8696  * active, fixed, or single-aggregated with another binary variable
8697  */
8698  if( SCIPvarIsBinary(var) && consdata->nvars > 2 )
8699  continue;
8700 
8701  if ( SCIPdoNotMultaggrVar(scip, var) )
8702  continue;
8703 
8704  val = consdata->vals[i];
8705  obj = SCIPvarGetObj(var);
8706  lb = SCIPvarGetLbGlobal(var);
8707  ub = SCIPvarGetUbGlobal(var);
8708 
8709  /* lhs <= a_0 * x_0 + a_1 * x_1 + ... + a_{n-1} * x_{n-1} <= rhs
8710  *
8711  * a_i >= 0, c_i >= 0, lhs exists, nlocksdown(x_i) == 1:
8712  * - constraint is the only one that forbids fixing the variable to its lower bound
8713  * - 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
8714  *
8715  * a_i <= 0, c_i <= 0, lhs exists, nlocksup(x_i) == 1:
8716  * - constraint is the only one that forbids fixing the variable to its upper bound
8717  * - 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
8718  *
8719  * a_i >= 0, c_i <= 0, rhs exists, nlocksup(x_i) == 1:
8720  * - constraint is the only one that forbids fixing the variable to its upper bound
8721  * - 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
8722  *
8723  * a_i <= 0, c_i >= 0, rhs exists, nlocksdown(x_i) == 1:
8724  * - constraint is the only one that forbids fixing the variable to its lower bound
8725  * - 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
8726  *
8727  * but: all this is only applicable, if the aggregated value is inside x_i's bounds for all possible values
8728  * of all x_j
8729  * furthermore: we only want to apply this, if no fill-in will be produced
8730  */
8731  agglhs = lhsexists
8732  && ((val > 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDown(var) == 1
8733  && SCIPvarGetNLocksUp(var) <= maxotherlocks)
8734  || (val < 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUp(var) == 1
8735  && SCIPvarGetNLocksDown(var) <= maxotherlocks));
8736  aggrhs = rhsexists
8737  && ((val > 0.0 && !SCIPisPositive(scip, obj) && SCIPvarGetNLocksUp(var) == 1
8738  && SCIPvarGetNLocksDown(var) <= maxotherlocks)
8739  || (val < 0.0 && !SCIPisNegative(scip, obj) && SCIPvarGetNLocksDown(var) == 1
8740  && SCIPvarGetNLocksUp(var) <= maxotherlocks));
8741  if( agglhs || aggrhs )
8742  {
8743  SCIP_Real minresactivity;
8744  SCIP_Real maxresactivity;
8745  SCIP_Real minval;
8746  SCIP_Real maxval;
8747  SCIP_Bool minisrelax;
8748  SCIP_Bool maxisrelax;
8749  SCIP_Bool isminsettoinfinity;
8750  SCIP_Bool ismaxsettoinfinity;
8751 
8752  /* calculate bounds for \sum_{j \neq i} a_j * x_j */
8753  consdataGetActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
8754  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
8755  assert(SCIPisLE(scip, minresactivity, maxresactivity));
8756 
8757  /* We called consdataGetActivityResiduals() saying that we do not need a good relaxation,
8758  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
8759  * This is needed, because we do not want to rely on relaxed finite resactivities.
8760  */
8761  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
8762 
8763  if( agglhs )
8764  {
8765  /* check if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
8766  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
8767 
8768  assert(SCIPisLE(scip, minval, maxval));
8769  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
8770  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
8771  {
8772  SCIP_Real oldmaxresactivity;
8773  SCIP_Real oldminresactivity;
8774  SCIP_Bool recalculated;
8775 
8776  recalculated = FALSE;
8777  oldmaxresactivity = maxresactivity;
8778  oldminresactivity = minresactivity;
8779 
8780  /* check minresactivity for reliability */
8781  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
8782  {
8783  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
8784  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
8785  isminsettoinfinity = TRUE; /* here it means only that it was even calculated */
8786  }
8787 
8788  /* check maxresactivity for reliability */
8789  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
8790  {
8791  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
8792  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
8793  ismaxsettoinfinity = TRUE; /* here it means only that it was even calculated */
8794  }
8795 
8796  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
8797  if( recalculated )
8798  {
8799  assert(SCIPisLE(scip, minresactivity, maxresactivity));
8800 
8801  /* check again if lhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
8802  calculateMinvalAndMaxval(scip, consdata->lhs, val, minresactivity, maxresactivity, &minval, &maxval);
8803 
8804  assert(SCIPisLE(scip, minval, maxval));
8805  }
8806 
8807  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
8808  {
8809  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
8810  * in the multi-aggregation
8811  */
8812  if( !isint || (SCIPisIntegral(scip, consdata->lhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
8813  {
8814  bestpos = i;
8815  bestisint = isint;
8816  bestislhs = TRUE;
8817  continue; /* no need to also look at the right hand side */
8818  }
8819  }
8820  }
8821  }
8822 
8823  if( aggrhs )
8824  {
8825  /* check if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
8826  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
8827 
8828  assert(SCIPisLE(scip,minval,maxval));
8829  if( (!SCIPisInfinity(scip, -minval) && SCIPisFeasGE(scip, minval, lb)) &&
8830  (!SCIPisInfinity(scip, maxval) && SCIPisFeasLE(scip, maxval, ub)) )
8831  {
8832  SCIP_Real oldmaxresactivity;
8833  SCIP_Real oldminresactivity;
8834  SCIP_Bool recalculated;
8835 
8836  recalculated = FALSE;
8837  oldmaxresactivity = maxresactivity;
8838  oldminresactivity = minresactivity;
8839 
8840  /* check minresactivity for reliability */
8841  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastminactivity) )
8842  {
8843  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, FALSE);
8844  recalculated = !SCIPisEQ(scip, oldminresactivity, minresactivity);
8845  }
8846 
8847  /* check maxresactivity for reliability */
8848  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastmaxactivity) )
8849  {
8850  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, FALSE);
8851  recalculated = recalculated || !SCIPisEQ(scip, oldmaxresactivity, maxresactivity);
8852  }
8853 
8854  /* minresactivity or maxresactivity wasn't reliable so recalculate min- and maxval*/
8855  if( recalculated )
8856  {
8857  /* check again if rhs/a_i - \sum_{j \neq i} a_j/a_i * x_j is always inside the bounds of x_i */
8858  calculateMinvalAndMaxval(scip, consdata->rhs, val, minresactivity, maxresactivity, &minval, &maxval);
8859  assert(SCIPisLE(scip,minval,maxval));
8860  }
8861 
8862  if( !recalculated || (SCIPisFeasGE(scip, minval, lb) && SCIPisFeasLE(scip, maxval, ub)) )
8863  {
8864  /* if the variable is integer, we have to check whether the integrality condition would always be satisfied
8865  * in the multi-aggregation
8866  */
8867  if( !isint || (SCIPisIntegral(scip, consdata->rhs/val) && consdataIsResidualIntegral(scip, consdata, i, val)) )
8868  {
8869  bestpos = i;
8870  bestisint = isint;
8871  bestislhs = FALSE;
8872  }
8873  }
8874  }
8875  }
8876  }
8877  }
8878 
8879  if( bestpos >= 0 )
8880  {
8881  SCIP_VAR** aggrvars;
8882  SCIP_Real* aggrcoefs;
8883  SCIP_Real aggrconst;
8884  SCIP_VAR* bestvar;
8885  SCIP_Real bestval;
8886  int naggrs;
8887  int j;
8888  SCIP_Bool infeasible;
8889  SCIP_Bool aggregated;
8890  SCIP_Bool samevar;
8891  int supinf; /* counter for infinite contributions to the supremum of a possible
8892  * multi-aggregation
8893  */
8894  int infinf; /* counter for infinite contributions to the infimum of a possible
8895  * multi-aggregation
8896  */
8897 
8898  assert(!bestislhs || lhsexists);
8899  assert(bestislhs || rhsexists);
8900 
8901  bestvar = consdata->vars[bestpos];
8902  bestval = consdata->vals[bestpos];
8903  assert(bestisint ==
8905 
8906  /* allocate temporary memory */
8907  SCIP_CALL( SCIPallocBufferArray(scip, &aggrvars, consdata->nvars-1) );
8908  SCIP_CALL( SCIPallocBufferArray(scip, &aggrcoefs, consdata->nvars-1) );
8909 
8910  /* set up the multi-aggregation */
8911  SCIPdebugPrintCons(scip, cons, NULL);
8912  SCIPdebugMessage("linear constraint <%s> (dual): multi-aggregate <%s> ==", SCIPconsGetName(cons), SCIPvarGetName(bestvar));
8913  naggrs = 0;
8914  supinf = 0;
8915  infinf = 0;
8916  samevar = FALSE;
8917 
8918  for( j = 0; j < consdata->nvars; ++j )
8919  {
8920  if( j != bestpos )
8921  {
8922  aggrvars[naggrs] = consdata->vars[j];
8923  aggrcoefs[naggrs] = -consdata->vals[j]/consdata->vals[bestpos];
8924  SCIPdebugPrintf(" %+.15g<%s>", aggrcoefs[naggrs], SCIPvarGetName(aggrvars[naggrs]));
8925  if( bestisint )
8926  {
8927  /* coefficient must be integral: round it to exact integral value */
8928  assert(SCIPisIntegral(scip, aggrcoefs[naggrs]));
8929  aggrcoefs[naggrs] = SCIPfloor(scip, aggrcoefs[naggrs]+0.5);
8930  }
8931 
8932  if( SCIPisPositive(scip, aggrcoefs[naggrs]) )
8933  {
8934  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
8935  {
8936  ++supinf;
8937  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
8938  {
8939  ++infinf;
8940  samevar = TRUE;
8941  }
8942  }
8943  else if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
8944  ++infinf;
8945  }
8946  else if( SCIPisNegative(scip, aggrcoefs[naggrs]) )
8947  {
8948  if( SCIPisInfinity(scip, -SCIPvarGetLbGlobal(consdata->vars[j])) )
8949  {
8950  ++supinf;
8951  if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
8952  {
8953  ++infinf;
8954  samevar = TRUE;
8955  }
8956  }
8957  else if( SCIPisInfinity(scip, SCIPvarGetUbGlobal(consdata->vars[j])) )
8958  ++infinf;
8959  }
8960 
8961  naggrs++;
8962  }
8963  }
8964  assert(!samevar || (supinf > 0 && infinf > 0));
8965 
8966  aggrconst = (bestislhs ? consdata->lhs/bestval : consdata->rhs/bestval);
8967  SCIPdebugPrintf(" %+.15g, bounds of <%s>: [%.15g,%.15g]\n", aggrconst, SCIPvarGetName(bestvar),
8968  SCIPvarGetLbGlobal(bestvar), SCIPvarGetUbGlobal(bestvar));
8969  assert(naggrs == consdata->nvars-1);
8970 
8971  /* right hand side must be integral: round it to exact integral value */
8972  if( bestisint )
8973  {
8974  assert(SCIPisIntegral(scip, aggrconst));
8975  aggrconst = SCIPfloor(scip, aggrconst+0.5);
8976  }
8977 
8978  aggregated = FALSE;
8979  infeasible = FALSE;
8980 
8981  /* perform the multi-aggregation */
8982  if( (samevar && supinf == 1 && infinf == 1) || (!samevar && (supinf == 0 || infinf == 0)) )
8983  {
8984  /* @todo if multi-aggregate makes them numerical trouble, avoid them if the coefficients differ to much, see
8985  * also convertLongEquality() early termination due to coefficients
8986  */
8987  SCIP_CALL( SCIPmultiaggregateVar(scip, bestvar, naggrs, aggrvars, aggrcoefs, aggrconst, &infeasible, &aggregated) );
8988  }
8989  else
8990  {
8991  /* If the infimum and the supremum of a multi-aggregation are both infinite, then the multi-aggregation might not be resolvable.
8992  * E.g., consider the equality z = x-y. If x and y are both fixed to +infinity, the value for z is not determined */
8993  SCIPdebugMessage("do not perform multi-aggregation: infimum and supremum are both infinite\n");
8994  }
8995  /* free temporary memory */
8996  SCIPfreeBufferArray(scip, &aggrcoefs);
8997  SCIPfreeBufferArray(scip, &aggrvars);
8998 
8999  /* check for infeasible aggregation */
9000  if( infeasible )
9001  {
9002  SCIPdebugMessage("linear constraint <%s>: infeasible multi-aggregation\n", SCIPconsGetName(cons));
9003  *cutoff = TRUE;
9004  return SCIP_OKAY;
9005  }
9006 
9007  /* delete the constraint, if the aggregation was successful */
9008  if( aggregated )
9009  {
9010  SCIP_CALL( SCIPdelCons(scip, cons) );
9011 
9012  if( !consdata->upgraded )
9013  (*ndelconss)++;
9014  (*naggrvars)++;
9015  }
9016  else
9017  {
9018  SCIPdebugMessage("aggregation non successful!\n");
9019  }
9020  }
9021 
9022  return SCIP_OKAY;
9023 }
9024 
9025 #define BINWEIGHT 1
9026 #define INTWEIGHT 4
9027 #define CONTWEIGHT 8
9028 
9029 /** gets weight for variable in a "weighted number of variables" sum */
9030 static
9032  SCIP_VAR* var /**< variable to get weight for */
9033  )
9034 {
9035  switch( SCIPvarGetType(var) )
9036  {
9037  case SCIP_VARTYPE_BINARY:
9038  return BINWEIGHT;
9039  case SCIP_VARTYPE_INTEGER:
9040  case SCIP_VARTYPE_IMPLINT:
9041  return INTWEIGHT;
9043  return CONTWEIGHT;
9044  default:
9045  SCIPerrorMessage("invalid variable type\n");
9046  SCIPABORT();
9047  return 0; /*lint !e527*/
9048  }
9049 }
9050 
9051 /** tries to aggregate variables in equations a^Tx = lhs
9052  * in case there are at most two binary variables with an odd coefficient and all other
9053  * variables are not continuous and have an even coefficient then:
9054  * - exactly one odd binary variables
9055  * this binary variables y can be fixed to 0 if the lhs is even and to 1 if the lhs is odd
9056  * - lhs is odd -> y = 1
9057  * - lhs is even -> y = 0
9058  * - exactly two odd binary variables
9059  * aggregate the two binary variables with odd coefficient
9060  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
9061  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
9062  */
9063 static
9065  SCIP* scip, /**< SCIP data structure */
9066  SCIP_CONS* cons, /**< linear constraint */
9067  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
9068  int* nfixedvars, /**< pointer to count number of fixed variables */
9069  int* naggrvars, /**< pointer to count number of aggregated variables */
9070  int* ndelconss /**< pointer to count number of deleted constraints */
9071  )
9072 { /*lint --e{715}*/
9073  SCIP_CONSDATA* consdata;
9074  SCIP_Bool success;
9075 
9076  assert( scip != NULL );
9077  assert( cons != NULL );
9078 
9079  consdata = SCIPconsGetData(cons);
9080  assert( consdata != NULL );
9081 
9082  /* check if the linear constraint is an equation with integral right hand side */
9083  if( !SCIPisEQ(scip, consdata->lhs, consdata->rhs) || !SCIPisIntegral(scip, consdata->lhs) )
9084  return SCIP_OKAY;
9085 
9086  /* try to fix and aggregated variables until nothing is possible anymore */
9087  do
9088  {
9089  int v;
9090  int nvars;
9091  SCIP_VAR** vars;
9092  SCIP_Real* vals;
9093  SCIP_Real lhs;
9094  SCIP_Bool lhsodd;
9095 
9096  SCIP_Bool infeasible;
9097  SCIP_Bool fixed;
9098  SCIP_Bool aggregated;
9099  SCIP_Bool redundant;
9100 
9101  SCIP_VAR* var1;
9102  SCIP_VAR* var2;
9103  int noddvars;
9104 
9105  success = FALSE;
9106 
9107  lhs = consdata->lhs;
9108  vars = consdata->vars;
9109  vals = consdata->vals;
9110  nvars = consdata->nvars;
9111 
9112  assert( !SCIPisInfinity(scip, ABS(lhs)) );
9113 
9114  var1 = NULL;
9115  var2 = NULL;
9116  noddvars = 0;
9117 
9118  /* search for binary variables with an odd coefficient */
9119  for( v = 0; v < nvars && noddvars < 3; ++v )
9120  {
9121  SCIP_Longint val;
9122 
9123  /* all coefficients and variables have to be integral */
9124  if( !SCIPisIntegral(scip, vals[v]) || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
9125  return SCIP_OKAY;
9126 
9127  val = (SCIP_Longint)SCIPfeasFloor(scip, vals[v]);
9128  if( val % 2 != 0 )
9129  {
9130  /* the odd values have to belong to binary variables */
9131  if( !SCIPvarIsBinary(vars[v]) )
9132  return SCIP_OKAY;
9133 
9134  if( noddvars == 0 )
9135  var1 = vars[v];
9136  else
9137  var2 = vars[v];
9138 
9139  noddvars++;
9140  }
9141  }
9142 
9143  /* check lhs is odd or even */
9144  lhsodd = (((SCIP_Longint)SCIPfeasFloor(scip, lhs)) % 2 != 0);
9145 
9146  if( noddvars == 1 )
9147  {
9148  assert( var1 != NULL );
9149 
9150  SCIPdebugMessage("linear constraint <%s>: try fixing variable <%s> to <%g>\n",
9151  SCIPconsGetName(cons), SCIPvarGetName(var1), lhsodd ? 1.0 : 0.0);
9152 
9153  SCIP_CALL( SCIPfixVar(scip, var1, lhsodd? 1.0 : 0.0, &infeasible, &fixed) );
9154 
9155  /* check for infeasibility of fixing */
9156  if( infeasible )
9157  {
9158  SCIPdebugMessage(" -> infeasible fixing\n");
9159  *cutoff = TRUE;
9160  return SCIP_OKAY;
9161  }
9162 
9163  if( fixed )
9164  {
9165  SCIPdebugMessage(" -> feasible fixing\n");
9166  (*nfixedvars)++;
9167  success = TRUE;
9168  }
9169  }
9170  else if( noddvars == 2 )
9171  {
9172  assert( var1 != NULL );
9173  assert( var2 != NULL );
9174 
9175  /* aggregate the two variables with odd coefficient
9176  * - lhs is odd -> exactly one of the variable has to be 1 -> var1 + var2 = 1
9177  * - lhs is even -> both have to take the same value -> var1 - var2 = 0
9178  */
9179  SCIPdebugMessage("linear constraint <%s>: try aggregation of variables <%s> and <%s>\n",
9180  SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2));
9181 
9182  SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, lhsodd ? 1.0 : -1.0,
9183  lhsodd ? 1.0 : 0.0, &infeasible, &redundant, &aggregated) );
9184 
9185  /* check for infeasibility of aggregation */
9186  if( infeasible )
9187  {
9188  SCIPdebugMessage(" -> infeasible aggregation\n");
9189  *cutoff = TRUE;
9190  return SCIP_OKAY;
9191  }
9192 
9193  /* count the aggregation */
9194  if( aggregated )
9195  {
9196  SCIPdebugMessage(" -> feasible aggregation\n");
9197  (*naggrvars)++;
9198  success = TRUE;
9199  }
9200  }
9201 
9202  if( success )
9203  {
9204  /* apply fixings and aggregation to successfully rerun this presolving step */
9205  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
9206 
9207  if( infeasible )
9208  {
9209  SCIPdebugMessage(" -> infeasible fixing\n");
9210  *cutoff = TRUE;
9211  return SCIP_OKAY;
9212  }
9213 
9214  /* normalize constraint */
9215  SCIP_CALL( normalizeCons(scip, cons) );
9216  }
9217  }
9218  while( success );
9219 
9220  return SCIP_OKAY;
9221 }
9222 
9223 
9224 
9225 /** sorting method for constraint data, compares two variables on given indices, continuous variables will be sorted to
9226  * the end and for all other variables the sortation will be in non-increasing order of their absolute value of the
9227  * coefficients
9228  */
9229 static
9230 SCIP_DECL_SORTINDCOMP(consdataCompSim)
9231 { /*lint --e{715}*/
9232  SCIP_CONSDATA* consdata = (SCIP_CONSDATA*)dataptr;
9233  SCIP_VARTYPE vartype1;
9234  SCIP_VARTYPE vartype2;
9235  SCIP_Real value;
9236 
9237  assert(consdata != NULL);
9238  assert(0 <= ind1 && ind1 < consdata->nvars);
9239  assert(0 <= ind2 && ind2 < consdata->nvars);
9240 
9241  vartype1 = SCIPvarGetType(consdata->vars[ind1]);
9242  vartype2 = SCIPvarGetType(consdata->vars[ind2]);
9243 
9244  if( vartype1 == SCIP_VARTYPE_CONTINUOUS )
9245  {
9246  /* continuous varibles will be sorted to the back */
9247  if( vartype2 != vartype1 )
9248  return +1;
9249  /* both variables are continuous */
9250  else
9251  return 0;
9252  }
9253  /* continuous variables will be sorted to the back */
9254  else if( vartype2 == SCIP_VARTYPE_CONTINUOUS )
9255  return -1;
9256 
9257  value = REALABS(consdata->vals[ind2]) - REALABS(consdata->vals[ind1]);
9258 
9259  /* for all non-continuous variables, the variables are sorted after decreasing absolute coefficients */
9260  return (value > 0 ? +1 : (value < 0 ? -1 : 0));
9261 }
9262 
9263 /** tries to simplify coefficients and delete variables in ranged row of the form lhs <= a^Tx <= rhs, e.g. using the greatest
9264  * common divisor
9265  *
9266  * 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
9267  * constraint to 1^Tx = 1
9268  */
9269 static
9271  SCIP* scip, /**< SCIP data structure */
9272  SCIP_CONS* cons, /**< linear constraint */
9273  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
9274  int* nchgsides /**< pointer to store the amount of changed sides */
9275  )
9276 {
9277  SCIP_CONSDATA* consdata;
9278  SCIP_VAR** vars;
9279  SCIP_Real* vals;
9280  SCIP_Real minval;
9281  SCIP_Real secondminval;
9282  SCIP_Real maxval;
9283  SCIP_Real lhs;
9284  SCIP_Real rhs;
9285  int nvars;
9286  int v;
9287 
9288  /* we must not change a modifiable constraint in any way */
9289  if( SCIPconsIsModifiable(cons) )
9290  return SCIP_OKAY;
9291 
9292  if( SCIPconsIsDeleted(cons) )
9293  return SCIP_OKAY;
9294 
9295  consdata = SCIPconsGetData(cons);
9296  assert(consdata != NULL);
9297 
9298  nvars = consdata->nvars;
9299 
9300  /* do not check empty or bound-constraints */
9301  if( nvars < 2 )
9302  return SCIP_OKAY;
9303 
9304  vals = consdata->vals;
9305  vars = consdata->vars;
9306  assert(vars != NULL);
9307  assert(vals != NULL);
9308 
9309  lhs = consdata->lhs;
9310  rhs = consdata->rhs;
9311  assert(!SCIPisInfinity(scip, -lhs) && !SCIPisInfinity(scip, rhs));
9312  assert(!SCIPisNegative(scip, rhs));
9313 
9314  minval = SCIP_INVALID;
9315  secondminval = SCIP_INVALID;
9316  maxval = -SCIP_INVALID;
9317 
9318  for( v = nvars - 1; v >= 0; --v )
9319  {
9320  if( SCIPvarIsBinary(vars[v]) )
9321  {
9322  if( minval > vals[v] || minval == SCIP_INVALID ) /*lint !e777*/
9323  {
9324  secondminval = minval;
9325  minval = vals[v];
9326  }
9327  else if( secondminval > vals[v] || secondminval == SCIP_INVALID ) /*lint !e777*/
9328  secondminval = vals[v];
9329 
9330  if( maxval < vals[v] || maxval == -SCIP_INVALID ) /*lint !e777*/
9331  maxval = vals[v];
9332  }
9333  else
9334  break;
9335  }
9336 
9337  /* check if all variables are binary */
9338  if( v == -1 )
9339  {
9340  if( SCIPisEQ(scip, minval, maxval) && SCIPisEQ(scip, lhs, rhs) )
9341  return SCIP_OKAY;
9342 
9343  /* check if we can and need to choose exactly one binary variable */
9344  if( SCIPisGE(scip, minval, lhs) && SCIPisLE(scip, maxval, rhs) && SCIPisGT(scip, minval + secondminval, rhs) )
9345  {
9346  /* change all coefficients to 1.0 */
9347  for( v = nvars - 1; v >= 0; --v )
9348  {
9349  SCIP_CALL( chgCoefPos(scip, cons, v, 1.0) );
9350  }
9351  (*nchgcoefs) += nvars;
9352 
9353  /* replace old right and left hand side with 1.0 */
9354  SCIP_CALL( chgRhs(scip, cons, 1.0) );
9355  SCIP_CALL( chgLhs(scip, cons, 1.0) );
9356  (*nchgsides) += 2;
9357  }
9358  }
9359 
9360  return SCIP_OKAY;
9361 }
9362 
9363 /** tries to simplify coefficients and delete variables in constraints of the form lhs <= a^Tx <= rhs
9364  * for equations @see rangedRowSimplify() will be called
9365  *
9366  * there are several different coefficient reduction steps which will be applied
9367  *
9368  * 1. We try to determine parts of the constraint which will not change anything on (in-)feasibility of the constraint
9369  *
9370  * e.g. 5x1 + 5x2 + 3z1 <= 8 => 3z1 is redundant if all x are binary and -2 < 3z1 <= 3
9371  *
9372  * 2. We try to remove redundant fractional parts in a constraint
9373  *
9374  * e.g. 5.2x1 + 5.1x2 + 3x3 <= 8.3 => will be changed to 5x1 + 5x2 + 3x3 <= 8 if all x are binary
9375  *
9376  * 3. We are using the greatest common divisor for further reductions
9377  *
9378  * e.g. 10x1 + 5y2 + 5x3 + 3x4 <= 15 => will be changed to 2x1 + y2 + x3 + x4 <= 3 if all xi are binary and y2 is
9379  * integral
9380  */
9381 static
9383  SCIP* scip, /**< SCIP data structure */
9384  SCIP_CONS* cons, /**< linear constraint */
9385  int* nchgcoefs, /**< pointer to store the amount of changed coefficients */
9386  int* nchgsides /**< pointer to store the amount of changed sides */
9387  )
9388 {
9389  SCIP_CONSDATA* consdata;
9390  SCIP_VAR** vars;
9391  SCIP_Real* vals;
9392  int* perm;
9393  SCIP_Real minactsub;
9394  SCIP_Real maxactsub;
9395  SCIP_Real siderest;
9396  SCIP_Real feastol;
9397  SCIP_Real newcoef;
9398  SCIP_Real absval;
9399  SCIP_Real side;
9400  SCIP_Real lhs;
9401  SCIP_Real rhs;
9402  SCIP_Real lb;
9403  SCIP_Real ub;
9404  SCIP_Longint restcoef;
9405  SCIP_Longint oldgcd;
9406  SCIP_Longint rest;
9407  SCIP_Longint gcd;
9408  SCIP_Bool isminsettoinfinity;
9409  SCIP_Bool ismaxsettoinfinity;
9410  SCIP_Bool isminrelax;
9411  SCIP_Bool ismaxrelax;
9412  SCIP_Bool allcoefintegral;
9413  SCIP_Bool onlybin;
9414  SCIP_Bool hasrhs;
9415  SCIP_Bool haslhs;
9416  int oldnchgcoefs;
9417  int oldnchgsides;
9418  int foundbin;
9419  int candpos;
9420  int candpos2;
9421  int offsetv;
9422  int nvars;
9423  int v;
9424  int w;
9425 
9426  assert(scip != NULL);
9427  assert(cons != NULL);
9428  assert(nchgcoefs != NULL);
9429  assert(nchgsides != NULL);
9430 
9431  /* we must not change a modifiable constraint in any way */
9432  if( SCIPconsIsModifiable(cons) )
9433  return SCIP_OKAY;
9434 
9435  if( SCIPconsIsDeleted(cons) )
9436  return SCIP_OKAY;
9437 
9438  consdata = SCIPconsGetData(cons);
9439  assert(consdata != NULL);
9440 
9441  nvars = consdata->nvars;
9442 
9443  /* do not check empty or bound-constraints */
9444  if( nvars <= 2 )
9445  return SCIP_OKAY;
9446 
9447  /* update maximal activity delta if necessary */
9448  if( consdata->maxactdelta == SCIP_INVALID ) /*lint !e777*/
9449  consdataRecomputeMaxActivityDelta(scip, consdata);
9450 
9451  assert(consdata->maxactdelta != SCIP_INVALID); /*lint !e777*/
9452  assert(!SCIPisFeasNegative(scip, consdata->maxactdelta));
9453 
9454  /* @todo the following might be to hard, check which steps can be applied and what code must be corrected
9455  * accordingly
9456  */
9457  /* can only work with valid non-infinity activities per variable */
9458  if( SCIPisInfinity(scip, consdata->maxactdelta) )
9459  return SCIP_OKAY;
9460 
9461  /* @todo: change the following: due to vartype changes, the status of the normalization can be wrong, need an event
9462  * but the eventsystem seems to be full
9463  */
9464  consdata->normalized = FALSE;
9465 
9466  /* normalize constraint */
9467  SCIP_CALL( normalizeCons(scip, cons) );
9468  assert(consdata->normalized);
9469  assert(nvars == consdata->nvars);
9470 
9471  lhs = consdata->lhs;
9472  rhs = consdata->rhs;
9473  assert(!SCIPisInfinity(scip, -lhs) || !SCIPisInfinity(scip, rhs));
9474  assert(!SCIPisNegative(scip, rhs));
9475 
9476  if( !SCIPisInfinity(scip, -lhs) )
9477  haslhs = TRUE;
9478  else
9479  haslhs = FALSE;
9480 
9481  if( !SCIPisInfinity(scip, rhs) )
9482  hasrhs = TRUE;
9483  else
9484  hasrhs = FALSE;
9485 
9486  oldnchgcoefs = *nchgcoefs;
9487  oldnchgsides = *nchgsides;
9488 
9489  /* @todo also work on ranged rows */
9490  if( haslhs && hasrhs )
9491  {
9492  SCIP_CALL( rangedRowSimplify(scip, cons, nchgcoefs, nchgsides ) );
9493 
9494  return SCIP_OKAY;
9495  }
9496  assert(haslhs != hasrhs);
9497 
9498  /* if we have a normalized inequality (not ranged) the one side should be positive, @see normalizeCons() */
9499  assert(!hasrhs || !SCIPisNegative(scip, rhs));
9500  assert(!haslhs || !SCIPisNegative(scip, lhs));
9501 
9502  /* get temporary memory to store the sorted permutation */
9503  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nvars) );
9504 
9505  /* call sorting method, order continuous variables to the end and all other variables after non-increasing absolute
9506  * value of their coefficients
9507  */
9508  SCIPsort(perm, consdataCompSim, (void*)consdata, nvars);
9509 
9510  /* perform sorting after permutation array */
9511  permSortConsdata(consdata, perm, nvars);
9512  consdata->sorted = FALSE;
9513  consdata->binvarssorted = FALSE;
9514 
9515  vars = consdata->vars;
9516  vals = consdata->vals;
9517  assert(vars != NULL);
9518  assert(vals != NULL);
9519  assert(consdata->validmaxabsval ? (SCIPisFeasEQ(scip, consdata->maxabsval, REALABS(vals[0])) || SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS) : TRUE);
9520 
9521  /* free temporary memory */
9522  SCIPfreeBufferArray(scip, &perm);
9523 
9524  /* only check constraints with at least two non continuous variables */
9525  if( SCIPvarGetType(vars[1]) == SCIP_VARTYPE_CONTINUOUS )
9526  return SCIP_OKAY;
9527 
9528  /* do not process constraints when all coefficients are 1.0 */
9529  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) && ((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs))) )
9530  return SCIP_OKAY;
9531 
9532  feastol = SCIPfeastol(scip);
9533 
9534  SCIPdebugMessage("starting simplification of coeffcients\n");
9535  SCIPdebugPrintCons(scip, cons, NULL);
9536 
9537  /* get global activities */
9538  consdataGetGlbActivityBounds(scip, consdata, FALSE, &minactsub, &maxactsub,
9539  &isminrelax, &ismaxrelax, &isminsettoinfinity, &ismaxsettoinfinity);
9540 
9541  /* cannot work with infinite activities */
9542  if( isminsettoinfinity || ismaxsettoinfinity )
9543  return SCIP_OKAY;
9544 
9545  assert(!isminrelax);
9546  assert(!ismaxrelax);
9547  assert(maxactsub > minactsub);
9548  assert(!SCIPisInfinity(scip, -minactsub));
9549  assert(!SCIPisInfinity(scip, maxactsub));
9550 
9551  v = 0;
9552  offsetv = -1;
9553  side = haslhs ? lhs : rhs;
9554 
9555  /* we now determine coefficients as large as the side of the constraint to might retrieve a better reduction were we
9556  * do not need to look at the large coefficients
9557  *
9558  * e.g. all x are binary, z are positive integer
9559  * c1: +5x1 + 5x2 + 3x3 + 3x4 + x5 >= 5 (x5 is redundant and does not change (in-)feasibility of this constraint)
9560  * c2: +4x1 + 4x2 + 3x3 + 3x4 + x5 >= 4 (gcd (without the coefficient of x5) after the large coefficients is 3
9561  * c3: +30x1 + 29x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 30 (gcd (without the coefficient of x2) after the large coefficients is 7
9562  *
9563  * can be changed to
9564  *
9565  * c1: +6x1 + 6x2 + 3x3 + 3x4 >= 6 (will be changed to c1: +2x1 + 2x2 + x3 + x4 >= 2)
9566  * c2: +6x1 + 6x2 + 3x3 + 3x4 + 3x5 >= 6 (will be changed to c2: +2x1 + 2x2 + x3 + x4 + x5 >= 2)
9567  * c3: +28x1 + 28x2 + 14x3 + 14z1 + 7x5 + 7x6 <= 28 (will be changed to c3: +4x1 + 4x2 + 2x3 + 2z1 + x5 + x6 <= 4)
9568  */
9569 
9570  /* if the minimal activity is negative and we found more than one variable with a coefficient bigger than the left
9571  * hand side, we cannot apply the extra reduction step and need to reset v
9572  *
9573  * e.g. 7x1 + 7x2 - 4x3 - 4x4 >= 7 => xi = 1 forall i is not a solution, but if we would do a change on the
9574  * coeffcients due to the gcd on the "small" coeffcients we would get 8x1 + 8x2 - 4x3 - 4x4 >= 8 were xi = 1
9575  * forall i is a solution
9576  *
9577  * also redundancy of variables would not be correct determined in such a case
9578  */
9579  if( nvars > 2 && SCIPisEQ(scip, vals[0], side) && !SCIPisNegative(scip, minactsub) )
9580  {
9581  ++v;
9582 
9583  while( SCIPisEQ(scip, side, vals[v]) )
9584  {
9585  /* if we have integer variable with "side"-coefficients but also with a lower bound greater than 0 we stop this
9586  * extra step, which might have worked
9587  */
9588  if( SCIPvarGetLbGlobal(vars[v]) > 0.5 )
9589  {
9590  v = 0;
9591  break;
9592  }
9593 
9594  ++v;
9595  assert(v < nvars);
9596  }
9597 
9598  /* cannot work with continuous variables which have a big coefficient */
9599  if( v > 0 && SCIPvarGetType(vars[v - 1]) == SCIP_VARTYPE_CONTINUOUS )
9600  return SCIP_OKAY;
9601 
9602  /* big negative coefficient, do not try to use the extra coefficient reduction step */
9603  if( SCIPisEQ(scip, side, -vals[v]) )
9604  v = 0;
9605 
9606  /* all but one variable are processed or the next variables is continuous we cannot perform the extra coefficient
9607  * reduction
9608  */
9609  if( v == nvars - 1 || SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
9610  v = 0;
9611 
9612  if( v > 0 )
9613  {
9614  assert(v < nvars);
9615 
9616  offsetv = v - 1;
9617 
9618  for( w = 0; w < v; ++w )
9619  {
9620  lb = SCIPvarGetLbGlobal(vars[w]);
9621  ub = SCIPvarGetUbGlobal(vars[w]);
9622 
9623  assert(vals[w] > 0);
9624 
9625  /* update residual activities */
9626  maxactsub -= ub * vals[w];
9627  minactsub -= lb * vals[w];
9628  assert(maxactsub > minactsub);
9629  }
9630  }
9631  }
9632 
9633  /* find and remove redundant variables which do not interact with the (in-)feasible of a constraints
9634  *
9635  * e.g. assume all x are binary and y1 is continuous with bounds [-3,1] then we can reduce
9636  *
9637  * 15x1 + 15x2 + 7x3 + 3x4 + y1 <= 26
9638  * to
9639  * 15x1 + 15x2 <= 26 <=> x1 + x2 <= 1
9640  */
9641  if( nvars > 2 && SCIPisIntegral(scip, vals[v]) )
9642  {
9643  SCIP_Bool redundant = FALSE;
9644 
9645  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
9646  assert(gcd >= 1);
9647 
9648  if( v == 0 )
9649  {
9650  lb = SCIPvarGetLbGlobal(vars[0]);
9651  ub = SCIPvarGetUbGlobal(vars[0]);
9652 
9653  /* update residual activities */
9654  if( vals[0] > 0 )
9655  {
9656  maxactsub -= ub * vals[0];
9657  minactsub -= lb * vals[0];
9658  }
9659  else
9660  {
9661  maxactsub -= lb * vals[0];
9662  minactsub -= ub * vals[0];
9663  }
9664  assert(maxactsub > minactsub);
9665  ++v;
9666  }
9667 
9668  siderest = -SCIP_INVALID;
9669  allcoefintegral = TRUE;
9670 
9671  /* check if some variables always fit into the given constraint */
9672  for( ; v < nvars - 1; ++v )
9673  {
9674  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
9675  break;
9676 
9677  if( !SCIPisIntegral(scip, vals[v]) )
9678  {
9679  allcoefintegral = FALSE;
9680  break;
9681  }
9682 
9683  /* calculate greatest common divisor for all general and binary variables */
9684  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
9685 
9686  if( gcd == 1 )
9687  break;
9688 
9689  lb = SCIPvarGetLbGlobal(vars[v]);
9690  ub = SCIPvarGetUbGlobal(vars[v]);
9691 
9692  assert(!SCIPisInfinity(scip, -lb));
9693  assert(!SCIPisInfinity(scip, ub));
9694 
9695  /* update residual activities */
9696  if( vals[v] > 0 )
9697  {
9698  maxactsub -= ub * vals[v];
9699  minactsub -= lb * vals[v];
9700  }
9701  else
9702  {
9703  maxactsub -= lb * vals[v];
9704  minactsub -= ub * vals[v];
9705  }
9706  assert(SCIPisGE(scip, maxactsub, minactsub));
9707 
9708  if( hasrhs )
9709  {
9710  /* determine the remainder of the right hand side and the gcd */
9711  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
9712  }
9713  else
9714  {
9715  /* determine the remainder of the left hand side and the gcd */
9716  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
9717  if( SCIPisZero(scip, siderest) )
9718  siderest = gcd;
9719  }
9720 
9721  /* early termination if the activities deceed the gcd */
9722  if( (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) || (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd) )
9723  {
9724  redundant = TRUE;
9725  break;
9726  }
9727  }
9728  assert(v < nvars || (offsetv >= 0 && gcd > 1));
9729 
9730  if( !redundant )
9731  {
9732  if( hasrhs )
9733  {
9734  /* determine the remainder of the right hand side and the gcd */
9735  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
9736  }
9737  else
9738  {
9739  /* determine the remainder of the left hand side and the gcd */
9740  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
9741  if( SCIPisZero(scip, siderest) )
9742  siderest = gcd;
9743  }
9744  }
9745  else
9746  ++v;
9747 
9748  SCIPdebugMessage("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", v, nvars, minactsub, maxactsub, redundant, hasrhs, siderest, gcd, offsetv);
9749 
9750  /* check if we can remove redundant variables */
9751  if( v < nvars && (redundant ||
9752  (offsetv == -1 && hasrhs && maxactsub <= siderest && SCIPisFeasGT(scip, minactsub, siderest - gcd)) ||
9753  (haslhs && SCIPisFeasLT(scip, maxactsub, siderest) && minactsub >= siderest - gcd)) )
9754  {
9755  SCIP_Real oldcoef;
9756 
9757  /* double check the redundancy */
9758 #ifndef NDEBUG
9759  SCIP_Real tmpminactsub = 0.0;
9760  SCIP_Real tmpmaxactsub = 0.0;
9761 
9762  /* recompute residual activities */
9763  for( w = v; w < nvars; ++w )
9764  {
9765  lb = SCIPvarGetLbGlobal(vars[w]);
9766  ub = SCIPvarGetUbGlobal(vars[w]);
9767 
9768  assert(!SCIPisInfinity(scip, -lb));
9769  assert(!SCIPisInfinity(scip, ub));
9770 
9771  /* update residual activities */
9772  if( vals[w] > 0 )
9773  {
9774  tmpmaxactsub += ub * vals[w];
9775  tmpminactsub += lb * vals[w];
9776  }
9777  else
9778  {
9779  tmpmaxactsub += lb * vals[w];
9780  tmpminactsub += ub * vals[w];
9781  }
9782  assert(tmpmaxactsub >= tmpminactsub);
9783  }
9784 
9785  if( hasrhs )
9786  {
9787  assert(offsetv == -1);
9788 
9789  /* determine the remainder of the right hand side and the gcd */
9790  siderest = rhs - SCIPfeasFloor(scip, rhs/gcd) * gcd;
9791  }
9792  else
9793  {
9794  /* determine the remainder of the left hand side and the gcd */
9795  siderest = lhs - SCIPfeasFloor(scip, lhs/gcd) * gcd;
9796  if( SCIPisZero(scip, siderest) )
9797  siderest = gcd;
9798  }
9799 
9800  /* does the redundancy really is fulfilled */
9801  assert((hasrhs && SCIPisLE(scip, tmpmaxactsub, siderest) && tmpminactsub > siderest - gcd) || (haslhs && tmpmaxactsub < siderest && SCIPisGE(scip, tmpminactsub, siderest - gcd)));
9802 #endif
9803 
9804  SCIPdebugMessage("removing %d last variables from constraint <%s>, because they never change anything on the feasibility of this constraint\n", nvars - v, SCIPconsGetName(cons));
9805 
9806  /* remove redundant variables */
9807  for( w = nvars - 1; w >= v; --w )
9808  {
9809  SCIP_CALL( delCoefPos(scip, cons, w) );
9810  }
9811  (*nchgcoefs) += (nvars - v);
9812 
9813  assert(w >= 0);
9814 
9815  oldcoef = vals[w];
9816 
9817  /* normalize constraint */
9818  SCIP_CALL( normalizeCons(scip, cons) );
9819  assert(vars == consdata->vars);
9820  assert(vals == consdata->vals);
9821  assert(w < consdata->nvars);
9822 
9823  /* compute new greatest common divisor due to normalization */
9824  gcd = (SCIP_Longint)(gcd / (oldcoef/vals[w]) + feastol);
9825  assert(gcd >= 1);
9826 
9827  /* update side */
9828  if( hasrhs )
9829  {
9830  /* replace old with new right hand side */
9831  SCIP_CALL( chgRhs(scip, cons, SCIPfeasFloor(scip, consdata->rhs)) );
9832  rhs = consdata->rhs;
9833  }
9834  else
9835  {
9836  if( SCIPisFeasGT(scip, oldcoef/vals[w], 1.0) )
9837  {
9838  SCIP_CALL( chgLhs(scip, cons, SCIPfeasCeil(scip, consdata->lhs)) );
9839  lhs = consdata->lhs;
9840  }
9841  else
9842  assert(offsetv == -1 || SCIPisEQ(scip, vals[offsetv], consdata->lhs));
9843  }
9844  ++(*nchgsides);
9845 
9846  assert(!hasrhs || !SCIPisNegative(scip, rhs));
9847  assert(!haslhs || !SCIPisNegative(scip, lhs));
9848 
9849  /* get new constraint data */
9850  nvars = consdata->nvars;
9851  assert(nvars >= 2);
9852 
9853  allcoefintegral = TRUE;
9854 
9855 #ifndef NDEBUG
9856  /* check integrality */
9857  for( w = offsetv + 1; w < nvars; ++w )
9858  {
9859  assert(SCIPisIntegral(scip, vals[w]));
9860  }
9861 #endif
9862  SCIPdebugPrintCons(scip, cons, NULL);
9863  }
9864 
9865  /* try to find a better gcd, when having large coefficients */
9866  if( offsetv >= 0 && gcd == 1 )
9867  {
9868  /* calculate greatest common divisor for all general variables */
9869  gcd = (SCIP_Longint)(REALABS(vals[nvars - 1]) + feastol);
9870 
9871  if( gcd > 1 )
9872  {
9873  gcd = -1;
9874  candpos = -1;
9875 
9876  for( v = nvars - 1; v > offsetv; --v )
9877  {
9878  assert(!SCIPisZero(scip, vals[v]));
9879  if( SCIPvarGetType(vars[v]) == SCIP_VARTYPE_CONTINUOUS )
9880  break;
9881 
9882  if( !SCIPisIntegral(scip, vals[v]) )
9883  {
9884  allcoefintegral = FALSE;
9885  break;
9886  }
9887 
9888  oldgcd = gcd;
9889 
9890  if( gcd == -1 )
9891  {
9892  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
9893  assert(gcd >= 1);
9894  }
9895  else
9896  {
9897  /* calculate greatest common divisor for all general and binary variables */
9898  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
9899  }
9900 
9901  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
9902  * can stop searching
9903  */
9904  if( gcd == 1 )
9905  {
9906  if( !SCIPvarIsBinary(vars[v]) )
9907  break;
9908 
9909  /* found candidate */
9910  if( candpos == -1 )
9911  {
9912  gcd = oldgcd;
9913  candpos = v;
9914  }
9915  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
9916  else
9917  break;
9918  }
9919  }
9920  assert(v > offsetv || candpos > offsetv);
9921  }
9922  else
9923  candpos = -1;
9924  }
9925  else
9926  candpos = nvars - 1;
9927 
9928  /* check last coefficient for integrality */
9929  if( gcd > 1 && allcoefintegral && !redundant )
9930  {
9931  if( !SCIPisIntegral(scip, vals[nvars - 1]) )
9932  allcoefintegral = FALSE;
9933  }
9934 
9935  /* check for further necessary coefficient adjustments */
9936  if( offsetv >= 0 && gcd > 1 && allcoefintegral )
9937  {
9938  assert(offsetv + 1 < nvars);
9939  assert(0 <= candpos && candpos < nvars);
9940 
9941  if( SCIPvarGetType(vars[candpos]) != SCIP_VARTYPE_CONTINUOUS )
9942  {
9943  SCIP_Bool notchangable = FALSE;
9944 
9945 #ifndef NDEBUG
9946  /* check integrality */
9947  for( w = offsetv + 1; w < nvars; ++w )
9948  {
9949  assert(SCIPisIntegral(scip, vals[w]));
9950  }
9951 #endif
9952 
9953  if( vals[candpos] > 0 && SCIPvarIsBinary(vars[candpos]) &&
9954  SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) < gcd )
9955  {
9956  /* determine the remainder of the side and the gcd */
9957  if( hasrhs )
9958  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
9959  else
9960  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
9961  assert(rest >= 0);
9962  assert(rest < gcd);
9963 
9964  /* determine the remainder of the coefficient candidate and the gcd */
9965  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
9966  assert(restcoef >= 1);
9967  assert(restcoef < gcd);
9968 
9969  if( hasrhs )
9970  {
9971  /* calculate new coefficient */
9972  if( restcoef > rest )
9973  newcoef = vals[candpos] - restcoef + gcd;
9974  else
9975  newcoef = vals[candpos] - restcoef;
9976  }
9977  else
9978  {
9979  /* calculate new coefficient */
9980  if( rest == 0 || restcoef < rest )
9981  newcoef = vals[candpos] - restcoef;
9982  else
9983  newcoef = vals[candpos] - restcoef + gcd;
9984  }
9985 
9986  /* new coeffcient must not be zero if we would loose the implication that a variable needs to be 0 if
9987  * another with the big coefficient was set to 1
9988  */
9989  if( hasrhs && SCIPisZero(scip, newcoef) )
9990  {
9991  notchangable = TRUE;
9992  }
9993  else if( SCIPisZero(scip, newcoef) )
9994  {
9995  /* delete old redundant coefficient */
9996  SCIP_CALL( delCoefPos(scip, cons, candpos) );
9997  ++(*nchgcoefs);
9998  }
9999  else
10000  {
10001  /* replace old with new coefficient */
10002  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
10003  ++(*nchgcoefs);
10004  }
10005  }
10006  else if( vals[candpos] < 0 || !SCIPvarIsBinary(vars[candpos]) )
10007  {
10008  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol));
10009  }
10010 
10011  /* correct side and big coefficients */
10012  if( (!notchangable && hasrhs && ((!SCIPisFeasIntegral(scip, rhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(rhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd))) ||
10013  ( haslhs && (!SCIPisFeasIntegral(scip, lhs) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(lhs + feastol)) < gcd) && (SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[candpos]) + feastol)) == gcd)) )
10014  {
10015  if( haslhs )
10016  {
10017  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasCeil(scip, lhs/gcd) * gcd + feastol));
10018 
10019  SCIP_CALL( chgLhs(scip, cons, newcoef) );
10020  ++(*nchgsides);
10021  }
10022  else
10023  {
10024  assert(hasrhs);
10025  newcoef = (SCIP_Real)((SCIP_Longint)(SCIPfeasFloor(scip, rhs/gcd) * gcd + feastol));
10026 
10027  SCIP_CALL( chgRhs(scip, cons, newcoef) );
10028  ++(*nchgsides);
10029  }
10030 
10031  /* correct coefficients up front */
10032  for( w = offsetv; w >= 0; --w )
10033  {
10034  assert(vals[w] > 0);
10035 
10036  SCIP_CALL( chgCoefPos(scip, cons, w, newcoef) );
10037  }
10038  (*nchgcoefs) += (offsetv + 1);
10039  }
10040 
10041  if( !notchangable )
10042  {
10043  /* normalize constraint */
10044  SCIP_CALL( normalizeCons(scip, cons) );
10045  assert(vars == consdata->vars);
10046  assert(vals == consdata->vals);
10047 
10048  /* get new constraint data */
10049  nvars = consdata->nvars;
10050  assert(nvars >= 2);
10051 
10052  SCIPdebugPrintCons(scip, cons, NULL);
10053 
10054  lhs = consdata->lhs;
10055  rhs = consdata->rhs;
10056  assert(!hasrhs || !SCIPisNegative(scip, rhs));
10057  assert(!haslhs || !SCIPisNegative(scip, lhs));
10058  }
10059  }
10060  }
10061  }
10062 
10063  /* @todo we still can remove continuous variables if they are redundant due to the non-integrality argument */
10064  /* no continuous variables are left over */
10065  if( SCIPvarGetType(vars[nvars - 1]) == SCIP_VARTYPE_CONTINUOUS )
10066  return SCIP_OKAY;
10067 
10068  onlybin = TRUE;
10069  allcoefintegral = TRUE;
10070  /* check if all variables are of binary type */
10071  for( v = nvars - 1; v >= 0; --v )
10072  {
10073  if( !SCIPvarIsBinary(vars[v]) )
10074  onlybin = FALSE;
10075  if( !SCIPisIntegral(scip, vals[v]) )
10076  allcoefintegral = FALSE;
10077  }
10078 
10079  /* check if the non-integrality part of all integral variables is smaller than the non-inegrality part of the right
10080  * hand side or bigger than the left hand side respectively, so we can make all of them integral
10081  *
10082  * @todo there are some steps missing ....
10083  */
10084  if( (hasrhs && !SCIPisFeasIntegral(scip, rhs)) || (haslhs && !SCIPisFeasIntegral(scip, lhs)) )
10085  {
10086  SCIP_Real val;
10087  SCIP_Real newval;
10088  SCIP_Real frac = 0.0;
10089  SCIP_Bool found = FALSE;
10090 
10091  if( hasrhs )
10092  {
10093  if( allcoefintegral )
10094  {
10095  /* replace old with new right hand side */
10096  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
10097  ++(*nchgsides);
10098  }
10099  else
10100  {
10101  siderest = rhs - SCIPfloor(scip, rhs);
10102 
10103  /* try to round down all non-integral coefficients */
10104  for( v = nvars - 1; v >= 0; --v )
10105  {
10106  val = vals[v];
10107 
10108  /* add up all possible fractional parts */
10109  if( !SCIPisIntegral(scip, val) )
10110  {
10111  lb = SCIPvarGetLbGlobal(vars[v]);
10112  ub = SCIPvarGetUbGlobal(vars[v]);
10113 
10114  /* at least one bound need to be at zero */
10115  if( !onlybin && !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
10116  return SCIP_OKAY;
10117 
10118  /* swap bounds for 'standard' form */
10119  if( !SCIPisFeasZero(scip, lb) )
10120  {
10121  SCIP_Real tmp = lb;
10122  lb = ub;
10123  ub = tmp;
10124  val *= -1;
10125  }
10126 
10127  found = TRUE;
10128 
10129  frac += (val - SCIPfloor(scip, val)) * ub;
10130 
10131  /* if we exceed the fractional part of the right hand side, we cannot tighten the coefficients
10132  *
10133  * e.g. 1.1x1 + 1.1x2 + 1.4x3 + 1.02x4 <= 2.4, here we cannot floor all fractionals because
10134  * x3, x4 set to 1 would be infeasible but feasible after flooring
10135  */
10136  if( SCIPisGT(scip, frac, siderest) )
10137  return SCIP_OKAY;
10138  }
10139  }
10140  assert(v == -1);
10141 
10142  SCIPdebugMessage("rounding all non-integral coefficients and the right hand side down\n");
10143 
10144  /* round rhs and coefficients to integral values */
10145  if( found )
10146  {
10147  for( v = nvars - 1; v >= 0; --v )
10148  {
10149  val = vals[v];
10150 
10151  /* add the whole fractional part */
10152  if( !SCIPisIntegral(scip, val) )
10153  {
10154  lb = SCIPvarGetLbGlobal(vars[v]);
10155 
10156  if( SCIPisFeasZero(scip, lb) )
10157  newval = SCIPfloor(scip, val);
10158  else
10159  newval = SCIPceil(scip, val);
10160 
10161  if( SCIPisZero(scip, newval) )
10162  {
10163  /* delete old redundant coefficient */
10164  SCIP_CALL( delCoefPos(scip, cons, v) );
10165  ++(*nchgcoefs);
10166  }
10167  else
10168  {
10169  /* replace old with new coefficient */
10170  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
10171  ++(*nchgcoefs);
10172  }
10173  }
10174  }
10175  }
10176 
10177  /* replace old with new right hand side */
10178  SCIP_CALL( chgRhs(scip, cons, SCIPfloor(scip, rhs)) );
10179  ++(*nchgsides);
10180  }
10181  }
10182  else
10183  {
10184  if( allcoefintegral )
10185  {
10186  /* replace old with new left hand side */
10187  SCIP_CALL( chgLhs(scip, cons, SCIPceil(scip, lhs)) );
10188  ++(*nchgsides);
10189  }
10190  else
10191  {
10192  /* cannot floor left hand side to zero */
10193  if( SCIPisLT(scip, lhs, 1.0) )
10194  return SCIP_OKAY;
10195 
10196  siderest = lhs - SCIPfloor(scip, lhs);
10197 
10198  /* try to round down all non-integral coefficients */
10199  for( v = nvars - 1; v >= 0; --v )
10200  {
10201  val = vals[v];
10202 
10203  /* add up all possible fractional parts */
10204  if( !SCIPisIntegral(scip, val) )
10205  {
10206  lb = SCIPvarGetLbGlobal(vars[v]);
10207  ub = SCIPvarGetUbGlobal(vars[v]);
10208 
10209  /* at least one bound need to be at zero */
10210  if( !SCIPisFeasZero(scip, lb) && !SCIPisFeasZero(scip, ub) )
10211  return SCIP_OKAY;
10212 
10213  /* swap bounds for 'standard' form */
10214  if( !SCIPisFeasZero(scip, lb) )
10215  {
10216  SCIP_Real tmp = lb;
10217  lb = ub;
10218  ub = tmp;
10219  val *= -1;
10220  }
10221 
10222  /* cannot floor to zero */
10223  if( SCIPisLT(scip, val, 1.0) )
10224  return SCIP_OKAY;
10225 
10226  /* the fractional part on each variable need to exceed the fractional part on the left hand side */
10227  if( SCIPisLT(scip, val - SCIPfloor(scip, val), siderest) )
10228  return SCIP_OKAY;
10229 
10230  found = TRUE;
10231 
10232  frac += (val - SCIPfloor(scip, val)) * ub;
10233 
10234  /* if we exceed the fractional part of the left hand side plus one by summing up all maximal
10235  * fractional parts of the variables, we cannot tighten the coefficients
10236  *
10237  * e.g. 4.3x1 + 1.3x2 + 1.3x3 + 1.6x4 >= 4.2, here we cannot floor all fractionals because
10238  * x2-x4 set to 1 would be feasible but not after flooring
10239  */
10240  if( SCIPisGE(scip, frac, 1 + siderest) )
10241  return SCIP_OKAY;
10242  }
10243  /* all coefficients need to be integral, otherwise we might do an invalid reduction */
10244  else
10245  return SCIP_OKAY;
10246  }
10247  assert(v == -1);
10248 
10249  SCIPdebugMessage("rounding all non-integral coefficients and the left hand side down\n");
10250 
10251  /* round lhs and coefficients to integral values */
10252  if( found )
10253  {
10254  for( v = nvars - 1; v >= 0; --v )
10255  {
10256  val = vals[v];
10257 
10258  /* add the whole fractional part */
10259  if( !SCIPisIntegral(scip, val) )
10260  {
10261  lb = SCIPvarGetLbGlobal(vars[v]);
10262 
10263  if( SCIPisFeasZero(scip, lb) )
10264  newval = SCIPfloor(scip, val);
10265  else
10266  newval = SCIPceil(scip, val);
10267 
10268  if( SCIPisZero(scip, newval) )
10269  {
10270  /* delete old redundant coefficient */
10271  SCIP_CALL( delCoefPos(scip, cons, v) );
10272  ++(*nchgcoefs);
10273  }
10274  else
10275  {
10276  /* replace old with new coefficient */
10277  SCIP_CALL( chgCoefPos(scip, cons, v, newval) );
10278  ++(*nchgcoefs);
10279  }
10280  }
10281  }
10282  }
10283 
10284  /* replace old with new left hand side */
10285  SCIP_CALL( chgLhs(scip, cons, SCIPfloor(scip, lhs)) );
10286  ++(*nchgsides);
10287  }
10288  }
10289 
10290  /* normalize constraint */
10291  SCIP_CALL( normalizeCons(scip, cons) );
10292  assert(vars == consdata->vars);
10293  assert(vals == consdata->vals);
10294 
10295  rhs = consdata->rhs;
10296  lhs = consdata->lhs;
10297 
10298  assert(!hasrhs || !SCIPisNegative(scip, rhs));
10299  assert(!haslhs || !SCIPisNegative(scip, lhs));
10300 
10301  SCIPdebugPrintCons(scip, cons, NULL);
10302 
10303  nvars = consdata->nvars;
10304  if( nvars < 2 )
10305  return SCIP_OKAY;
10306 
10307  allcoefintegral = TRUE;
10308 #ifndef NDEBUG
10309  /* debug check if all coefficients are really integral */
10310  for( v = nvars - 1; v >= 0; --v )
10311  assert(SCIPisIntegral(scip, vals[v]));
10312 #endif
10313  }
10314 
10315  /* @todo following can also work on non integral coefficients, need more investigation */
10316  /* only check constraints with integral coefficients on all integral variables */
10317  if( !allcoefintegral )
10318  return SCIP_OKAY;
10319 
10320  /* we want to avoid numerical troubles, therefore we do not change non-integral sides */
10321  if( (hasrhs && !SCIPisIntegral(scip, rhs)) || (haslhs && !SCIPisIntegral(scip, lhs)) )
10322  return SCIP_OKAY;
10323 
10324  /* maximal absolute value of coefficients in constraint is one, so we cannot tighten it further */
10325  if( SCIPisEQ(scip, REALABS(vals[0]), 1.0) )
10326  return SCIP_OKAY;
10327 
10328  /* stop if the last coeffcients is one in absolute value and the variable is not binary */
10329  if( !SCIPvarIsBinary(vars[nvars - 1]) && SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) )
10330  return SCIP_OKAY;
10331 
10332  assert(nvars >= 2);
10333 
10334  /* start gcd procedure for all variables */
10335 
10336  do
10337  {
10338  oldnchgcoefs = *nchgcoefs;
10339  oldnchgsides = *nchgsides;
10340 
10341  /* stop if we have two coeffcients which are one in absolute value */
10342  if( SCIPisEQ(scip, REALABS(vals[nvars - 1]), 1.0) && SCIPisEQ(scip, REALABS(vals[nvars - 2]), 1.0) )
10343  return SCIP_OKAY;
10344 
10345  gcd = -1;
10346 
10347  /* calculate greatest common divisor over all integer variables */
10348  if( !onlybin )
10349  {
10350  foundbin = -1;
10351 
10352  for( v = nvars - 1; v >= 0; --v )
10353  {
10354  assert(!SCIPisZero(scip, vals[v]));
10355  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS);
10356 
10357  if( SCIPvarIsBinary(vars[v]) )
10358  {
10359  if( foundbin == -1 )
10360  foundbin = v;
10361  continue;
10362  }
10363 
10364  absval = REALABS(vals[v]);
10365  assert(SCIPisIntegral(scip, absval));
10366 
10367  if( gcd == -1 )
10368  {
10369  gcd = (SCIP_Longint)(absval + feastol);
10370  assert(gcd >= 1);
10371  }
10372  else
10373  {
10374  /* calculate greatest common divisor for all general variables */
10375  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(absval + feastol));
10376  }
10377  if( gcd == 1 )
10378  break;
10379  }
10380  }
10381  else
10382  foundbin = nvars - 1;
10383 
10384  /* we need at least one binary variable and a gcd greater than 1 to try to perform further coefficient changes */
10385  if( gcd == 1 || foundbin == -1)
10386  return SCIP_OKAY;
10387 
10388  assert((onlybin && gcd == -1) || (!onlybin && gcd > 1));
10389 
10390  candpos = -1;
10391  candpos2 = -1;
10392 
10393  /* calculate greatest common divisor over all integer and binary variables and determine the candidate where we might
10394  * change the coefficient
10395  */
10396  for( v = foundbin; v >= 0; --v )
10397  {
10398  if( onlybin || SCIPvarIsBinary(vars[v]) )
10399  {
10400  absval = REALABS(vals[v]);
10401  assert(SCIPisIntegral(scip, absval));
10402 
10403  oldgcd = gcd;
10404 
10405  if( gcd == -1 )
10406  {
10407  gcd = (SCIP_Longint)(REALABS(vals[v]) + feastol);
10408  assert(gcd >= 1);
10409  }
10410  else
10411  {
10412  /* calculate greatest common divisor for all general and binary variables */
10413  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
10414  }
10415 
10416  /* if the greatest commmon divisor has become 1, we might have found the possible coefficient to change or we
10417  * can terminate
10418  */
10419  if( gcd == 1 )
10420  {
10421  /* found candidate */
10422  if( candpos == -1 )
10423  {
10424  gcd = oldgcd;
10425  candpos = v;
10426 
10427  /* if we have only binary variables and both first coefficients have a gcd of 1, both are candidates for
10428  * the coefficient change
10429  */
10430  if( onlybin && v == foundbin - 1 )
10431  candpos2 = foundbin;
10432  }
10433  /* two different binary variables lead to a gcd of one, so we cannot change a coefficient */
10434  else
10435  {
10436  if( onlybin && candpos == v + 1 && candpos2 == v + 2 )
10437  {
10438  assert(candpos2 == nvars - 1);
10439 
10440  /* take new candidates */
10441  candpos = candpos2;
10442 
10443  /* recalculate gcd from scratch */
10444  gcd = (SCIP_Longint)(REALABS(vals[v+1]) + feastol);
10445  assert(gcd >= 1);
10446 
10447  /* calculate greatest common divisor for all general and binary variables */
10448  gcd = SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(vals[v]) + feastol));
10449  if( gcd == 1 )
10450  return SCIP_OKAY;
10451  }
10452  else
10453  /* cannot determine a possible coefficient for reduction */
10454  return SCIP_OKAY;
10455  }
10456  }
10457  }
10458  }
10459  assert(gcd >= 2);
10460 
10461  /* we should have found one coefficient, that led to a gcd of 1, otherwise we could normalize the constraint
10462  * further
10463  */
10464  assert(candpos >= 0 && candpos < nvars);
10465 
10466  /* all variables and all coefficients are integral, so the side should be too */
10467  assert((hasrhs && SCIPisIntegral(scip, rhs)) || (haslhs && SCIPisIntegral(scip, lhs)));
10468 
10469  /* check again, if we have a normalized inequality (not ranged) the one side should be positive,
10470  * @see normalizeCons()
10471  */
10472  assert(!hasrhs || !SCIPisNegative(scip, rhs));
10473  assert(!haslhs || !SCIPisNegative(scip, lhs));
10474 
10475  /* determine the remainder of the side and the gcd */
10476  if( hasrhs )
10477  rest = ((SCIP_Longint)(rhs + feastol)) % gcd;
10478  else
10479  rest = ((SCIP_Longint)(lhs + feastol)) % gcd;
10480  assert(rest >= 0);
10481  assert(rest < gcd);
10482 
10483  /* determine the remainder of the coefficient candidate and the gcd */
10484  if( vals[candpos] < 0 )
10485  {
10486  restcoef = ((SCIP_Longint)(vals[candpos] - feastol)) % gcd;
10487  assert(restcoef <= -1);
10488  restcoef += gcd;
10489  }
10490  else
10491  restcoef = ((SCIP_Longint)(vals[candpos] + feastol)) % gcd;
10492  assert(restcoef >= 1);
10493  assert(restcoef < gcd);
10494 
10495  if( hasrhs )
10496  {
10497  if( rest > 0 )
10498  {
10499  /* replace old with new right hand side */
10500  SCIP_CALL( chgRhs(scip, cons, rhs - rest) );
10501  ++(*nchgsides);
10502  }
10503 
10504  /* calculate new coefficient */
10505  if( restcoef > rest )
10506  newcoef = vals[candpos] - restcoef + gcd;
10507  else
10508  newcoef = vals[candpos] - restcoef;
10509  }
10510  else
10511  {
10512  if( rest > 0 )
10513  {
10514  /* replace old with new left hand side */
10515  SCIP_CALL( chgLhs(scip, cons, lhs - rest + gcd) );
10516  ++(*nchgsides);
10517  }
10518 
10519  /* calculate new coefficient */
10520  if( rest == 0 || restcoef < rest )
10521  newcoef = vals[candpos] - restcoef;
10522  else
10523  newcoef = vals[candpos] - restcoef + gcd;
10524  }
10525  assert(SCIPisZero(scip, newcoef) || SCIPcalcGreComDiv(gcd, (SCIP_Longint)(REALABS(newcoef) + feastol)) == gcd);
10526 
10527  SCIPdebugMessage("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));
10528 
10529  if( SCIPisZero(scip, newcoef) )
10530  {
10531  /* delete redundant coefficient */
10532  SCIP_CALL( delCoefPos(scip, cons, candpos) );
10533  }
10534  else
10535  {
10536  /* replace old with new coefficient */
10537  SCIP_CALL( chgCoefPos(scip, cons, candpos, newcoef) );
10538  }
10539  ++(*nchgcoefs);
10540 
10541  /* now constraint can be normalized, might be directly done by dividing it by the gcd */
10542  SCIP_CALL( normalizeCons(scip, cons) );
10543  assert(vars == consdata->vars);
10544  assert(vals == consdata->vals);
10545 
10546  SCIPdebugPrintCons(scip, cons, NULL);
10547 
10548  rhs = consdata->rhs;
10549  lhs = consdata->lhs;
10550  assert(!hasrhs || !SCIPisNegative(scip, rhs));
10551  assert(!haslhs || !SCIPisNegative(scip, lhs));
10552 
10553  nvars = consdata->nvars;
10554 
10555  SCIPdebugMessage("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));
10556  }
10557  while( nvars >= 2 );
10558 
10559  return SCIP_OKAY;
10560 }
10561 
10562 
10563 /* tries to aggregate an (in)equality and an equality in order to decrease the number of variables in the (in)equality:
10564  * cons0 := a * cons0 + b * cons1,
10565  * where a = val1[v] and b = -val0[v] for common variable v which removes most variable weight;
10566  * for numerical stability, we will only accept integral a and b;
10567  * the variable weight is a weighted sum over all included variables, where each binary variable weighs BINWEIGHT,
10568  * each integer or implicit integer variable weighs INTWEIGHT and each continuous variable weighs CONTWEIGHT
10569  */
10570 static
10572  SCIP* scip, /**< SCIP data structure */
10573  SCIP_CONS* cons0, /**< (in)equality to modify */
10574  SCIP_CONS* cons1, /**< equality to use for aggregation of cons0 */
10575  int* commonidx0, /**< array with indices of variables in cons0, that appear also in cons1 */
10576  int* commonidx1, /**< array with indices of variables in cons1, that appear also in cons0 */
10577  int* diffidx0minus1, /**< array with indices of variables in cons0, that don't appear in cons1 */
10578  int* diffidx1minus0, /**< array with indices of variables in cons1, that don't appear in cons0 */
10579  int nvarscommon, /**< number of variables, that appear in both constraints */
10580  int commonidxweight, /**< variable weight sum of common variables */
10581  int diffidx0minus1weight, /**< variable weight sum of variables in cons0, that don't appear in cons1 */
10582  int diffidx1minus0weight, /**< variable weight sum of variables in cons1, that don't appear in cons0 */
10583  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
10584  int* nchgcoefs, /**< pointer to count the number of changed coefficients */
10585  SCIP_Bool* aggregated /**< pointer to store whether an aggregation was made */
10586  )
10587 {
10588  SCIP_CONSDATA* consdata0;
10589  SCIP_CONSDATA* consdata1;
10590  SCIP_Real a;
10591  SCIP_Real b;
10592  SCIP_Real aggrcoef;
10593  SCIP_Real scalarsum;
10594  SCIP_Real bestscalarsum;
10595  SCIP_Bool betterscalarsum;
10596  SCIP_Bool commonvarlindependent; /* indicates whether coefficient vector of common variables in linearly dependent */
10597  int varweight;
10598  int nvars;
10599  int bestvarweight;
10600  int bestnvars;
10601  int bestv;
10602  int v;
10603  int i;
10604 
10605  assert(scip != NULL);
10606  assert(cons0 != NULL);
10607  assert(cons1 != NULL);
10608  assert(commonidx0 != NULL);
10609  assert(commonidx1 != NULL);
10610  assert(diffidx0minus1 != NULL);
10611  assert(diffidx1minus0 != NULL);
10612  assert(nvarscommon >= 1);
10613  assert(commonidxweight >= nvarscommon);
10614  assert(nchgcoefs != NULL);
10615  assert(aggregated != NULL);
10616 
10617  assert(SCIPconsIsActive(cons0));
10618  assert(SCIPconsIsActive(cons1));
10619 
10620  SCIPdebugMessage("try aggregation of <%s> and <%s>\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
10621 
10622  /* cons0 is an (in)equality */
10623  consdata0 = SCIPconsGetData(cons0);
10624  assert(consdata0 != NULL);
10625  assert(consdata0->nvars >= 1);
10626  assert(SCIPisLE(scip, consdata0->lhs, consdata0->rhs));
10627  assert(diffidx0minus1weight >= consdata0->nvars - nvarscommon);
10628 
10629  /* cons1 is an equality */
10630  consdata1 = SCIPconsGetData(cons1);
10631  assert(consdata1 != NULL);
10632  assert(consdata1->nvars >= 1);
10633  assert(SCIPisEQ(scip, consdata1->lhs, consdata1->rhs));
10634  assert(diffidx1minus0weight >= consdata1->nvars - nvarscommon);
10635 
10636  *aggregated = FALSE;
10637 
10638  /* search for the best common variable such that
10639  * val1[var] * consdata0 - val0[var] * consdata1
10640  * has least weighted number of variables
10641  */
10642  bestvarweight = commonidxweight + diffidx0minus1weight;
10643  bestnvars = consdata0->nvars;
10644  bestv = -1;
10645  bestscalarsum = 0.0;
10646  commonvarlindependent = TRUE;
10647  for( v = 0; v < nvarscommon; ++v )
10648  {
10649  assert(consdata0->vars[commonidx0[v]] == consdata1->vars[commonidx1[v]]);
10650  a = consdata1->vals[commonidx1[v]];
10651  b = -consdata0->vals[commonidx0[v]];
10652 
10653  /* only try aggregation, if coefficients are integral (numerical stability) */
10654  if( SCIPisIntegral(scip, a) && SCIPisIntegral(scip, b) )
10655  {
10656  /* count the number of variables in the potential new constraint a * consdata0 + b * consdata1 */
10657  varweight = diffidx0minus1weight + diffidx1minus0weight;
10658  nvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
10659  scalarsum = REALABS(a) + REALABS(b);
10660  betterscalarsum = (scalarsum < bestscalarsum);
10661  for( i = 0; i < nvarscommon
10662  && (varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum)); ++i )
10663  {
10664  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
10665  if( !SCIPisZero(scip, aggrcoef) )
10666  {
10667  varweight += getVarWeight(consdata0->vars[commonidx0[i]]);
10668  nvars++;
10669  }
10670  }
10671  if( varweight < bestvarweight || (varweight == bestvarweight && betterscalarsum) )
10672  {
10673  bestv = v;
10674  bestvarweight = varweight;
10675  bestnvars = nvars;
10676  bestscalarsum = scalarsum;
10677  }
10678  }
10679 
10680  /* update commonvarlindependent flag, if still TRUE:
10681  * 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
10682  */
10683  if( commonvarlindependent && v > 0 )
10684  commonvarlindependent = SCIPisEQ(scip,
10685  consdata1->vals[commonidx1[v]] * consdata0->vals[commonidx0[0]],
10686  consdata1->vals[commonidx1[0]] * consdata0->vals[commonidx0[v]]);
10687  }
10688 
10689  /* if better aggregation was found, create new constraint and delete old one */
10690  if( (bestv != -1 || commonvarlindependent) && SCIPconsGetNUpgradeLocks(cons0) == 0 )
10691  {
10692  SCIP_CONS* newcons;
10693  SCIP_CONSDATA* newconsdata;
10694  SCIP_VAR** newvars;
10695  SCIP_Real* newvals;
10696  SCIP_Real newlhs;
10697  SCIP_Real newrhs;
10698  int newnvars;
10699 
10700  if( bestv != -1 )
10701  {
10702  /* choose multipliers such that the multiplier for the (in)equality cons0 is positive */
10703  if( consdata1->vals[commonidx1[bestv]] > 0.0 )
10704  {
10705  a = consdata1->vals[commonidx1[bestv]];
10706  b = -consdata0->vals[commonidx0[bestv]];
10707  }
10708  else
10709  {
10710  a = -consdata1->vals[commonidx1[bestv]];
10711  b = consdata0->vals[commonidx0[bestv]];
10712  }
10713  assert(SCIPisIntegral(scip, a));
10714  assert(SCIPisPositive(scip, a));
10715  assert(SCIPisIntegral(scip, b));
10716  assert(!SCIPisZero(scip, b));
10717  }
10718  else
10719  {
10720  assert(commonvarlindependent);
10721  if( consdata1->vals[commonidx1[0]] > 0.0 )
10722  {
10723  a = consdata1->vals[commonidx1[0]];
10724  b = -consdata0->vals[commonidx0[0]];
10725  }
10726  else
10727  {
10728  a = -consdata1->vals[commonidx1[0]];
10729  b = consdata0->vals[commonidx0[0]];
10730  }
10731  assert(SCIPisPositive(scip, a));
10732  assert(!SCIPisZero(scip, b));
10733 
10734  /* if a/b is integral, then we can easily choose integer multipliers */
10735  if( SCIPisIntegral(scip, a/b) )
10736  {
10737  if( a/b > 0 )
10738  {
10739  a /= b;
10740  b = 1.0;
10741  }
10742  else
10743  {
10744  a /= -b;
10745  b = -1.0;
10746  }
10747  }
10748 
10749  /* setup best* variables that were not setup above because we are in the commonvarlindependent case */
10750  bestvarweight = diffidx0minus1weight + diffidx1minus0weight;
10751  bestnvars = consdata0->nvars + consdata1->nvars - 2*nvarscommon;
10752  }
10753 
10754  SCIPdebugMessage("aggregate linear constraints <%s> := %.15g*<%s> + %.15g*<%s> -> nvars: %d -> %d, weight: %d -> %d\n",
10755  SCIPconsGetName(cons0), a, SCIPconsGetName(cons0), b, SCIPconsGetName(cons1),
10756  consdata0->nvars, bestnvars, commonidxweight + diffidx0minus1weight, bestvarweight);
10757  SCIPdebugPrintCons(scip, cons0, NULL);
10758  SCIPdebugPrintCons(scip, cons1, NULL);
10759 
10760  /* get temporary memory for creating the new linear constraint */
10761  SCIP_CALL( SCIPallocBufferArray(scip, &newvars, bestnvars) );
10762  SCIP_CALL( SCIPallocBufferArray(scip, &newvals, bestnvars) );
10763 
10764  /* calculate the common coefficients, if we have not recognized linear dependency */
10765  newnvars = 0;
10766  if( !commonvarlindependent )
10767  {
10768  for( i = 0; i < nvarscommon; ++i )
10769  {
10770  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
10771  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
10772 
10773  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
10774  if( !SCIPisZero(scip, aggrcoef) )
10775  {
10776  assert(newnvars < bestnvars);
10777  newvars[newnvars] = consdata0->vars[commonidx0[i]];
10778  newvals[newnvars] = aggrcoef;
10779  newnvars++;
10780  }
10781  }
10782  }
10783  else
10784  {
10785  /* if we recognized linear dependency of the common coefficients, then the aggregation coefficient should be 0.0 for every common variable */
10786 #ifndef NDEBUG
10787  for( i = 0; i < nvarscommon; ++i )
10788  {
10789  assert(0 <= commonidx0[i] && commonidx0[i] < consdata0->nvars);
10790  assert(0 <= commonidx1[i] && commonidx1[i] < consdata1->nvars);
10791 
10792  aggrcoef = a * consdata0->vals[commonidx0[i]] + b * consdata1->vals[commonidx1[i]];
10793  assert(SCIPisZero(scip, aggrcoef));
10794  }
10795 #endif
10796  }
10797 
10798  /* calculate the coefficients appearing in cons0 but not in cons1 */
10799  for( i = 0; i < consdata0->nvars - nvarscommon; ++i )
10800  {
10801  assert(0 <= diffidx0minus1[i] && diffidx0minus1[i] < consdata0->nvars);
10802 
10803  aggrcoef = a * consdata0->vals[diffidx0minus1[i]];
10804  assert(!SCIPisZero(scip, aggrcoef));
10805  assert(newnvars < bestnvars);
10806  newvars[newnvars] = consdata0->vars[diffidx0minus1[i]];
10807  newvals[newnvars] = aggrcoef;
10808  newnvars++;
10809  }
10810 
10811  /* calculate the coefficients appearing in cons1 but not in cons0 */
10812  for( i = 0; i < consdata1->nvars - nvarscommon; ++i )
10813  {
10814  assert(0 <= diffidx1minus0[i] && diffidx1minus0[i] < consdata1->nvars);
10815 
10816  aggrcoef = b * consdata1->vals[diffidx1minus0[i]];
10817  assert(!SCIPisZero(scip, aggrcoef));
10818  assert(newnvars < bestnvars);
10819  newvars[newnvars] = consdata1->vars[diffidx1minus0[i]];
10820  newvals[newnvars] = aggrcoef;
10821  newnvars++;
10822  }
10823  assert(newnvars == bestnvars);
10824 
10825  /* calculate the new left and right hand side of the (in)equality */
10826  assert(!SCIPisInfinity(scip, -consdata1->lhs));
10827  assert(!SCIPisInfinity(scip, consdata1->rhs));
10828  if( SCIPisInfinity(scip, -consdata0->lhs) )
10829  newlhs = -SCIPinfinity(scip);
10830  else
10831  newlhs = a * consdata0->lhs + b * consdata1->lhs;
10832  if( SCIPisInfinity(scip, consdata0->rhs) )
10833  newrhs = SCIPinfinity(scip);
10834  else
10835  newrhs = a * consdata0->rhs + b * consdata1->rhs;
10836 
10837  /* create the new linear constraint */
10838  SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, SCIPconsGetName(cons0), newnvars, newvars, newvals, newlhs, newrhs,
10840  SCIPconsIsChecked(cons0), SCIPconsIsPropagated(cons0),
10841  SCIPconsIsLocal(cons0), SCIPconsIsModifiable(cons0),
10843 
10844  newconsdata = SCIPconsGetData(newcons);
10845  assert(newconsdata != NULL);
10846 
10847  /* copy the upgraded flag from the old cons0 to the new constraint */
10848  newconsdata->upgraded = consdata0->upgraded;
10849 
10850  /* normalize the new constraint */
10851  SCIP_CALL( normalizeCons(scip, newcons) );
10852 
10853  /* check, if we really want to use the new constraint instead of the old one:
10854  * use the new one, if the maximum norm doesn't grow too much
10855  */
10856  if( consdataGetMaxAbsval(SCIPconsGetData(newcons)) <= maxaggrnormscale * consdataGetMaxAbsval(consdata0) )
10857  {
10858  SCIPdebugMessage(" -> aggregated to <%s>\n", SCIPconsGetName(newcons));
10859  SCIPdebugPrintCons(scip, newcons, NULL);
10860 
10861  /* update the statistics: we changed all coefficients */
10862  if( !consdata0->upgraded )
10863  (*nchgcoefs) += consdata0->nvars + consdata1->nvars - nvarscommon;
10864  *aggregated = TRUE;
10865 
10866  /* delete the old constraint, and add the new linear constraint to the problem */
10867  SCIP_CALL( SCIPdelCons(scip, cons0) );
10868  SCIP_CALL( SCIPaddCons(scip, newcons) );
10869  }
10870 
10871  /* release the new constraint */
10872  SCIP_CALL( SCIPreleaseCons(scip, &newcons) );
10873 
10874  /* free temporary memory */
10875  SCIPfreeBufferArray(scip, &newvals);
10876  SCIPfreeBufferArray(scip, &newvars);
10877  }
10878 
10879  return SCIP_OKAY;
10880 }
10881 
10882 /** gets the key of the given element */
10883 static
10884 SCIP_DECL_HASHGETKEY(hashGetKeyLinearcons)
10885 { /*lint --e{715}*/
10886  /* the key is the element itself */
10887  return elem;
10888 }
10889 
10890 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables and the
10891  * coefficients are either equal or negated
10892  */
10893 static
10894 SCIP_DECL_HASHKEYEQ(hashKeyEqLinearcons)
10895 {
10896  SCIP* scip;
10897  SCIP_CONSDATA* consdata1;
10898  SCIP_CONSDATA* consdata2;
10899  SCIP_Bool coefsequal;
10900  SCIP_Bool coefsnegated;
10901  int i;
10902 
10903  assert(key1 != NULL);
10904  assert(key2 != NULL);
10905  consdata1 = SCIPconsGetData((SCIP_CONS*)key1);
10906  consdata2 = SCIPconsGetData((SCIP_CONS*)key2);
10907  assert(consdata1->sorted);
10908  assert(consdata2->sorted);
10909 
10910  scip = (SCIP*)userptr;
10911  assert(scip != NULL);
10912 
10913  /* checks trivial case */
10914  if( consdata1->nvars != consdata2->nvars )
10915  return FALSE;
10916 
10917  coefsequal = TRUE;
10918  coefsnegated = TRUE;
10919 
10920  for( i = 0; i < consdata1->nvars && (coefsequal || coefsnegated); ++i )
10921  {
10922  SCIP_Real val1;
10923  SCIP_Real val2;
10924 
10925  /* tests if variables are equal */
10926  if( consdata1->vars[i] != consdata2->vars[i] )
10927  {
10928  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 1 ||
10929  SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == -1);
10930  coefsequal = FALSE;
10931  coefsnegated = FALSE;
10932  break;
10933  }
10934  assert(SCIPvarCompare(consdata1->vars[i], consdata2->vars[i]) == 0);
10935 
10936  /* tests if coefficients are either equal or negated */
10937  val1 = consdata1->vals[i];
10938  val2 = consdata2->vals[i];
10939  coefsequal = coefsequal && SCIPisEQ(scip, val1, val2);
10940  coefsnegated = coefsnegated && SCIPisEQ(scip, val1, -val2);
10941  }
10942 
10943  return (coefsequal || coefsnegated);
10944 }
10945 
10946 #define MULTIPLIER 2048
10947 /** returns the hash value of the key */
10948 static
10949 SCIP_DECL_HASHKEYVAL(hashKeyValLinearcons)
10950 {
10951  SCIP_CONSDATA* consdata;
10952  SCIP_Real maxabsrealval;
10953  unsigned int hashval;
10954  int minidx;
10955  int mididx;
10956  int maxidx;
10957  int addval;
10958 #ifndef NDEBUG
10959  SCIP* scip;
10960 
10961  scip = (SCIP*)userptr;
10962  assert(scip != NULL);
10963 #endif
10964 
10965  assert(key != NULL);
10966  consdata = SCIPconsGetData((SCIP_CONS*)key);
10967  assert(consdata != NULL);
10968  assert(consdata->nvars > 0);
10969 
10970  assert(consdata->sorted);
10971 
10972  minidx = SCIPvarGetIndex(consdata->vars[0]);
10973  mididx = SCIPvarGetIndex(consdata->vars[consdata->nvars / 2]);
10974  maxidx = SCIPvarGetIndex(consdata->vars[consdata->nvars - 1]);
10975  assert(minidx >= 0 && minidx <= maxidx);
10976 
10977  addval = (int) REALABS(consdata->vals[0]);
10978  addval += (((int) REALABS(consdata->vals[consdata->nvars / 2])) << 4); /*lint !e701*/
10979  addval += (((int) REALABS(consdata->vals[consdata->nvars - 1])) << 8); /*lint !e701*/
10980 
10981  maxabsrealval = consdataGetMaxAbsval(consdata);
10982  /* hash value depends on vectors of variable indices */
10983  if( maxabsrealval < (SCIP_Real) INT_MAX )
10984  {
10985  if( maxabsrealval < 1.0 )
10986  addval += (int) (MULTIPLIER * maxabsrealval);
10987  else
10988  addval += (int) maxabsrealval;
10989  }
10990 
10991  hashval = (consdata->nvars << 29) + (minidx << 22) + (mididx << 11) + maxidx + addval; /*lint !e701*/
10992 
10993  return hashval;
10994 }
10995 
10996 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
10997  * accordingly; in contrast to preprocessConstraintPairs(), it uses a hash table
10998  */
10999 static
11001  SCIP* scip, /**< SCIP data structure */
11002  BMS_BLKMEM* blkmem, /**< block memory */
11003  SCIP_CONS** conss, /**< constraint set */
11004  int nconss, /**< number of constraints in constraint set */
11005  int* firstchange, /**< pointer to store first changed constraint */
11006  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11007  int* ndelconss, /**< pointer to count number of deleted constraints */
11008  int* nchgsides /**< pointer to count number of changed left/right hand sides */
11009  )
11010 {
11011  SCIP_HASHTABLE* hashtable;
11012  int hashtablesize;
11013  int c;
11014 
11015  assert(scip != NULL);
11016  assert(blkmem != NULL);
11017  assert(conss != NULL);
11018  assert(firstchange != NULL);
11019  assert(cutoff != NULL);
11020  assert(ndelconss != NULL);
11021  assert(nchgsides != NULL);
11022 
11023  /* create a hash table for the constraint set */
11024  hashtablesize = SCIPcalcHashtableSize(10*nconss);
11025  hashtablesize = MAX(hashtablesize, HASHSIZE_LINEARCONS);
11026  SCIP_CALL( SCIPhashtableCreate(&hashtable, blkmem, hashtablesize,
11027  hashGetKeyLinearcons, hashKeyEqLinearcons, hashKeyValLinearcons, (void*) scip) );
11028 
11029  /* check all constraints in the given set for redundancy */
11030  for( c = 0; c < nconss; ++c )
11031  {
11032  SCIP_CONS* cons0;
11033  SCIP_CONS* cons1;
11034  SCIP_CONSDATA* consdata0;
11035 
11036  cons0 = conss[c];
11037 
11038  if( !SCIPconsIsActive(cons0) || SCIPconsIsModifiable(cons0) )
11039  continue;
11040 
11041  /* check for interuption */
11042  if( c % 1000 == 0 && SCIPisStopped(scip) )
11043  break;
11044 
11045  /* sorts the constraint */
11046  consdata0 = SCIPconsGetData(cons0);
11047  assert(consdata0 != NULL);
11048  SCIP_CALL( consdataSort(scip, consdata0) );
11049  assert(consdata0->sorted);
11050 
11051  /* get constraint from current hash table with same variables as cons0 and with coefficients either equal or negated
11052  * to the ones of cons0 */
11053  cons1 = (SCIP_CONS*)(SCIPhashtableRetrieve(hashtable, (void*)cons0));
11054 
11055  if( cons1 != NULL )
11056  {
11057  SCIP_CONS* consstay;
11058  SCIP_CONS* consdel;
11059  SCIP_CONSDATA* consdatastay;
11060  SCIP_CONSDATA* consdatadel;
11061  SCIP_CONSDATA* consdata1;
11062 
11063  SCIP_Real lhs;
11064  SCIP_Real rhs;
11065 
11066  assert(SCIPconsIsActive(cons1));
11067  assert(!SCIPconsIsModifiable(cons1));
11068 
11069  /* constraint found: create a new constraint with same coefficients and best left and right hand side;
11070  * delete old constraints afterwards
11071  */
11072  consdata1 = SCIPconsGetData(cons1);
11073 
11074  assert(consdata1 != NULL);
11075  assert(consdata0->nvars >= 1 && consdata0->nvars == consdata1->nvars);
11076 
11077  assert(consdata1->sorted);
11078  assert(consdata0->vars[0] == consdata1->vars[0]);
11079 
11080  if( SCIPisEQ(scip, consdata0->vals[0], consdata1->vals[0]) )
11081  {
11082  /* the coefficients of both constraints are equal */
11083  assert(consdata0->nvars < 2 || SCIPisEQ(scip, consdata0->vals[1], consdata1->vals[1]));
11084  SCIPdebugMessage("aggregate linear constraints <%s> and <%s> with equal coefficients into single ranged row\n",
11085  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11086  SCIPdebugPrintCons(scip, cons0, NULL);
11087  SCIPdebugPrintCons(scip, cons1, NULL);
11088 
11089  lhs = MAX(consdata1->lhs, consdata0->lhs);
11090  rhs = MIN(consdata1->rhs, consdata0->rhs);
11091  }
11092  else
11093  {
11094  /* the coefficients of both rows are negations */
11095  assert(SCIPisEQ(scip, consdata0->vals[0], -(consdata1->vals[0])));
11096  assert(consdata0->nvars < 2 || SCIPisEQ(scip, consdata0->vals[1], -(consdata1->vals[1])));
11097  SCIPdebugMessage("aggregate linear constraints <%s> and <%s> with negated coefficients into single ranged row\n",
11098  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11099  SCIPdebugPrintCons(scip, cons0, NULL);
11100  SCIPdebugPrintCons(scip, cons1, NULL);
11101 
11102  lhs = MAX(consdata1->lhs, -consdata0->rhs);
11103  rhs = MIN(consdata1->rhs, -consdata0->lhs);
11104  }
11105 
11106  if( SCIPisFeasLT(scip, rhs, lhs) )
11107  {
11108  SCIPdebugMessage("aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons1));
11109  *cutoff = TRUE;
11110  break;
11111  }
11112 
11113  /* ensure that lhs <= rhs holds without tolerances as we only allow such rows to enter the LP */
11114  if( lhs > rhs )
11115  {
11116  rhs = (lhs + rhs)/2;
11117  lhs = rhs;
11118  }
11119 
11120  /* check which constraint has to stay;
11121  * changes applied to an upgraded constraint will not be considered in the instance */
11122  if( consdata1->upgraded && !consdata0->upgraded )
11123  {
11124  consstay = cons0;
11125  consdatastay = consdata0;
11126  consdel = cons1;
11127  consdatadel = consdata1;
11128 
11129  /* exchange consdel with consstay in hashtable */
11130  SCIP_CALL( SCIPhashtableRemove(hashtable, (void*) consdel) );
11131  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) consstay) );
11132  }
11133  else
11134  {
11135  consstay = cons1;
11136  consdatastay = consdata1;
11137  consdel = cons0;
11138  consdatadel = consdata0;
11139  }
11140 
11141  /* update lhs and rhs of consstay */
11142  SCIP_CALL( chgLhs(scip, consstay, lhs) );
11143  SCIP_CALL( chgRhs(scip, consstay, rhs) );
11144 
11145  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11146  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
11147 
11148  /* delete consdel */
11149  assert(!consdatastay->upgraded || (consdatastay->upgraded && consdatadel->upgraded));
11150  SCIP_CALL( SCIPdelCons(scip, consdel) );
11151  if( !consdatadel->upgraded )
11152  (*ndelconss)++;
11153 
11154  /* update the first changed constraint to begin the next aggregation round with */
11155  if( consdatastay->changed && SCIPconsGetPos(consstay) < *firstchange )
11156  *firstchange = SCIPconsGetPos(consstay);
11157 
11158  assert(SCIPconsIsActive(consstay));
11159  }
11160  else
11161  {
11162  /* no such constraint in current hash table: insert cons0 into hash table */
11163  SCIP_CALL( SCIPhashtableInsert(hashtable, (void*) cons0) );
11164  }
11165  }
11166 #ifdef SCIP_MORE_DEBUG
11167  SCIPinfoMessage(scip, NULL, "linear pairwise comparison hashtable statistics:\n");
11169 #endif
11170 
11171  /* free hash table */
11172  SCIPhashtableFree(&hashtable);
11173 
11174  return SCIP_OKAY;
11175 }
11176 
11177 /** compares constraint with all prior constraints for possible redundancy or aggregation,
11178  * and removes or changes constraint accordingly
11179  */
11180 static
11182  SCIP* scip, /**< SCIP data structure */
11183  SCIP_CONS** conss, /**< constraint set */
11184  int firstchange, /**< first constraint that changed since last pair preprocessing round */
11185  int chkind, /**< index of constraint to check against all prior indices upto startind */
11186  SCIP_Real maxaggrnormscale, /**< maximal allowed relative gain in maximum norm for constraint aggregation */
11187  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11188  int* ndelconss, /**< pointer to count number of deleted constraints */
11189  int* nchgsides, /**< pointer to count number of changed left/right hand sides */
11190  int* nchgcoefs /**< pointer to count number of changed coefficients */
11191  )
11192 {
11193  SCIP_CONS* cons0;
11194  SCIP_CONSDATA* consdata0;
11195  int* commonidx0;
11196  int* commonidx1;
11197  int* diffidx0minus1;
11198  int* diffidx1minus0;
11199  SCIP_Longint possignature0;
11200  SCIP_Longint negsignature0;
11201  SCIP_Bool cons0changed;
11202  SCIP_Bool cons0isequality;
11203  int diffidx1minus0size;
11204  int c;
11205  SCIP_Real cons0lhs;
11206  SCIP_Real cons0rhs;
11207  SCIP_Bool cons0upgraded;
11208 
11209  assert(scip != NULL);
11210  assert(conss != NULL);
11211  assert(firstchange <= chkind);
11212  assert(cutoff != NULL);
11213  assert(ndelconss != NULL);
11214  assert(nchgsides != NULL);
11215  assert(nchgcoefs != NULL);
11216 
11217  /* get the constraint to be checked against all prior constraints */
11218  cons0 = conss[chkind];
11219  assert(cons0 != NULL);
11220  assert(SCIPconsIsActive(cons0));
11221  assert(!SCIPconsIsModifiable(cons0));
11222 
11223  consdata0 = SCIPconsGetData(cons0);
11224  assert(consdata0 != NULL);
11225  assert(consdata0->nvars >= 1);
11226  cons0isequality = SCIPisEQ(scip, consdata0->lhs, consdata0->rhs);
11227 
11228  /* sort the constraint */
11229  SCIP_CALL( consdataSort(scip, consdata0) );
11230 
11231  /* calculate bit signatures of cons0 for potentially positive and negative coefficients */
11232  consdataCalcSignatures(consdata0);
11233  possignature0 = consdata0->possignature;
11234  negsignature0 = consdata0->negsignature;
11235 
11236  /* get temporary memory for indices of common variables */
11237  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx0, consdata0->nvars) );
11238  SCIP_CALL( SCIPallocBufferArray(scip, &commonidx1, consdata0->nvars) );
11239  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx0minus1, consdata0->nvars) );
11240  SCIP_CALL( SCIPallocBufferArray(scip, &diffidx1minus0, consdata0->nvars) );
11241  diffidx1minus0size = consdata0->nvars;
11242 
11243  cons0lhs = consdata0->lhs;
11244  cons0rhs = consdata0->rhs;
11245  cons0upgraded = consdata0->upgraded;
11246 
11247  /* check constraint against all prior constraints */
11248  cons0changed = consdata0->changed;
11249  consdata0->changed = FALSE;
11250  for( c = (cons0changed ? 0 : firstchange); c < chkind && !(*cutoff) && conss[chkind] != NULL; ++c )
11251  {
11252  SCIP_CONS* cons1;
11253  SCIP_CONSDATA* consdata1;
11254  SCIP_Longint possignature1;
11255  SCIP_Longint negsignature1;
11256  SCIP_Bool cons0dominateslhs;
11257  SCIP_Bool cons1dominateslhs;
11258  SCIP_Bool cons0dominatesrhs;
11259  SCIP_Bool cons1dominatesrhs;
11260  SCIP_Bool cons1isequality;
11261  SCIP_Bool coefsequal;
11262  SCIP_Bool coefsnegated;
11263  SCIP_Bool tryaggregation;
11264  int nvarscommon;
11265  int nvars0minus1;
11266  int nvars1minus0;
11267  int commonidxweight;
11268  int diffidx0minus1weight;
11269  int diffidx1minus0weight;
11270  int v0;
11271  int v1;
11272 
11273  assert(cons0lhs == consdata0->lhs); /*lint !e777*/
11274  assert(cons0rhs == consdata0->rhs); /*lint !e777*/
11275  assert(cons0upgraded == consdata0->upgraded);
11276 
11277  cons1 = conss[c];
11278 
11279  /* cons1 has become inactive during presolving of constraint pairs */
11280  if( cons1 == NULL )
11281  continue;
11282 
11283  assert(SCIPconsIsActive(cons0) && !SCIPconsIsModifiable(cons0));
11284  assert(SCIPconsIsActive(cons1) && !SCIPconsIsModifiable(cons1));
11285 
11286  consdata1 = SCIPconsGetData(cons1);
11287  assert(consdata1 != NULL);
11288 
11289  /* SCIPdebugMessage("preprocess linear constraint pair <%s>[chgd:%d, upgd:%d] and <%s>[chgd:%d, upgd:%d]\n",
11290  SCIPconsGetName(cons0), cons0changed, cons0upgraded,
11291  SCIPconsGetName(cons1), consdata1->changed, consdata1->upgraded); */
11292 
11293  /* if both constraints didn't change since last pair processing, we can ignore the pair */
11294  if( !cons0changed && !consdata1->changed )
11295  continue;
11296 
11297  /* if both constraints are already upgraded, skip the pair;
11298  * because changes on these constraints cannot be applied to the instance anymore */
11299  if( cons0upgraded && consdata1->upgraded )
11300  continue;
11301 
11302  assert(consdata1->nvars >= 1);
11303 
11304  /* sort the constraint */
11305  SCIP_CALL( consdataSort(scip, consdata1) );
11306 
11307  /* calculate bit signatures of cons1 for potentially positive and negative coefficients */
11308  consdataCalcSignatures(consdata1);
11309  possignature1 = consdata1->possignature;
11310  negsignature1 = consdata1->negsignature;
11311 
11312  /* the signatures give a quick test to check for domination and equality of coefficients */
11313  coefsequal = (possignature0 == possignature1) && (negsignature0 == negsignature1);
11314  coefsnegated = (possignature0 == negsignature1) && (negsignature0 == possignature1);
11315  cons0dominateslhs = SCIPisGE(scip, cons0lhs, consdata1->lhs)
11316  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
11317  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
11318  cons1dominateslhs = SCIPisGE(scip, consdata1->lhs, cons0lhs)
11319  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
11320  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
11321  cons0dominatesrhs = SCIPisLE(scip, cons0rhs, consdata1->rhs)
11322  && ((possignature0 | possignature1) == possignature0) /* possignature0 >= possignature1 (as bit vector) */
11323  && ((negsignature0 | negsignature1) == negsignature1); /* negsignature0 <= negsignature1 (as bit vector) */
11324  cons1dominatesrhs = SCIPisLE(scip, consdata1->rhs, cons0rhs)
11325  && ((possignature0 | possignature1) == possignature1) /* possignature0 <= possignature1 (as bit vector) */
11326  && ((negsignature0 | negsignature1) == negsignature0); /* negsignature0 >= negsignature1 (as bit vector) */
11327  cons1isequality = SCIPisEQ(scip, consdata1->lhs, consdata1->rhs);
11328  tryaggregation = (cons0isequality || cons1isequality) && (maxaggrnormscale > 0.0);
11329  if( !cons0dominateslhs && !cons1dominateslhs && !cons0dominatesrhs && !cons1dominatesrhs
11330  && !coefsequal && !coefsnegated && !tryaggregation )
11331  continue;
11332 
11333  /* make sure, we have enough memory for the index set of V_1 \ V_0 */
11334  if( tryaggregation && consdata1->nvars > diffidx1minus0size )
11335  {
11336  SCIP_CALL( SCIPreallocBufferArray(scip, &diffidx1minus0, consdata1->nvars) );
11337  diffidx1minus0size = consdata1->nvars;
11338  }
11339 
11340  /* check consdata0 against consdata1:
11341  * - if lhs0 >= lhs1 and for each variable v and each solution value x_v val0[v]*x_v <= val1[v]*x_v,
11342  * consdata0 dominates consdata1 w.r.t. left hand side
11343  * - if rhs0 <= rhs1 and for each variable v and each solution value x_v val0[v]*x_v >= val1[v]*x_v,
11344  * consdata0 dominates consdata1 w.r.t. right hand side
11345  * - if val0[v] == -val1[v] for all variables v, the two inequalities can be replaced by a single
11346  * ranged row (or equality)
11347  * - if at least one constraint is an equality, count the weighted number of common variables W_c
11348  * and the weighted number of variable in the difference sets W_0 = w(V_0 \ V_1), W_1 = w(V_1 \ V_0),
11349  * where the weight of each variable depends on its type, such that aggregations in order to remove the
11350  * number of continuous and integer variables are preferred:
11351  * - if W_c > W_1, try to aggregate consdata0 := a * consdata0 + b * consdata1 in order to decrease the
11352  * variable weight in consdata0, where a = +/- val1[v] and b = -/+ val0[v] for common v which leads to
11353  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
11354  * to be positive to not switch the sense of the (in)equality cons0
11355  * - if W_c > W_0, try to aggregate consdata1 := a * consdata1 + b * consdata0 in order to decrease the
11356  * variable weight in consdata1, where a = +/- val0[v] and b = -/+ val1[v] for common v which leads to
11357  * the smallest weight; for numerical stability, we will only accept integral a and b; the sign of a has
11358  * to be positive to not switch the sense of the (in)equality cons1
11359  */
11360 
11361  /* check consdata0 against consdata1 for redundancy, or ranged row accumulation */
11362  nvarscommon = 0;
11363  commonidxweight = 0;
11364  nvars0minus1 = 0;
11365  diffidx0minus1weight = 0;
11366  nvars1minus0 = 0;
11367  diffidx1minus0weight = 0;
11368  v0 = 0;
11369  v1 = 0;
11370  while( (v0 < consdata0->nvars || v1 < consdata1->nvars)
11371  && (cons0dominateslhs || cons1dominateslhs || cons0dominatesrhs || cons1dominatesrhs
11372  || coefsequal || coefsnegated || tryaggregation) )
11373  {
11374  SCIP_VAR* var;
11375  SCIP_Real val0;
11376  SCIP_Real val1;
11377  int varcmp;
11378 
11379  /* test, if variable appears in only one or in both constraints */
11380  if( v0 < consdata0->nvars && v1 < consdata1->nvars )
11381  varcmp = SCIPvarCompare(consdata0->vars[v0], consdata1->vars[v1]);
11382  else if( v0 < consdata0->nvars )
11383  varcmp = -1;
11384  else
11385  varcmp = +1;
11386 
11387  switch( varcmp )
11388  {
11389  case -1:
11390  /* variable doesn't appear in consdata1 */
11391  var = consdata0->vars[v0];
11392  val0 = consdata0->vals[v0];
11393  val1 = 0.0;
11394  if( tryaggregation )
11395  {
11396  diffidx0minus1[nvars0minus1] = v0;
11397  nvars0minus1++;
11398  diffidx0minus1weight += getVarWeight(var);
11399  }
11400  v0++;
11401  coefsequal = FALSE;
11402  coefsnegated = FALSE;
11403  break;
11404 
11405  case +1:
11406  /* variable doesn't appear in consdata0 */
11407  var = consdata1->vars[v1];
11408  val0 = 0.0;
11409  val1 = consdata1->vals[v1];
11410  if( tryaggregation )
11411  {
11412  diffidx1minus0[nvars1minus0] = v1;
11413  nvars1minus0++;
11414  diffidx1minus0weight += getVarWeight(var);
11415  }
11416  v1++;
11417  coefsequal = FALSE;
11418  coefsnegated = FALSE;
11419  break;
11420 
11421  case 0:
11422  /* variable appears in both constraints */
11423  assert(consdata0->vars[v0] == consdata1->vars[v1]);
11424  var = consdata0->vars[v0];
11425  val0 = consdata0->vals[v0];
11426  val1 = consdata1->vals[v1];
11427  if( tryaggregation )
11428  {
11429  commonidx0[nvarscommon] = v0;
11430  commonidx1[nvarscommon] = v1;
11431  nvarscommon++;
11432  commonidxweight += getVarWeight(var);
11433  }
11434  v0++;
11435  v1++;
11436  coefsequal = coefsequal && (SCIPisEQ(scip, val0, val1));
11437  coefsnegated = coefsnegated && (SCIPisEQ(scip, val0, -val1));
11438  break;
11439 
11440  default:
11441  SCIPerrorMessage("invalid comparison result\n");
11442  var = NULL;
11443  val0 = 0.0;
11444  val1 = 0.0;
11445  SCIPABORT();
11446  }
11447  assert(var != NULL);
11448 
11449  /* update domination criteria w.r.t. the coefficient and the variable's bounds */
11450  if( SCIPisGT(scip, val0, val1) )
11451  {
11452  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
11453  {
11454  cons0dominatesrhs = FALSE;
11455  cons1dominateslhs = FALSE;
11456  }
11457  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
11458  {
11459  cons0dominateslhs = FALSE;
11460  cons1dominatesrhs = FALSE;
11461  }
11462  }
11463  else if( SCIPisLT(scip, val0, val1) )
11464  {
11465  if( SCIPisNegative(scip, SCIPvarGetLbGlobal(var)) )
11466  {
11467  cons0dominateslhs = FALSE;
11468  cons1dominatesrhs = FALSE;
11469  }
11470  if( SCIPisPositive(scip, SCIPvarGetUbGlobal(var)) )
11471  {
11472  cons0dominatesrhs = FALSE;
11473  cons1dominateslhs = FALSE;
11474  }
11475  }
11476  }
11477 
11478  /* check for disaggregated ranged rows */
11479  if( coefsequal || coefsnegated )
11480  {
11481  SCIP_CONS* consstay;
11482  SCIP_CONS* consdel;
11483 #ifndef NDEBUG
11484  SCIP_CONSDATA* consdatastay;
11485 #endif
11486  SCIP_CONSDATA* consdatadel;
11487  SCIP_Real lhs;
11488  SCIP_Real rhs;
11489  int consinddel;
11490 
11491  /* the coefficients in both rows are either equal or negated: create a new constraint with same coefficients and
11492  * best left and right hand sides; delete the old constraints afterwards
11493  */
11494  SCIPdebugMessage("aggregate linear constraints <%s> and <%s> with %s coefficients into single ranged row\n",
11495  SCIPconsGetName(cons0), SCIPconsGetName(cons1), coefsequal ? "equal" : "negated");
11496  SCIPdebugPrintCons(scip, cons0, NULL);
11497  SCIPdebugPrintCons(scip, cons1, NULL);
11498 
11499  if( coefsequal )
11500  {
11501  /* the coefficients of both rows are equal */
11502  lhs = MAX(consdata0->lhs, consdata1->lhs);
11503  rhs = MIN(consdata0->rhs, consdata1->rhs);
11504  }
11505  else
11506  {
11507  /* the coefficients of both rows are negations */
11508  lhs = MAX(consdata0->lhs, -consdata1->rhs);
11509  rhs = MIN(consdata0->rhs, -consdata1->lhs);
11510  }
11511  if( SCIPisFeasLT(scip, rhs, lhs) )
11512  {
11513  SCIPdebugMessage("aggregated linear constraint <%s> is infeasible\n", SCIPconsGetName(cons0));
11514  *cutoff = TRUE;
11515  break;
11516  }
11517 
11518  /* check which constraint has to stay;
11519  * changes applied to an upgraded constraint will not be considered in the instance */
11520  if( consdata0->upgraded )
11521  {
11522  assert(!consdata1->upgraded);
11523  consstay = cons1;
11524 #ifndef NDEBUG
11525  consdatastay = consdata1;
11526 #endif
11527 
11528  consdel = cons0;
11529  consdatadel = consdata0;
11530  consinddel = chkind;
11531  }
11532  else
11533  {
11534  consstay = cons0;
11535 #ifndef NDEBUG
11536  consdatastay = consdata0;
11537 #endif
11538 
11539  consdel = cons1;
11540  consdatadel = consdata1;
11541  consinddel = c;
11542  }
11543 
11544  /* update the sides of consstay */
11545  SCIP_CALL( chgLhs(scip, consstay, lhs) );
11546  SCIP_CALL( chgRhs(scip, consstay, rhs) );
11547  if( !consdata0->upgraded )
11548  {
11549  assert(consstay == cons0);
11550  cons0lhs = consdata0->lhs;
11551  cons0rhs = consdata0->rhs;
11552  }
11553 
11554  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11555  SCIP_CALL( SCIPupdateConsFlags(scip, consstay, consdel) );
11556 
11557  assert( !consdatastay->upgraded );
11558  /* delete consdel */
11559  SCIP_CALL( SCIPdelCons(scip, consdel) );
11560  conss[consinddel] = NULL;
11561  if( !consdatadel->upgraded )
11562  (*ndelconss)++;
11563  continue;
11564  }
11565 
11566  /* check for domination: remove dominated sides, but don't touch equalities as long as they are not totally
11567  * redundant
11568  */
11569  if( cons1dominateslhs && (!cons0isequality || cons1dominatesrhs || SCIPisInfinity(scip, consdata0->rhs) ) )
11570  {
11571  /* left hand side is dominated by consdata1: delete left hand side of consdata0 */
11572  SCIPdebugMessage("left hand side of linear constraint <%s> is dominated by <%s>:\n",
11573  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11574  SCIPdebugPrintCons(scip, cons0, NULL);
11575  SCIPdebugPrintCons(scip, cons1, NULL);
11576 
11577  /* check for infeasibility */
11578  if( SCIPisFeasGT(scip, consdata1->lhs, consdata0->rhs) )
11579  {
11580  SCIPdebugMessage("linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11581  *cutoff = TRUE;
11582  break;
11583  }
11584 
11585  /* remove redundant left hand side */
11586  if( !SCIPisInfinity(scip, -consdata0->lhs) )
11587  {
11588  SCIP_CALL( chgLhs(scip, cons0, -SCIPinfinity(scip)) );
11589  cons0lhs = consdata0->lhs;
11590  cons0isequality = FALSE;
11591  if( !consdata0->upgraded )
11592  {
11593  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11594  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
11595 
11596  (*nchgsides)++;
11597  }
11598  }
11599  }
11600  else if( cons0dominateslhs && (!cons1isequality || cons0dominatesrhs || SCIPisInfinity(scip, consdata1->rhs)) )
11601  {
11602  /* left hand side is dominated by consdata0: delete left hand side of consdata1 */
11603  SCIPdebugMessage("left hand side of linear constraint <%s> is dominated by <%s>:\n",
11604  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
11605  SCIPdebugPrintCons(scip, cons1, NULL);
11606  SCIPdebugPrintCons(scip, cons0, NULL);
11607 
11608  /* check for infeasibility */
11609  if( SCIPisFeasGT(scip, consdata0->lhs, consdata1->rhs) )
11610  {
11611  SCIPdebugMessage("linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11612  *cutoff = TRUE;
11613  break;
11614  }
11615 
11616  /* remove redundant left hand side */
11617  if( !SCIPisInfinity(scip, -consdata1->lhs) )
11618  {
11619  SCIP_CALL( chgLhs(scip, cons1, -SCIPinfinity(scip)) );
11620  cons1isequality = FALSE;
11621  if( !consdata1->upgraded )
11622  {
11623  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11624  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
11625 
11626  (*nchgsides)++;
11627  }
11628  }
11629  }
11630  if( cons1dominatesrhs && (!cons0isequality || cons1dominateslhs || SCIPisInfinity(scip, -consdata0->lhs)) )
11631  {
11632  /* right hand side is dominated by consdata1: delete right hand side of consdata0 */
11633  SCIPdebugMessage("right hand side of linear constraint <%s> is dominated by <%s>:\n",
11634  SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11635  SCIPdebugPrintCons(scip, cons0, NULL);
11636  SCIPdebugPrintCons(scip, cons1, NULL);
11637 
11638  /* check for infeasibility */
11639  if( SCIPisFeasLT(scip, consdata1->rhs, consdata0->lhs) )
11640  {
11641  SCIPdebugMessage("linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11642  *cutoff = TRUE;
11643  break;
11644  }
11645 
11646  /* remove redundant right hand side */
11647  if( !SCIPisInfinity(scip, consdata0->rhs) )
11648  {
11649  SCIP_CALL( chgRhs(scip, cons0, SCIPinfinity(scip)) );
11650  cons0rhs = consdata0->rhs;
11651  cons0isequality = FALSE;
11652  if( !consdata0->upgraded )
11653  {
11654  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11655  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
11656 
11657  (*nchgsides)++;
11658  }
11659  }
11660  }
11661  else if( cons0dominatesrhs && (!cons1isequality || cons0dominateslhs || SCIPisInfinity(scip, -consdata1->lhs)) )
11662  {
11663  /* right hand side is dominated by consdata0: delete right hand side of consdata1 */
11664  SCIPdebugMessage("right hand side of linear constraint <%s> is dominated by <%s>:\n",
11665  SCIPconsGetName(cons1), SCIPconsGetName(cons0));
11666  SCIPdebugPrintCons(scip, cons1, NULL);
11667  SCIPdebugPrintCons(scip, cons0, NULL);
11668 
11669  /* check for infeasibility */
11670  if( SCIPisFeasLT(scip, consdata0->rhs, consdata1->lhs) )
11671  {
11672  SCIPdebugMessage("linear constraints <%s> and <%s> are infeasible\n", SCIPconsGetName(cons0), SCIPconsGetName(cons1));
11673  *cutoff = TRUE;
11674  break;
11675  }
11676 
11677  /* remove redundant right hand side */
11678  if( !SCIPisInfinity(scip, consdata1->rhs) )
11679  {
11680  SCIP_CALL( chgRhs(scip, cons1, SCIPinfinity(scip)) );
11681  cons1isequality = FALSE;
11682  if( !consdata1->upgraded )
11683  {
11684  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11685  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
11686 
11687  (*nchgsides)++;
11688  }
11689  }
11690  }
11691 
11692  /* check for now redundant constraints */
11693  if( SCIPisInfinity(scip, -consdata0->lhs) && SCIPisInfinity(scip, consdata0->rhs) )
11694  {
11695  /* consdata0 became redundant */
11696  SCIPdebugMessage("linear constraint <%s> is redundant\n", SCIPconsGetName(cons0));
11697  SCIP_CALL( SCIPdelCons(scip, cons0) );
11698  conss[chkind] = NULL;
11699  if( !consdata0->upgraded )
11700  {
11701  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11702  SCIP_CALL( SCIPupdateConsFlags(scip, cons1, cons0) );
11703 
11704  (*ndelconss)++;
11705  }
11706  continue;
11707  }
11708  if( SCIPisInfinity(scip, -consdata1->lhs) && SCIPisInfinity(scip, consdata1->rhs) )
11709  {
11710  /* consdata1 became redundant */
11711  SCIPdebugMessage("linear constraint <%s> is redundant\n", SCIPconsGetName(cons1));
11712  SCIP_CALL( SCIPdelCons(scip, cons1) );
11713  conss[c] = NULL;
11714  if( !consdata1->upgraded )
11715  {
11716  /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
11717  SCIP_CALL( SCIPupdateConsFlags(scip, cons0, cons1) );
11718 
11719  (*ndelconss)++;
11720  }
11721  continue;
11722  }
11723 
11724  /* check, if we want to aggregate an (in)equality with an equality:
11725  * consdata0 := a * consdata0 + b * consdata1 or consdata1 := a * consdata1 + b * consdata0
11726  */
11727  if( tryaggregation )
11728  {
11729  SCIP_Bool aggregated;
11730 
11731  assert(consdata0->nvars == nvarscommon + nvars0minus1);
11732  assert(consdata1->nvars == nvarscommon + nvars1minus0);
11733 
11734  aggregated = FALSE;
11735  if( cons1isequality && !consdata0->upgraded && commonidxweight > diffidx1minus0weight )
11736  {
11737  /* W_c > W_1: try to aggregate consdata0 := a * consdata0 + b * consdata1 */
11738  SCIP_CALL( aggregateConstraints(scip, cons0, cons1, commonidx0, commonidx1, diffidx0minus1, diffidx1minus0,
11739  nvarscommon, commonidxweight, diffidx0minus1weight, diffidx1minus0weight, maxaggrnormscale,
11740  nchgcoefs, &aggregated) );
11741 
11742  /* update array of active constraints */
11743  if( aggregated )
11744  {
11745  assert(!SCIPconsIsActive(cons0));
11746  assert(SCIPconsIsActive(cons1));
11747  conss[chkind] = NULL;
11748  }
11749  }
11750  if( !aggregated && cons0isequality && !consdata1->upgraded && commonidxweight > diffidx0minus1weight )
11751  {
11752  /* W_c > W_0: try to aggregate consdata1 := a * consdata1 + b * consdata0 */
11753  SCIP_CALL( aggregateConstraints(scip, cons1, cons0, commonidx1, commonidx0, diffidx1minus0, diffidx0minus1,
11754  nvarscommon, commonidxweight, diffidx1minus0weight, diffidx0minus1weight, maxaggrnormscale,
11755  nchgcoefs, &aggregated) );
11756 
11757  /* update array of active constraints */
11758  if( aggregated )
11759  {
11760  assert(!SCIPconsIsActive(cons1));
11761  assert(SCIPconsIsActive(cons0));
11762  conss[c] = NULL;
11763  }
11764  }
11765  }
11766  }
11767 
11768  /* free temporary memory */
11769  SCIPfreeBufferArray(scip, &diffidx1minus0);
11770  SCIPfreeBufferArray(scip, &diffidx0minus1);
11771  SCIPfreeBufferArray(scip, &commonidx1);
11772  SCIPfreeBufferArray(scip, &commonidx0);
11773 
11774  return SCIP_OKAY;
11775 }
11776 
11777 /** applies full dual presolving on variables that only appear in linear constraints */
11778 static
11780  SCIP* scip, /**< SCIP data structure */
11781  SCIP_CONS** conss, /**< constraint set */
11782  int nconss, /**< number of constraints */
11783  SCIP_Bool* cutoff, /**< pointer to store TRUE, if a cutoff was found */
11784  int* nchgbds /**< pointer to count the number of bound changes */
11785  )
11786 {
11787  SCIP_Real* redlb;
11788  SCIP_Real* redub;
11789  int* nlocksdown;
11790  int* nlocksup;
11791  SCIP_Bool* isimplint;
11792  SCIP_VAR** origvars;
11793  SCIP_VAR** vars;
11794  SCIP_VAR** conscontvars;
11795  int nvars;
11796  int nbinvars;
11797  int nintvars;
11798  int ncontvars;
11799  int v;
11800  int c;
11801 
11802  /* we calculate redundancy bounds with the following meaning:
11803  * redlb[v] == k : if x_v >= k, we can always round x_v down to x_v == k without violating any constraint
11804  * redub[v] == k : if x_v <= k, we can always round x_v up to x_v == k without violating any constraint
11805  * then:
11806  * c_v >= 0 : x_v <= redlb[v] is feasible due to optimality
11807  * c_v <= 0 : x_v >= redub[v] is feasible due to optimality
11808  */
11809 
11810  /* Additionally, we detect continuous variables that are implicitly integral.
11811  * A continuous variable j is implicit integral if it only has only +/-1 coefficients,
11812  * and all constraints (including the bounds as trivial constraints) in which:
11813  * c_j > 0: the variable is down-locked,
11814  * c_j < 0: the variable is up-locked,
11815  * c_j = 0: the variable appears
11816  * have, apart from j, only integer variables with integral coefficients and integral sides.
11817  * This is because then, the value of the variable is either determined by one of its bounds or
11818  * by one of these constraints, and in all cases, the value of the variable is integral.
11819  */
11820 
11821  assert(scip != NULL);
11822  assert(nconss == 0 || conss != NULL);
11823  assert(nchgbds != NULL);
11824  assert(!SCIPinProbing(scip));
11825 
11826  /* get active variables */
11827  nvars = SCIPgetNVars(scip);
11828  origvars = SCIPgetVars(scip);
11829 
11830  /* if the problem is a pure binary program, nothing can be achieved by full dual presolve */
11831  nbinvars = SCIPgetNBinVars(scip);
11832  if( nbinvars == nvars )
11833  return SCIP_OKAY;
11834 
11835  /* get number of continuous variables */
11836  ncontvars = SCIPgetNContVars(scip);
11837  nintvars = nvars - ncontvars;
11838 
11839  /* copy the variable array since this array might change during the curse of this algorithm */
11840  nvars = nvars - nbinvars;
11841  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, &(origvars[nbinvars]), nvars) );
11842 
11843  /* allocate temporary memory */
11844  SCIP_CALL( SCIPallocBufferArray(scip, &redlb, nvars) );
11845  SCIP_CALL( SCIPallocBufferArray(scip, &redub, nvars) );
11846  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksdown, nvars) );
11847  SCIP_CALL( SCIPallocBufferArray(scip, &nlocksup, nvars) );
11848  SCIP_CALL( SCIPallocBufferArray(scip, &isimplint, ncontvars) );
11849  SCIP_CALL( SCIPallocBufferArray(scip, &conscontvars, ncontvars) );
11850 
11851  /* initialize redundancy bounds */
11852  for( v = 0; v < nvars; ++v )
11853  {
11854  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
11855  redlb[v] = SCIPvarGetLbGlobal(vars[v]);
11856  redub[v] = SCIPvarGetUbGlobal(vars[v]);
11857  }
11858  BMSclearMemoryArray(nlocksdown, nvars);
11859  BMSclearMemoryArray(nlocksup, nvars);
11860 
11861  /* Initialize isimplint array: variable may be implied integer if both bounds are integral.
11862  * We better not use SCIPisFeasIntegral() in these checks.
11863  */
11864  for( v = 0; v < ncontvars; v++ )
11865  {
11866  SCIP_VAR* var;
11867  SCIP_Real lb;
11868  SCIP_Real ub;
11869 
11870  var = vars[v + nintvars - nbinvars];
11871  lb = SCIPvarGetLbGlobal(var);
11872  ub = SCIPvarGetUbGlobal(var);
11873  isimplint[v] = (SCIPisInfinity(scip, -lb) || SCIPisIntegral(scip, lb))
11874  && (SCIPisInfinity(scip, ub) || SCIPisIntegral(scip, ub));
11875  }
11876 
11877  /* scan all constraints */
11878  for( c = 0; c < nconss; ++c )
11879  {
11880  /* we only need to consider constraints that have been locked (i.e., checked constraints or constraints that are
11881  * part of checked disjunctions)
11882  */
11883  if( SCIPconsIsLocked(conss[c]) )
11884  {
11885  SCIP_CONSDATA* consdata;
11886  SCIP_Bool lhsexists;
11887  SCIP_Bool rhsexists;
11888  SCIP_Bool hasimpliedpotential;
11889  SCIP_Bool integralcoefs;
11890  int nlockspos;
11891  int contvarpos;
11892  int nconscontvars;
11893  int i;
11894 
11895  consdata = SCIPconsGetData(conss[c]);
11896  assert(consdata != NULL);
11897 
11898  /* get number of times the constraint was locked */
11899  nlockspos = SCIPconsGetNLocksPos(conss[c]);
11900 
11901  /* we do not want to include constraints with locked negation (this would be too weird) */
11902  if( SCIPconsGetNLocksNeg(conss[c]) > 0 )
11903  {
11904  /* mark all continuous variables as not being implicit integral */
11905  for( i = 0; i < consdata->nvars; ++i )
11906  {
11907  SCIP_VAR* var;
11908 
11909  var = consdata->vars[i];
11911  {
11912  int contv;
11913  contv = SCIPvarGetProbindex(var) - nintvars;
11914  assert(0 <= contv && contv < ncontvars); /* variable should be active due to applyFixings() */
11915  isimplint[contv] = FALSE;
11916  }
11917  }
11918  continue;
11919  }
11920 
11921  /* check for existing sides */
11922  lhsexists = !SCIPisInfinity(scip, -consdata->lhs);
11923  rhsexists = !SCIPisInfinity(scip, consdata->rhs);
11924 
11925  /* count locks and update redundancy bounds */
11926  contvarpos = -1;
11927  nconscontvars = 0;
11928  hasimpliedpotential = FALSE;
11929  integralcoefs = !SCIPconsIsModifiable(conss[c]);
11930 
11931  for( i = 0; i < consdata->nvars; ++i )
11932  {
11933  SCIP_VAR* var;
11934  SCIP_Real val;
11935  SCIP_Real minresactivity;
11936  SCIP_Real maxresactivity;
11937  SCIP_Real newredlb;
11938  SCIP_Real newredub;
11939  SCIP_Bool minisrelax;
11940  SCIP_Bool maxisrelax;
11941  SCIP_Bool isminsettoinfinity;
11942  SCIP_Bool ismaxsettoinfinity;
11943  int arrayindex;
11944 
11945  var = consdata->vars[i];
11946  val = consdata->vals[i];
11947 
11948  /* check if still all integer variables have integral coefficients */
11949  if( SCIPvarIsIntegral(var) )
11950  integralcoefs = integralcoefs && SCIPisIntegral(scip, val);
11951 
11952  /* we do not need to process binary variables */
11953  if( SCIPvarIsBinary(var) )
11954  continue;
11955 
11956  if( SCIPconsIsModifiable(conss[c]) )
11957  {
11958  minresactivity = -SCIPinfinity(scip);
11959  maxresactivity = SCIPinfinity(scip);
11960  isminsettoinfinity = TRUE;
11961  ismaxsettoinfinity = TRUE;
11962  }
11963  else
11964  {
11965  /* calculate residual activity bounds if variable would be fixed to zero */
11966  consdataGetGlbActivityResiduals(scip, consdata, var, val, FALSE, &minresactivity, &maxresactivity,
11967  &minisrelax, &maxisrelax, &isminsettoinfinity, &ismaxsettoinfinity);
11968 
11969  /* We called consdataGetGlbActivityResiduals() saying that we do not need a good relaxation,
11970  * so whenever we have a relaxed activity, it should be relaxed to +/- infinity.
11971  * This is needed, because we do not want to rely on relaxed finite resactivities.
11972  */
11973  assert((!minisrelax || isminsettoinfinity) && (!maxisrelax || ismaxsettoinfinity));
11974 
11975  /* check minresactivity for reliability */
11976  if( !isminsettoinfinity && SCIPisUpdateUnreliable(scip, minresactivity, consdata->lastglbminactivity) )
11977  consdataGetReliableResidualActivity(scip, consdata, var, &minresactivity, TRUE, TRUE);
11978 
11979  /* check maxresactivity for reliability */
11980  if( !ismaxsettoinfinity && SCIPisUpdateUnreliable(scip, maxresactivity, consdata->lastglbmaxactivity) )
11981  consdataGetReliableResidualActivity(scip, consdata, var, &maxresactivity, FALSE, TRUE);
11982  }
11983 
11984  arrayindex = SCIPvarGetProbindex(var) - nbinvars;
11985 
11986  assert(0 <= arrayindex && arrayindex < nvars); /* variable should be active due to applyFixings() */
11987 
11988  newredlb = redlb[arrayindex];
11989  newredub = redub[arrayindex];
11990  if( val > 0.0 )
11991  {
11992  if( lhsexists )
11993  {
11994  /* lhs <= d*x + a*y, d > 0 -> redundant in y if x >= (lhs - min{a*y})/d */
11995  nlocksdown[arrayindex] += nlockspos;
11996  newredlb = (isminsettoinfinity ? SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
11997  }
11998  if( rhsexists )
11999  {
12000  /* d*x + a*y <= rhs, d > 0 -> redundant in y if x <= (rhs - max{a*y})/d */
12001  nlocksup[arrayindex] += nlockspos;
12002  newredub = (ismaxsettoinfinity ? -SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
12003  }
12004  }
12005  else
12006  {
12007  if( lhsexists )
12008  {
12009  /* lhs <= d*x + a*y, d < 0 -> redundant in y if x <= (lhs - min{a*y})/d */
12010  nlocksup[arrayindex] += nlockspos;
12011  newredub = (isminsettoinfinity ? -SCIPinfinity(scip) : (consdata->lhs - minresactivity)/val);
12012  }
12013  if( rhsexists )
12014  {
12015  /* d*x + a*y <= rhs, d < 0 -> redundant in y if x >= (rhs - max{a*y})/d */
12016  nlocksdown[arrayindex] += nlockspos;
12017  newredlb = (ismaxsettoinfinity ? SCIPinfinity(scip) : (consdata->rhs - maxresactivity)/val);
12018  }
12019  }
12020 
12021  /* if the variable is integer, we have to round the value to the next integral value */
12022  if( SCIPvarIsIntegral(var) )
12023  {
12024  if( !SCIPisInfinity(scip, newredlb) )
12025  newredlb = SCIPceil(scip, newredlb);
12026  if( !SCIPisInfinity(scip, -newredub) )
12027  newredub = SCIPfloor(scip, newredub);
12028  }
12029 
12030  /* update redundancy bounds */
12031  redlb[arrayindex] = MAX(redlb[arrayindex], newredlb);
12032  redub[arrayindex] = MIN(redub[arrayindex], newredub);
12033 
12034  /* collect the continuous variables of the constraint */
12036  {
12037  int contv;
12038 
12039  assert(nconscontvars < ncontvars);
12040  contvarpos = i;
12041  conscontvars[nconscontvars] = var;
12042  nconscontvars++;
12043 
12044  contv = SCIPvarGetProbindex(var) - nintvars;
12045  assert(0 <= contv && contv < ncontvars);
12046  hasimpliedpotential = hasimpliedpotential || isimplint[contv];
12047  }
12048  }
12049 
12050  /* update implied integer status of continuous variables */
12051  if( hasimpliedpotential )
12052  {
12053  if( nconscontvars > 1 || !integralcoefs )
12054  {
12055  /* there is more than one continuous variable or the integer variables have fractional coefficients:
12056  * none of the continuous variables is implied integer
12057  */
12058  for( i = 0; i < nconscontvars; i++ )
12059  {
12060  int contv;
12061  contv = SCIPvarGetProbindex(conscontvars[i]) - nintvars;
12062  assert(0 <= contv && contv < ncontvars);
12063  isimplint[contv] = FALSE;
12064  }
12065  }
12066  else
12067  {
12068  SCIP_VAR* var;
12069  SCIP_Real val;
12070  SCIP_Real absval;
12071  int contv;
12072 
12073  /* there is exactly one continuous variable and the integer variables have integral coefficients:
12074  * this is the interesting case, and we have to check whether the coefficient is +/-1 and the corresponding
12075  * side(s) of the constraint is integral
12076  */
12077  assert(nconscontvars == 1);
12078  assert(0 <= contvarpos && contvarpos < consdata->nvars);
12079  var = consdata->vars[contvarpos];
12080  val = consdata->vals[contvarpos];
12081  contv = SCIPvarGetProbindex(var) - nintvars;
12082  assert(0 <= contv && contv < ncontvars);
12083  assert(isimplint[contv]);
12084 
12085  absval = REALABS(val);
12086  if( !SCIPisEQ(scip, absval, 1.0) )
12087  isimplint[contv] = FALSE;
12088  else
12089  {
12090  SCIP_Real obj;
12091 
12092  obj = SCIPvarGetObj(var);
12093  if( obj * val >= 0.0 && lhsexists )
12094  {
12095  /* the variable may be blocked by the constraint's left hand side */
12096  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->lhs);
12097  }
12098  if( obj * val <= 0.0 && rhsexists )
12099  {
12100  /* the variable may be blocked by the constraint's left hand side */
12101  isimplint[contv] = isimplint[contv] && SCIPisIntegral(scip, consdata->rhs);
12102  }
12103  }
12104  }
12105  }
12106  }
12107  }
12108 
12109  /* check if any bounds can be tightened due to optimality */
12110  for( v = 0; v < nvars; ++v )
12111  {
12112  SCIP_VAR* var;
12113  SCIP_Real obj;
12114  SCIP_Bool infeasible;
12115  SCIP_Bool tightened;
12116 
12117  assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_BINARY);
12118  assert(SCIPvarGetNLocksDown(vars[v]) >= nlocksdown[v]);
12119  assert(SCIPvarGetNLocksUp(vars[v]) >= nlocksup[v]);
12120 
12121  var = vars[v];
12122  obj = SCIPvarGetObj(var);
12123  if( obj >= 0.0 )
12124  {
12125  /* making the variable as small as possible does not increase the objective:
12126  * check if all down locks of the variables are due to linear constraints;
12127  * if largest bound to make constraints redundant is -infinity, we better do nothing for numerical reasons
12128  */
12129  if( SCIPvarGetNLocksDown(var) == nlocksdown[v]
12130  && !SCIPisInfinity(scip, -redlb[v])
12131  && redlb[v] < SCIPvarGetUbGlobal(var) )
12132  {
12133  SCIP_Real ub;
12134 
12135  /* if x_v >= redlb[v], we can always round x_v down to x_v == redlb[v] without violating any constraint
12136  * -> tighten upper bound to x_v <= redlb[v]
12137  */
12138  SCIPdebugMessage("variable <%s> only locked down in linear constraints: dual presolve <%s>[%.15g,%.15g] <= %.15g\n",
12140  redlb[v]);
12141  SCIP_CALL( SCIPtightenVarUb(scip, var, redlb[v], FALSE, &infeasible, &tightened) );
12142  assert(!infeasible);
12143 
12144  ub = SCIPvarGetUbGlobal(var);
12145  redub[v] = MIN(redub[v], ub);
12146  if( tightened )
12147  (*nchgbds)++;
12148  }
12149  }
12150  if( obj <= 0.0 )
12151  {
12152  /* making the variable as large as possible does not increase the objective:
12153  * check if all up locks of the variables are due to linear constraints;
12154  * if smallest bound to make constraints redundant is +infinity, we better do nothing for numerical reasons
12155  */
12156  if( SCIPvarGetNLocksUp(var) == nlocksup[v]
12157  && !SCIPisInfinity(scip, redub[v])
12158  && redub[v] > SCIPvarGetLbGlobal(var) )
12159  {
12160  SCIP_Real lb;
12161 
12162  /* if x_v <= redub[v], we can always round x_v up to x_v == redub[v] without violating any constraint
12163  * -> tighten lower bound to x_v >= redub[v]
12164  */
12165  SCIPdebugMessage("variable <%s> only locked up in linear constraints: dual presolve <%s>[%.15g,%.15g] >= %.15g\n",
12167  redub[v]);
12168  SCIP_CALL( SCIPtightenVarLb(scip, var, redub[v], FALSE, &infeasible, &tightened) );
12169  assert(!infeasible);
12170 
12171  lb = SCIPvarGetLbGlobal(var);
12172  redlb[v] = MAX(redlb[v], lb);
12173  if( tightened )
12174  (*nchgbds)++;
12175  }
12176  }
12177  }
12178 
12179  /* upgrade continuous variables to implied integers */
12180  for( v = nintvars - nbinvars; v < nvars; ++v )
12181  {
12182  SCIP_VAR* var;
12183  SCIP_Bool infeasible;
12184 
12185  var = vars[v];
12186  assert(var != NULL);
12187 
12188  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS);
12189  assert(SCIPvarGetNLocksDown(var) >= nlocksdown[v]);
12190  assert(SCIPvarGetNLocksUp(var) >= nlocksup[v]);
12191  assert(0 <= v - nintvars + nbinvars && v - nintvars + nbinvars < ncontvars);
12192 
12193  /* we can only conclude implied integrality if the variable appears in no other constraint */
12194  if( isimplint[v - nintvars + nbinvars]
12195  && SCIPvarGetNLocksDown(var) == nlocksdown[v]
12196  && SCIPvarGetNLocksUp(var) == nlocksup[v] )
12197  {
12198 
12199  /* since we locally copied the variable array we can change the variable type immediately */
12200  SCIP_CALL( SCIPchgVarType(scip, var, SCIP_VARTYPE_IMPLINT, &infeasible) );
12201 
12202  if( infeasible )
12203  {
12204  SCIPdebugMessage("infeasible upgrade of variable <%s> to integral type, domain is empty\n", SCIPvarGetName(var));
12205  *cutoff = TRUE;
12206 
12207  break;
12208  }
12209 
12210  SCIPdebugMessage("dual presolve: converting continuous variable <%s>[%g,%g] to implicit integer\n",
12212  }
12213  }
12214 
12215  /* free temporary memory */
12216  SCIPfreeBufferArray(scip, &conscontvars);
12217  SCIPfreeBufferArray(scip, &isimplint);
12218  SCIPfreeBufferArray(scip, &nlocksup);
12219  SCIPfreeBufferArray(scip, &nlocksdown);
12220  SCIPfreeBufferArray(scip, &redub);
12221  SCIPfreeBufferArray(scip, &redlb);
12222 
12223  SCIPfreeBufferArray(scip, &vars);
12224 
12225  return SCIP_OKAY;
12226 }
12227 
12228 
12229 /*
12230  * Callback methods of constraint handler
12231  */
12232 
12233 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
12234 static
12235 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLinear)
12236 { /*lint --e{715}*/
12237  assert(scip != NULL);
12238  assert(conshdlr != NULL);
12239  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12240 
12241  /* call inclusion method of constraint handler */
12243 
12244  *valid = TRUE;
12245 
12246  return SCIP_OKAY;
12247 }
12248 
12249 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
12250 static
12251 SCIP_DECL_CONSFREE(consFreeLinear)
12252 { /*lint --e{715}*/
12253  SCIP_CONSHDLRDATA* conshdlrdata;
12254 
12255  assert(scip != NULL);
12256  assert(conshdlr != NULL);
12257  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12258 
12259  /* free constraint handler data */
12260  conshdlrdata = SCIPconshdlrGetData(conshdlr);
12261  assert(conshdlrdata != NULL);
12262 
12263  conshdlrdataFree(scip, &conshdlrdata);
12264 
12265  SCIPconshdlrSetData(conshdlr, NULL);
12266 
12267  return SCIP_OKAY;
12268 }
12269 
12270 
12271 /** initialization method of constraint handler (called after problem was transformed) */
12272 static
12273 SCIP_DECL_CONSINIT(consInitLinear)
12274 {
12275  SCIP_CONSHDLRDATA* conshdlrdata;
12276  int c;
12277 
12278  assert(scip != NULL);
12279 
12280  /* get event handler */
12281  conshdlrdata = SCIPconshdlrGetData(conshdlr);
12282  assert(conshdlrdata != NULL);
12283  assert(conshdlrdata->eventhdlr != NULL);
12284  assert(nconss == 0 || conss != NULL);
12285 
12286  /* catch events for the constraints */
12287  for( c = 0; c < nconss; ++c )
12288  {
12289  /* catch all events */
12290  SCIP_CALL( consCatchAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
12291  }
12292 
12293  return SCIP_OKAY;
12294 }
12295 
12296 
12297 /** deinitialization method of constraint handler (called before transformed problem is freed) */
12298 static
12299 SCIP_DECL_CONSEXIT(consExitLinear)
12300 {
12301  SCIP_CONSHDLRDATA* conshdlrdata;
12302  int c;
12303 
12304  assert(scip != NULL);
12305 
12306  /* get event handler */
12307  conshdlrdata = SCIPconshdlrGetData(conshdlr);
12308  assert(conshdlrdata != NULL);
12309  assert(conshdlrdata->eventhdlr != NULL);
12310 
12311  /* drop events for the constraints */
12312  for( c = nconss - 1; c >= 0; --c )
12313  {
12314  SCIP_CONSDATA* consdata;
12315 
12316  consdata = SCIPconsGetData(conss[c]);
12317  assert(consdata != NULL);
12318 
12319  if( consdata->eventdatas != NULL )
12320  {
12321  /* drop all events */
12322  SCIP_CALL( consDropAllEvents(scip, conss[c], conshdlrdata->eventhdlr) );
12323  assert(consdata->eventdatas == NULL);
12324  }
12325  }
12326 
12327  return SCIP_OKAY;
12328 
12329 }
12330 
12331 #ifdef WITH_PRINTORIGCONSTYPES
12332 
12333 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
12334 static
12335 SCIP_Bool isRangedRow(
12336  SCIP* scip, /**< SCIP data structure */
12337  SCIP_CONS* cons /**< constraint */
12338  )
12339 {
12340  assert(scip != NULL);
12341  assert(cons != NULL);
12342  assert(SCIPconsGetData(cons) != NULL);
12343 
12344  return !(SCIPisEQ(scip, SCIPconsGetData(cons)->lhs, SCIPconsGetData(cons)->rhs)
12345  || SCIPisInfinity(scip, -SCIPconsGetData(cons)->lhs) || SCIPisInfinity(scip, SCIPconsGetData(cons)->rhs) );
12346 }
12347 
12348 /** is constraint ranged row, i.e., -inf < lhs < rhs < inf? */
12349 static
12350 SCIP_Bool isFiniteNonnegativeIntegral(
12351  SCIP* scip, /**< SCIP data structure */
12352  SCIP_Real x /**< value */
12353  )
12354 {
12355  assert(scip != NULL);
12356 
12357  return (!SCIPisInfinity(scip, x) && !SCIPisNegative(scip, x) && SCIPisIntegral(scip, x));
12358 }
12359 
12360 /** presolving initialization method of constraint handler (called when presolving is about to begin) */
12361 static
12362 SCIP_DECL_CONSINITPRE(consInitpreLinear)
12363 { /*lint --e{715}*/
12364  int counter[(int)SCIP_CONSTYPE_GENERAL + 1];
12365  int c;
12366 
12367  assert(scip != NULL);
12368 
12369  /* initialize counter for constraint types to zero */
12370  BMSclearMemoryArray(counter, (int)SCIP_CONSTYPE_GENERAL + 1);
12371 
12372  /* loop through all constraints */
12373  for( c = 0; c < nconss; c++ )
12374  {
12375  SCIP_CONS* cons;
12376  SCIP_CONSDATA* consdata;
12377  int i;
12378 
12379  /* get constraint */
12380  cons = conss[c];
12381  assert(cons != NULL);
12382 
12383  /* get constraint data */
12384  consdata = SCIPconsGetData(cons);
12385  assert(consdata != NULL);
12386 
12387  /* merge multiples and delete variables with zero coefficient */
12388  SCIP_CALL( mergeMultiples(scip, cons) );
12389  for( i = 0; i < consdata->nvars; i++ )
12390  {
12391  assert(!SCIPisZero(scip, consdata->vals[i]));
12392  }
12393 
12394  /* is constraint of type SCIP_CONSTYPE_EMPTY? */
12395  if( consdata->nvars == 0 )
12396  {
12397  SCIPdebugMessage("classified as EMPTY: ");
12398  SCIPdebugPrintCons(scip, cons, NULL);
12399  counter[SCIP_CONSTYPE_EMPTY]++;
12400  continue;
12401  }
12402 
12403  /* is constraint of type SCIP_CONSTYPE_FREE? */
12404  if( SCIPisInfinity(scip, consdata->rhs) && SCIPisInfinity(scip, -consdata->lhs) )
12405  {
12406  SCIPdebugMessage("classified as FREE: ");
12407  SCIPdebugPrintCons(scip, cons, NULL);
12408  counter[SCIP_CONSTYPE_FREE]++;
12409  continue;
12410  }
12411 
12412  /* is constraint of type SCIP_CONSTYPE_SINGLETON? */
12413  if( consdata->nvars == 1 )
12414  {
12415  SCIPdebugMessage("classified as SINGLETON: ");
12416  SCIPdebugPrintCons(scip, cons, NULL);
12417  counter[SCIP_CONSTYPE_SINGLETON] += isRangedRow(scip, cons) ? 2 : 1;
12418  continue;
12419  }
12420 
12421  /* is constraint of type SCIP_CONSTYPE_AGGREGATION? */
12422  if( consdata->nvars == 2 && SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
12423  {
12424  SCIPdebugMessage("classified as AGGREGATION: ");
12425  SCIPdebugPrintCons(scip, cons, NULL);
12426  counter[SCIP_CONSTYPE_AGGREGATION]++;
12427  continue;
12428  }
12429 
12430  /* is constraint of type SCIP_CONSTYPE_{VARBOUND}? */
12431  if( consdata->nvars == 2 )
12432  {
12433  SCIPdebugMessage("classified as VARBOUND: ");
12434  SCIPdebugPrintCons(scip, cons, NULL);
12435  counter[SCIP_CONSTYPE_VARBOUND] += isRangedRow(scip, cons) ? 2 : 1;
12436  continue;
12437  }
12438 
12439  /* is constraint of type SCIP_CONSTYPE_{SETPARTITION, SETPACKING, SETCOVERING, CARDINALITY, INVKNAPSACK}? */
12440  {
12441  SCIP_Real scale;
12442  SCIP_Real b;
12443  SCIP_Bool unmatched;
12444  int nnegbinvars;
12445 
12446  unmatched = FALSE;
12447  nnegbinvars = 0;
12448 
12449  scale = REALABS(consdata->vals[0]);
12450  for( i = 0; i < consdata->nvars && !unmatched; i++ )
12451  {
12452  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
12453  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
12454  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
12455  unmatched = unmatched || !SCIPisEQ(scip, REALABS(consdata->vals[i]), scale);
12456 
12457  if( consdata->vals[i] < 0.0 )
12458  nnegbinvars++;
12459  }
12460 
12461  if( !unmatched )
12462  {
12463  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
12464  {
12465  b = consdata->rhs/scale + nnegbinvars;
12466  if( SCIPisEQ(scip, 1.0, b) )
12467  {
12468  SCIPdebugMessage("classified as SETPARTITION: ");
12469  SCIPdebugPrintCons(scip, cons, NULL);
12470  counter[SCIP_CONSTYPE_SETPARTITION]++;
12471  continue;
12472  }
12473  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
12474  {
12475  SCIPdebugMessage("classified as CARDINALITY: ");
12476  SCIPdebugPrintCons(scip, cons, NULL);
12477  counter[SCIP_CONSTYPE_CARDINALITY]++;
12478  continue;
12479  }
12480  }
12481 
12482  b = consdata->rhs/scale + nnegbinvars;
12483  if( SCIPisEQ(scip, 1.0, b) )
12484  {
12485  SCIPdebugMessage("classified as SETPACKING: ");
12486  SCIPdebugPrintCons(scip, cons, NULL);
12487  counter[SCIP_CONSTYPE_SETPACKING]++;
12488  consdata->rhs = SCIPinfinity(scip);
12489  }
12490  else if( SCIPisIntegral(scip, b) && !SCIPisNegative(scip, b) )
12491  {
12492  SCIPdebugMessage("classified as INVKNAPSACK: ");
12493  SCIPdebugPrintCons(scip, cons, NULL);
12494  counter[SCIP_CONSTYPE_INVKNAPSACK]++;
12495  consdata->rhs = SCIPinfinity(scip);
12496  }
12497 
12498  b = consdata->lhs/scale + nnegbinvars;
12499  if( SCIPisEQ(scip, 1.0, b) )
12500  {
12501  SCIPdebugMessage("classified as SETCOVERING: ");
12502  SCIPdebugPrintCons(scip, cons, NULL);
12503  counter[SCIP_CONSTYPE_SETCOVERING]++;
12504  consdata->lhs = -SCIPinfinity(scip);
12505  }
12506 
12507  if( SCIPisInfinity(scip, -consdata->lhs) && SCIPisInfinity(scip, consdata->rhs) )
12508  continue;
12509  }
12510  }
12511 
12512  /* is constraint of type SCIP_CONSTYPE_{EQKNAPSACK, BINPACKING, KNAPSACK}? */
12513  /* @todo If coefficients or rhs are not integral, we currently do not check
12514  * if the constraint could be scaled (finitely), such that they are.
12515  */
12516  {
12517  SCIP_Real b;
12518  SCIP_Bool unmatched;
12519 
12520  b = consdata->rhs;
12521  unmatched = FALSE;
12522  for( i = 0; i < consdata->nvars && !unmatched; i++ )
12523  {
12524  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
12525  unmatched = unmatched || SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0);
12526  unmatched = unmatched || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0);
12527  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
12528 
12529  if( SCIPisNegative(scip, consdata->vals[i]) )
12530  b -= consdata->vals[i];
12531  }
12532  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
12533 
12534  if( !unmatched )
12535  {
12536  if( SCIPisEQ(scip, consdata->lhs, consdata->rhs) )
12537  {
12538  SCIPdebugMessage("classified as EQKNAPSACK: ");
12539  SCIPdebugPrintCons(scip, cons, NULL);
12540  counter[SCIP_CONSTYPE_EQKNAPSACK]++;
12541  continue;
12542  }
12543  else
12544  {
12545  SCIP_Bool matched;
12546 
12547  matched = FALSE;
12548  for( i = 0; i < consdata->nvars && !matched; i++ )
12549  {
12550  matched = matched || SCIPisEQ(scip, b, REALABS(consdata->vals[i]));
12551  }
12552 
12553  SCIPdebugMessage("classified as %s: ", matched ? "BINPACKING" : "KNAPSACK");
12554  SCIPdebugPrintCons(scip, cons, NULL);
12555  counter[matched ? SCIP_CONSTYPE_BINPACKING : SCIP_CONSTYPE_KNAPSACK]++;
12556  }
12557 
12558  if( SCIPisInfinity(scip, -consdata->lhs) )
12559  continue;
12560  else
12561  consdata->rhs = SCIPinfinity(scip);
12562  }
12563  }
12564 
12565  /* is constraint of type SCIP_CONSTYPE_{INTKNAPSACK}? */
12566  {
12567  SCIP_Real b;
12568  SCIP_Bool unmatched;
12569 
12570  unmatched = FALSE;
12571 
12572  b = consdata->rhs;
12573  unmatched = unmatched || !isFiniteNonnegativeIntegral(scip, b);
12574 
12575  for( i = 0; i < consdata->nvars && !unmatched; i++ )
12576  {
12577  unmatched = unmatched || SCIPvarGetType(consdata->vars[i]) == SCIP_VARTYPE_CONTINUOUS;
12578  unmatched = unmatched || SCIPisNegative(scip, SCIPvarGetLbGlobal(consdata->vars[i]));
12579  unmatched = unmatched || !SCIPisIntegral(scip, consdata->vals[i]);
12580  unmatched = unmatched || SCIPisNegative(scip, consdata->vals[i]);
12581  }
12582 
12583  if( !unmatched )
12584  {
12585  SCIPdebugMessage("classified as INTKNAPSACK: ");
12586  SCIPdebugPrintCons(scip, cons, NULL);
12587  counter[SCIP_CONSTYPE_INTKNAPSACK]++;
12588 
12589  if( SCIPisInfinity(scip, -consdata->lhs) )
12590  continue;
12591  else
12592  consdata->rhs = SCIPinfinity(scip);
12593  }
12594  }
12595 
12596  /* is constraint of type SCIP_CONSTYPE_{MIXEDBINARY}? */
12597  {
12598  SCIP_Bool unmatched;
12599 
12600  unmatched = FALSE;
12601  for( i = 0; i < consdata->nvars && !unmatched; i++ )
12602  {
12603  if( SCIPvarGetType(consdata->vars[i]) != SCIP_VARTYPE_CONTINUOUS
12604  && (SCIPisLE(scip, SCIPvarGetLbGlobal(consdata->vars[i]), -1.0)
12605  || SCIPisGE(scip, SCIPvarGetUbGlobal(consdata->vars[i]), 2.0)) )
12606  unmatched = TRUE;
12607  }
12608 
12609  if( !unmatched )
12610  {
12611  SCIPdebugMessage("classified as MIXEDBINARY (%d): ", isRangedRow(scip, cons) ? 2 : 1);
12612  SCIPdebugPrintCons(scip, cons, NULL);
12613  counter[SCIP_CONSTYPE_MIXEDBINARY] += isRangedRow(scip, cons) ? 2 : 1;
12614  continue;
12615  }
12616  }
12617 
12618  /* no special structure detected */
12619  SCIPdebugMessage("classified as GENERAL: ");
12620  SCIPdebugPrintCons(scip, cons, NULL);
12621  counter[SCIP_CONSTYPE_GENERAL] += isRangedRow(scip, cons) ? 2 : 1;
12622  }
12623 
12624  /* print statistics */
12625  SCIPinfoMessage(scip, NULL, "\n");
12626  SCIPinfoMessage(scip, NULL, "Number of constraints according to type:\n");
12627  SCIPinfoMessage(scip, NULL, "----------------------------------------\n");
12628  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_EMPTY %6d\n", 0, counter[ 0]);
12629  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_FREE %6d\n", 1, counter[ 1]);
12630  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SINGLETON %6d\n", 2, counter[ 2]);
12631  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_AGGREGATION %6d\n", 3, counter[ 3]);
12632  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_VARBOUND %6d\n", 4, counter[ 4]);
12633  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SETPARTITION %6d\n", 5, counter[ 5]);
12634  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SETPACKING %6d\n", 6, counter[ 6]);
12635  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_SETCOVERING %6d\n", 7, counter[ 7]);
12636  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_CARDINALITY %6d\n", 8, counter[ 8]);
12637  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_INVKNAPSACK %6d\n", 9, counter[ 9]);
12638  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_EQKNAPSACK %6d\n", 10, counter[10]);
12639  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_BINPACKING %6d\n", 11, counter[11]);
12640  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_KNAPSACK %6d\n", 12, counter[12]);
12641  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_INTKNAPSACK %6d\n", 13, counter[13]);
12642  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_MIXEDBINARY %6d\n", 14, counter[14]);
12643  SCIPinfoMessage(scip, NULL, "%2d SCIP_CONSTYPE_GENERAL %6d\n", 15, counter[15]);
12644  SCIPinfoMessage(scip, NULL, "----------------------------------------\n\n");
12645 
12646  SCIPinfoMessage(scip, NULL, " EMPTY");
12647  SCIPinfoMessage(scip, NULL, " FREE");
12648  SCIPinfoMessage(scip, NULL, " SING");
12649  SCIPinfoMessage(scip, NULL, " AGGR");
12650  SCIPinfoMessage(scip, NULL, " VARBD");
12651  SCIPinfoMessage(scip, NULL, " SETPART");
12652  SCIPinfoMessage(scip, NULL, " SETPACK");
12653  SCIPinfoMessage(scip, NULL, " SETCOV");
12654  SCIPinfoMessage(scip, NULL, " CARD");
12655  SCIPinfoMessage(scip, NULL, " INVKNAP");
12656  SCIPinfoMessage(scip, NULL, " EQKNAP");
12657  SCIPinfoMessage(scip, NULL, " BINPACK");
12658  SCIPinfoMessage(scip, NULL, " KNAP");
12659  SCIPinfoMessage(scip, NULL, " INTKNAP");
12660  SCIPinfoMessage(scip, NULL, " MIXBIN");
12661  SCIPinfoMessage(scip, NULL, " GEN\n");
12662  for( c = 0; c <= (int)SCIP_CONSTYPE_GENERAL; c++ )
12663  {
12664  SCIPinfoMessage(scip, NULL, "%9d", counter[c]);
12665  }
12666 
12667  SCIPinfoMessage(scip, NULL, "\n\n");
12668  SCIPinfoMessage(scip, NULL, "----------------------------------------\n\n");
12669 
12670  return SCIP_OKAY;
12671 }
12672 #endif
12673 
12674 
12675 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
12676 static
12677 SCIP_DECL_CONSEXITPRE(consExitpreLinear)
12678 { /*lint --e{715}*/
12679  int c;
12680 #ifdef SCIP_STATISTIC
12681  int ngoodconss;
12682  int nallconss;
12683 #endif
12684 
12685  /* delete all linear constraints that were upgraded to a more specific constraint type;
12686  * make sure, only active variables remain in the remaining constraints
12687  */
12688  assert(scip != NULL);
12689 
12690 #ifdef SCIP_STATISTIC
12691  /* count number of well behaved linear constraints */
12692 
12693  ngoodconss = 0;
12694  nallconss = 0;
12695 
12696  for( c = 0; c < nconss; ++c )
12697  {
12698  SCIP_CONSDATA* consdata;
12699 
12700  if( SCIPconsIsDeleted(conss[c]) )
12701  continue;
12702 
12703  consdata = SCIPconsGetData(conss[c]);
12704  assert(consdata != NULL);
12705 
12706  if( consdata->upgraded )
12707  continue;
12708 
12709  nallconss++;
12710 
12711  consdataRecomputeMaxActivityDelta(scip, consdata);
12712 
12713  if( SCIPisLT(scip, consdata->maxactdelta, MAXACTIVITYDELTATHR) )
12714  ngoodconss++;
12715  }
12716  if( nallconss )
12717  {
12718  SCIPstatisticMessage("below threshold: %d / %d ratio= %g\n", ngoodconss, nallconss, (100.0 * ngoodconss / nallconss));
12719  }
12720 #endif
12721 
12722  for( c = 0; c < nconss; ++c )
12723  {
12724  SCIP_CONSDATA* consdata;
12725 
12726  if( SCIPconsIsDeleted(conss[c]) )
12727  continue;
12728 
12729  consdata = SCIPconsGetData(conss[c]);
12730  assert(consdata != NULL);
12731 
12732  if( consdata->upgraded )
12733  {
12734  /* this is no problem reduction, because the upgraded constraint was added to the problem before, and the
12735  * (redundant) linear constraint was only kept in order to support presolving the the linear constraint handler
12736  */
12737  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
12738  }
12739  else
12740  {
12741  /* since we are not allowed to detect infeasibility in the exitpre stage, we dont give an infeasible pointer */
12742  SCIP_CALL( applyFixings(scip, conss[c], NULL) );
12743  }
12744  }
12745 
12746  return SCIP_OKAY;
12747 }
12748 
12749 
12750 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
12751 static
12752 SCIP_DECL_CONSEXITSOL(consExitsolLinear)
12753 { /*lint --e{715}*/
12754  int c;
12755 
12756  assert(scip != NULL);
12757 
12758  /* release the rows of all constraints */
12759  for( c = 0; c < nconss; ++c )
12760  {
12761  SCIP_CONSDATA* consdata;
12762 
12763  consdata = SCIPconsGetData(conss[c]);
12764  assert(consdata != NULL);
12765 
12766  if( consdata->row != NULL )
12767  {
12768  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
12769  }
12770  }
12771 
12772  /* if this is a restart, convert cutpool rows into linear constraints */
12773  if( restart )
12774  {
12775  int ncutsadded;
12776 
12777  ncutsadded = 0;
12778 
12779  /* create out of all active cuts in cutpool linear constraints */
12780  SCIP_CALL( SCIPconvertCutsToConss(scip, NULL, NULL, TRUE, &ncutsadded) );
12781 
12782  if( ncutsadded > 0 )
12783  {
12785  "(restart) converted %d cuts from the global cut pool into linear constraints\n", ncutsadded);
12786  /* an extra blank line should be printed separately since the buffer message handler only handles up to one
12787  * line correctly
12788  */
12790  }
12791  }
12792 
12793  return SCIP_OKAY;
12794 }
12795 
12796 
12797 /** frees specific constraint data */
12798 static
12799 SCIP_DECL_CONSDELETE(consDeleteLinear)
12800 { /*lint --e{715}*/
12801  SCIP_CONSHDLRDATA* conshdlrdata;
12802 
12803  assert(scip != NULL);
12804  assert(conshdlr != NULL);
12805  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12806 
12807  /* get event handler */
12808  conshdlrdata = SCIPconshdlrGetData(conshdlr);
12809  assert(conshdlrdata != NULL);
12810  assert(conshdlrdata->eventhdlr != NULL);
12811 
12812  /* free event datas */
12813  if( (*consdata)->eventdatas != NULL )
12814  {
12815  /* drop bound change events of variables */
12816  SCIP_CALL( consDropAllEvents(scip, cons, conshdlrdata->eventhdlr) );
12817  }
12818  assert((*consdata)->eventdatas == NULL);
12819 
12820  /* free linear constraint */
12821  SCIP_CALL( consdataFree(scip, consdata) );
12822 
12823  return SCIP_OKAY;
12824 }
12825 
12826 
12827 /** transforms constraint data into data belonging to the transformed problem */
12828 static
12829 SCIP_DECL_CONSTRANS(consTransLinear)
12830 { /*lint --e{715}*/
12831  SCIP_CONSHDLRDATA* conshdlrdata;
12832  SCIP_CONSDATA* sourcedata;
12833  SCIP_CONSDATA* targetdata;
12834 
12835  /*debugMessage("Trans method of linear constraints\n");*/
12836 
12837  assert(scip != NULL);
12838  assert(conshdlr != NULL);
12839  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12840  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
12841  assert(sourcecons != NULL);
12842  assert(targetcons != NULL);
12843 
12844  sourcedata = SCIPconsGetData(sourcecons);
12845  assert(sourcedata != NULL);
12846  assert(sourcedata->row == NULL); /* in original problem, there cannot be LP rows */
12847 
12848  /* get event handler */
12849  conshdlrdata = SCIPconshdlrGetData(conshdlr);
12850  assert(conshdlrdata != NULL);
12851  assert(conshdlrdata->eventhdlr != NULL);
12852 
12853  /* create linear constraint data for target constraint */
12854  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->nvars, sourcedata->vars, sourcedata->vals, sourcedata->lhs, sourcedata->rhs) );
12855 
12856  /* create target constraint */
12857  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
12858  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
12859  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
12860  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
12861  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
12862 
12863  if( SCIPisTransformed(scip) && needEvents(scip) )
12864  {
12865  /* catch bound change events of variables */
12866  SCIP_CALL( consCatchAllEvents(scip, *targetcons, conshdlrdata->eventhdlr) );
12867  assert(targetdata->eventdatas != NULL);
12868  }
12869 
12870  return SCIP_OKAY;
12871 }
12872 
12873 
12874 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
12875 static
12876 SCIP_DECL_CONSINITLP(consInitlpLinear)
12877 { /*lint --e{715}*/
12878  SCIP_Bool cutoff;
12879  int c;
12880 
12881  assert(scip != NULL);
12882  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12883 
12884  for( c = 0; c < nconss; ++c )
12885  {
12886  assert(SCIPconsIsInitial(conss[c]));
12887  SCIP_CALL( addRelaxation(scip, conss[c], NULL, &cutoff) );
12888  /* cannot use cutoff here, since initlp has no return value */
12889  }
12890 
12891  return SCIP_OKAY;
12892 }
12893 
12894 
12895 /** separation method of constraint handler for LP solutions */
12896 static
12897 SCIP_DECL_CONSSEPALP(consSepalpLinear)
12898 { /*lint --e{715}*/
12899  SCIP_CONSHDLRDATA* conshdlrdata;
12900  SCIP_Real loclowerbound;
12901  SCIP_Real glblowerbound;
12902  SCIP_Real cutoffbound;
12903  SCIP_Real maxbound;
12904  SCIP_Bool separatecards;
12905  SCIP_Bool cutoff;
12906  int c;
12907  int depth;
12908  int nrounds;
12909  int maxsepacuts;
12910  int ncuts;
12911 
12912  assert(scip != NULL);
12913  assert(conshdlr != NULL);
12914  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12915  assert(result != NULL);
12916 
12917  conshdlrdata = SCIPconshdlrGetData(conshdlr);
12918  assert(conshdlrdata != NULL);
12919  depth = SCIPgetDepth(scip);
12920  nrounds = SCIPgetNSepaRounds(scip);
12921 
12922  /*debugMessage("Sepa method of linear constraints\n");*/
12923 
12924  *result = SCIP_DIDNOTRUN;
12925 
12926  /* only call the separator a given number of times at each node */
12927  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
12928  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
12929  return SCIP_OKAY;
12930 
12931  /* get the maximal number of cuts allowed in a separation round */
12932  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
12933 
12934  /* check if we want to produce knapsack cardinality cuts at this node */
12935  loclowerbound = SCIPgetLocalLowerbound(scip);
12936  glblowerbound = SCIPgetLowerbound(scip);
12937  cutoffbound = SCIPgetCutoffbound(scip);
12938  maxbound = glblowerbound + conshdlrdata->maxcardbounddist * (cutoffbound - glblowerbound);
12939  separatecards = SCIPisLE(scip, loclowerbound, maxbound);
12940  separatecards = separatecards && (SCIPgetNLPBranchCands(scip) > 0);
12941 
12942  *result = SCIP_DIDNOTFIND;
12943  ncuts = 0;
12944  cutoff = FALSE;
12945 
12946  /* check all useful linear constraints for feasibility */
12947  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
12948  {
12949  /*debugMessage("separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
12950  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, NULL, separatecards, conshdlrdata->separateall, &ncuts, &cutoff) );
12951  }
12952 
12953  /* adjust return value */
12954  if( cutoff )
12955  *result = SCIP_CUTOFF;
12956  else if( ncuts > 0 )
12957  *result = SCIP_SEPARATED;
12958 
12959  /* combine linear constraints to get more cuts */
12960  /**@todo further cuts of linear constraints */
12961 
12962  return SCIP_OKAY;
12963 }
12964 
12965 
12966 /** separation method of constraint handler for arbitrary primal solutions */
12967 static
12968 SCIP_DECL_CONSSEPASOL(consSepasolLinear)
12969 { /*lint --e{715}*/
12970  SCIP_CONSHDLRDATA* conshdlrdata;
12971  int c;
12972  int depth;
12973  int nrounds;
12974  int maxsepacuts;
12975  int ncuts;
12976  SCIP_Bool cutoff;
12977 
12978  assert(scip != NULL);
12979  assert(conshdlr != NULL);
12980  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
12981  assert(result != NULL);
12982 
12983  conshdlrdata = SCIPconshdlrGetData(conshdlr);
12984  assert(conshdlrdata != NULL);
12985  depth = SCIPgetDepth(scip);
12986  nrounds = SCIPgetNSepaRounds(scip);
12987 
12988  /*debugMessage("Sepa method of linear constraints\n");*/
12989 
12990  *result = SCIP_DIDNOTRUN;
12991 
12992  /* only call the separator a given number of times at each node */
12993  if( (depth == 0 && conshdlrdata->maxroundsroot >= 0 && nrounds >= conshdlrdata->maxroundsroot)
12994  || (depth > 0 && conshdlrdata->maxrounds >= 0 && nrounds >= conshdlrdata->maxrounds) )
12995  return SCIP_OKAY;
12996 
12997  /* get the maximal number of cuts allowed in a separation round */
12998  maxsepacuts = (depth == 0 ? conshdlrdata->maxsepacutsroot : conshdlrdata->maxsepacuts);
12999 
13000  *result = SCIP_DIDNOTFIND;
13001  ncuts = 0;
13002  cutoff = FALSE;
13003 
13004  /* check all useful linear constraints for feasibility */
13005  for( c = 0; c < nusefulconss && ncuts < maxsepacuts && !cutoff; ++c )
13006  {
13007  /*debugMessage("separating linear constraint <%s>\n", SCIPconsGetName(conss[c]));*/
13008  SCIP_CALL( separateCons(scip, conss[c], conshdlrdata, sol, TRUE, conshdlrdata->separateall, &ncuts, &cutoff) );
13009  }
13010 
13011  /* adjust return value */
13012  if( cutoff )
13013  *result = SCIP_CUTOFF;
13014  else if( ncuts > 0 )
13015  *result = SCIP_SEPARATED;
13016 
13017  /* combine linear constraints to get more cuts */
13018  /**@todo further cuts of linear constraints */
13019 
13020  return SCIP_OKAY;
13021 }
13022 
13023 
13024 /** constraint enforcing method of constraint handler for LP solutions */
13025 static
13026 SCIP_DECL_CONSENFOLP(consEnfolpLinear)
13027 { /*lint --e{715}*/
13028  SCIP_CONSHDLRDATA* conshdlrdata;
13029  SCIP_Bool checkrelmaxabs;
13030  SCIP_Bool violated;
13031  SCIP_Bool cutoff;
13032  int c;
13033 
13034  assert(scip != NULL);
13035  assert(conshdlr != NULL);
13036  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13037  assert(result != NULL);
13038 
13039  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13040  assert(conshdlrdata != NULL);
13041 
13042  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
13043 
13044  /*SCIPdebugMessage("Enfolp method of linear constraints\n");*/
13045 
13046  /* check for violated constraints
13047  * LP is processed at current node -> we can add violated linear constraints to the SCIP_LP
13048  */
13049  *result = SCIP_FEASIBLE;
13050 
13051  /* check all useful linear constraints for feasibility */
13052  for( c = 0; c < nusefulconss; ++c )
13053  {
13054  SCIP_CALL( checkCons(scip, conss[c], NULL, FALSE, checkrelmaxabs, &violated) );
13055 
13056  if( violated )
13057  {
13058  /* insert LP row as cut */
13059  SCIP_CALL( addRelaxation(scip, conss[c], NULL, &cutoff) );
13060  if ( cutoff )
13061  *result = SCIP_CUTOFF;
13062  else
13063  *result = SCIP_SEPARATED;
13064  }
13065  }
13066 
13067  /* check all obsolete linear constraints for feasibility */
13068  for( c = nusefulconss; c < nconss && *result == SCIP_FEASIBLE; ++c )
13069  {
13070  SCIP_CALL( checkCons(scip, conss[c], NULL, FALSE, checkrelmaxabs, &violated) );
13071 
13072  if( violated )
13073  {
13074  /* insert LP row as cut */
13075  SCIP_CALL( addRelaxation(scip, conss[c], NULL, &cutoff) );
13076  if ( cutoff )
13077  *result = SCIP_CUTOFF;
13078  else
13079  *result = SCIP_SEPARATED;
13080  }
13081  }
13082 
13083  return SCIP_OKAY;
13084 }
13085 
13086 
13087 /** constraint enforcing method of constraint handler for pseudo solutions */
13088 static
13089 SCIP_DECL_CONSENFOPS(consEnfopsLinear)
13090 { /*lint --e{715}*/
13091  SCIP_CONSHDLRDATA* conshdlrdata;
13092  SCIP_Bool checkrelmaxabs;
13093  SCIP_Bool violated;
13094  int c;
13095 
13096  assert(scip != NULL);
13097  assert(conshdlr != NULL);
13098  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13099  assert(result != NULL);
13100 
13101  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13102  assert(conshdlrdata != NULL);
13103 
13104  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
13105 
13106  SCIPdebugMessage("Enfops method of linear constraints\n");
13107 
13108  /* if the solution is infeasible anyway due to objective value, skip the enforcement */
13109  if( objinfeasible )
13110  {
13111  SCIPdebugMessage("-> pseudo solution is objective infeasible, return.\n");
13112 
13113  *result = SCIP_DIDNOTRUN;
13114  return SCIP_OKAY;
13115  }
13116 
13117  /* check all linear constraints for feasibility */
13118  violated = FALSE;
13119  for( c = 0; c < nconss && !violated; ++c )
13120  {
13121  SCIP_CALL( checkCons(scip, conss[c], NULL, TRUE, checkrelmaxabs, &violated) );
13122  }
13123 
13124  if( violated )
13125  *result = SCIP_INFEASIBLE;
13126  else
13127  *result = SCIP_FEASIBLE;
13128 
13129  SCIPdebugMessage("-> constraints checked, %s\n", *result == SCIP_FEASIBLE ? "all constraints feasible" : "infeasibility detected");
13130 
13131  return SCIP_OKAY;
13132 }
13133 
13134 
13135 /** feasibility check method of constraint handler for integral solutions */
13136 static
13137 SCIP_DECL_CONSCHECK(consCheckLinear)
13138 { /*lint --e{715}*/
13139  SCIP_CONSHDLRDATA* conshdlrdata;
13140  SCIP_Bool checkrelmaxabs;
13141  SCIP_Bool violated;
13142  int c;
13143 
13144  assert(scip != NULL);
13145  assert(conshdlr != NULL);
13146  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13147  assert(result != NULL);
13148 
13149  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13150  assert(conshdlrdata != NULL);
13151 
13152  checkrelmaxabs = conshdlrdata->checkrelmaxabs;
13153 
13154  /*debugMessage("Check method of linear constraints\n");*/
13155 
13156  /* check all linear constraints for feasibility */
13157  violated = FALSE;
13158  for( c = 0; c < nconss && !violated; ++c )
13159  {
13160  SCIP_CALL( checkCons(scip, conss[c], sol, checklprows, checkrelmaxabs, &violated) );
13161  }
13162 
13163  if( violated )
13164  {
13165  *result = SCIP_INFEASIBLE;
13166 
13167  if( printreason )
13168  {
13169  SCIP_CONSDATA* consdata;
13170  SCIP_Real activity;
13171 
13172  consdata = SCIPconsGetData(conss[c-1]);
13173  assert( consdata != NULL);
13174 
13175  activity = consdataGetActivity(scip, consdata, sol);
13176 
13177  SCIP_CALL( SCIPprintCons(scip, conss[c-1], NULL ) );
13178  SCIPinfoMessage(scip, NULL, ";\n");
13179 
13180  if( SCIPisFeasLT(scip, activity, consdata->lhs) )
13181  SCIPinfoMessage(scip, NULL, "violation: left hand side is violated by %.15g\n", consdata->lhs - activity);
13182 
13183  if( SCIPisFeasGT(scip, activity, consdata->rhs) )
13184  SCIPinfoMessage(scip, NULL, "violation: right hand side is violated by %.15g\n", activity - consdata->rhs);
13185  }
13186  }
13187  else
13188  *result = SCIP_FEASIBLE;
13189 
13190  return SCIP_OKAY;
13191 }
13192 
13193 
13194 /** domain propagation method of constraint handler */
13195 static
13196 SCIP_DECL_CONSPROP(consPropLinear)
13197 { /*lint --e{715}*/
13198  SCIP_CONSHDLRDATA* conshdlrdata;
13199  SCIP_Bool tightenbounds;
13200  SCIP_Bool cutoff;
13201  int nchgbds;
13202  int i;
13203 
13204  assert(scip != NULL);
13205  assert(conshdlr != NULL);
13206  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13207  assert(result != NULL);
13208 
13209  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13210  assert(conshdlrdata != NULL);
13211 
13212  /*debugMessage("Prop method of linear constraints\n");*/
13213 
13214  /* check, if we want to tighten variable's bounds (in probing, we always want to tighten the bounds) */
13215  if( SCIPinProbing(scip) )
13216  tightenbounds = TRUE;
13217  else
13218  {
13219  int depth;
13220  int propfreq;
13221  int tightenboundsfreq;
13222 
13223  depth = SCIPgetDepth(scip);
13224  propfreq = SCIPconshdlrGetPropFreq(conshdlr);
13225  tightenboundsfreq = propfreq * conshdlrdata->tightenboundsfreq;
13226  tightenbounds = (conshdlrdata->tightenboundsfreq >= 0)
13227  && ((tightenboundsfreq == 0 && depth == 0) || (tightenboundsfreq >= 1 && (depth % tightenboundsfreq == 0)));
13228  }
13229 
13230  cutoff = FALSE;
13231  nchgbds = 0;
13232 
13233  /* process constraints marked for propagation */
13234  for( i = 0; i < nmarkedconss && !cutoff; i++ )
13235  {
13236  SCIP_CALL( SCIPunmarkConsPropagate(scip, conss[i]) );
13237  SCIP_CALL( propagateCons(scip, conss[i], tightenbounds, conshdlrdata->sortvars, &cutoff, &nchgbds) );
13238  }
13239 
13240  /* adjust result code */
13241  if( cutoff )
13242  *result = SCIP_CUTOFF;
13243  else if( nchgbds > 0 )
13244  *result = SCIP_REDUCEDDOM;
13245  else
13246  *result = SCIP_DIDNOTFIND;
13247 
13248  return SCIP_OKAY;
13249 }
13250 
13251 
13252 #define MAXCONSPRESOLROUNDS 10
13253 /** presolving method of constraint handler */
13254 static
13255 SCIP_DECL_CONSPRESOL(consPresolLinear)
13256 { /*lint --e{715}*/
13257  SCIP_CONSHDLRDATA* conshdlrdata;
13258  SCIP_CONS* cons;
13259  SCIP_CONSDATA* consdata;
13260  SCIP_Real minactivity;
13261  SCIP_Real maxactivity;
13262  SCIP_Bool minactisrelax;
13263  SCIP_Bool maxactisrelax;
13264  SCIP_Bool cutoff;
13265  SCIP_Bool delay;
13266  int oldnfixedvars;
13267  int oldnaggrvars;
13268  int oldnchgbds;
13269  int oldndelconss;
13270  int oldnupgdconss;
13271  int oldnchgcoefs;
13272  int oldnchgsides;
13273  int firstchange;
13274  int firstupgradetry;
13275  int c;
13276 
13277  assert(scip != NULL);
13278  assert(conshdlr != NULL);
13279  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
13280  assert(result != NULL);
13281 
13282  /*debugMessage("Presol method of linear constraints\n");*/
13283 
13284  /* remember old preprocessing counters */
13285  cutoff = FALSE;
13286  delay = FALSE;
13287  oldnfixedvars = *nfixedvars;
13288  oldnaggrvars = *naggrvars;
13289  oldnchgbds = *nchgbds;
13290  oldndelconss = *ndelconss;
13291  oldnupgdconss = *nupgdconss;
13292  oldnchgcoefs = *nchgcoefs;
13293  oldnchgsides = *nchgsides;
13294 
13295  /* get constraint handler data */
13296  conshdlrdata = SCIPconshdlrGetData(conshdlr);
13297  assert(conshdlrdata != NULL);
13298 
13299  /* process single constraints */
13300  firstchange = INT_MAX;
13301  firstupgradetry = INT_MAX;
13302  for( c = 0; c < nconss && !cutoff && !SCIPisStopped(scip); ++c )
13303  {
13304  int npresolrounds;
13305  SCIP_Bool infeasible;
13306 
13307  infeasible = FALSE;
13308 
13309  cons = conss[c];
13310  assert(SCIPconsIsActive(cons));
13311  consdata = SCIPconsGetData(cons);
13312  assert(consdata != NULL);
13313 
13314  /* constraint should not be already presolved in the initial round */
13315  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->propagated);
13316  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->boundstightened);
13317  assert(SCIPgetNRuns(scip) > 0 || nrounds > 0 || !consdata->presolved);
13318  assert(consdata->propagated || !consdata->presolved);
13319 
13320  /* incorporate fixings and aggregations in constraint */
13321  SCIP_CALL( applyFixings(scip, cons, &infeasible) );
13322 
13323  if( infeasible )
13324  {
13325  SCIPdebugMessage(" -> infeasible fixing\n");
13326  cutoff = TRUE;
13327  break;
13328  }
13329 
13330  assert(consdata->removedfixings);
13331 
13332  /* we can only presolve linear constraints, that are not modifiable */
13333  if( SCIPconsIsModifiable(cons) )
13334  continue;
13335 
13336  /* remember the first changed constraint to begin the next aggregation round with */
13337  if( firstchange == INT_MAX && consdata->changed )
13338  firstchange = c;
13339 
13340  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
13341  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
13342  firstupgradetry = c;
13343 
13344  /* check, if constraint is already preprocessed */
13345  if( consdata->presolved )
13346  continue;
13347 
13348  assert(SCIPconsIsActive(cons));
13349 
13350  SCIPdebugMessage("presolving linear constraint <%s>\n", SCIPconsGetName(cons));
13351  SCIPdebugPrintCons(scip, cons, NULL);
13352 
13353  /* apply presolving as long as possible on the single constraint (however, abort after a certain number of rounds
13354  * to avoid nearly infinite cycling due to very small bound changes)
13355  */
13356  npresolrounds = 0;
13357  while( !consdata->presolved && npresolrounds < MAXCONSPRESOLROUNDS && !SCIPisStopped(scip) )
13358  {
13359  assert(!cutoff);
13360  npresolrounds++;
13361 
13362  /* mark constraint being presolved and propagated */
13363  consdata->presolved = TRUE;
13364  consdata->propagated = TRUE;
13365 
13366  /* normalize constraint */
13367  SCIP_CALL( normalizeCons(scip, cons) );
13368 
13369  /* tighten left and right hand side due to integrality */
13370  SCIP_CALL( tightenSides(scip, cons, nchgsides) );
13371 
13372  /* check bounds */
13373  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
13374  {
13375  SCIPdebugMessage("linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
13376  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
13377  cutoff = TRUE;
13378  break;
13379  }
13380 
13381  /* tighten variable's bounds */
13382  SCIP_CALL( tightenBounds(scip, cons, conshdlrdata->sortvars, &cutoff, nchgbds) );
13383  if( cutoff )
13384  break;
13385 
13386  /* check for fixed variables */
13387  SCIP_CALL( fixVariables(scip, cons, &cutoff, nfixedvars) );
13388  if( cutoff )
13389  break;
13390 
13391  /* check constraint for infeasibility and redundancy */
13392  consdataGetActivityBounds(scip, consdata, TRUE, &minactivity, &maxactivity, &minactisrelax, &maxactisrelax);
13393  if( SCIPisFeasGT(scip, minactivity, consdata->rhs) || SCIPisFeasLT(scip, maxactivity, consdata->lhs) )
13394  {
13395  SCIPdebugMessage("linear constraint <%s> is infeasible: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
13396  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
13397  cutoff = TRUE;
13398  break;
13399  }
13400  else if( SCIPisFeasGE(scip, minactivity, consdata->lhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
13401  {
13402  SCIPdebugMessage("linear constraint <%s> is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
13403  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
13404  SCIP_CALL( SCIPdelCons(scip, cons) );
13405  assert(!SCIPconsIsActive(cons));
13406 
13407  if( !consdata->upgraded )
13408  (*ndelconss)++;
13409  break;
13410  }
13411  else if( !SCIPisInfinity(scip, -consdata->lhs) && SCIPisFeasGE(scip, minactivity, consdata->lhs) )
13412  {
13413  SCIPdebugMessage("linear constraint <%s> left hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
13414  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
13415  SCIP_CALL( chgLhs(scip, cons, -SCIPinfinity(scip)) );
13416  if( !consdata->upgraded )
13417  (*nchgsides)++;
13418  }
13419  else if( !SCIPisInfinity(scip, consdata->rhs) && SCIPisFeasLE(scip, maxactivity, consdata->rhs) )
13420  {
13421  SCIPdebugMessage("linear constraint <%s> right hand side is redundant: activitybounds=[%.15g,%.15g], sides=[%.15g,%.15g]\n",
13422  SCIPconsGetName(cons), minactivity, maxactivity, consdata->lhs, consdata->rhs);
13423  SCIP_CALL( chgRhs(scip, cons, SCIPinfinity(scip)) );
13424  if( !consdata->upgraded )
13425  (*nchgsides)++;
13426  }
13427  assert(consdata->nvars >= 1); /* otherwise, it should be redundant or infeasible */
13428 
13429  /* handle empty constraint */
13430  if( consdata->nvars == 0 )
13431  {
13432  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
13433  {
13434  SCIPdebugMessage("empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
13435  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
13436  cutoff = TRUE;
13437  }
13438  else
13439  {
13440  SCIPdebugMessage("empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
13441  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
13442  SCIP_CALL( SCIPdelCons(scip, cons) );
13443  assert(!SCIPconsIsActive(cons));
13444 
13445  if( !consdata->upgraded )
13446  (*ndelconss)++;
13447  }
13448  break;
13449  }
13450 
13451  /* reduce big-M coefficients, that make the constraint redundant if the variable is on a bound */
13452  SCIP_CALL( consdataTightenCoefs(scip, cons, nchgcoefs, nchgsides) );
13453 
13454  /* try to simplify inequalities */
13455  if( conshdlrdata->simplifyinequalities )
13456  {
13457  SCIP_CALL( simplifyInequalities(scip, cons, nchgcoefs, nchgsides) );
13458  }
13459 
13460  /* aggregation variable in equations */
13461  if( conshdlrdata->aggregatevariables )
13462  {
13463  SCIP_CALL( aggregateVariables(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
13464  if( cutoff )
13465  break;
13466  }
13467  }
13468 
13469  if( !SCIPisStopped(scip) )
13470  {
13471  /* extract cliques from constraint */
13472  if( !cutoff && SCIPconsIsActive(cons) )
13473  {
13474  SCIP_CALL( extractCliques(scip, cons, conshdlrdata->sortvars, nfixedvars, nchgbds, &cutoff) );
13475 
13476  /* check if the constraint got redundant or infeasible */
13477  if( !cutoff && SCIPconsIsActive(cons) && consdata->nvars == 0 )
13478  {
13479  if( SCIPisFeasGT(scip, consdata->lhs, consdata->rhs) )
13480  {
13481  SCIPdebugMessage("empty linear constraint <%s> is infeasible: sides=[%.15g,%.15g]\n",
13482  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
13483  cutoff = TRUE;
13484  }
13485  else
13486  {
13487  SCIPdebugMessage("empty linear constraint <%s> is redundant: sides=[%.15g,%.15g]\n",
13488  SCIPconsGetName(cons), consdata->lhs, consdata->rhs);
13489  SCIP_CALL( SCIPdelCons(scip, cons) );
13490  assert(!SCIPconsIsActive(cons));
13491 
13492  if( !consdata->upgraded )
13493  (*ndelconss)++;
13494  }
13495  }
13496  }
13497 
13498  /* convert special equalities */
13499  if( !cutoff && SCIPconsIsActive(cons) )
13500  {
13501  SCIP_CALL( convertEquality(scip, cons, conshdlrdata, &cutoff, nfixedvars, naggrvars, ndelconss) );
13502  }
13503 
13504  /* apply dual presolving for variables that appear in only one constraint */
13505  if( !cutoff && SCIPconsIsActive(cons) && conshdlrdata->dualpresolving )
13506  {
13507  SCIP_CALL( dualPresolve(scip, cons, &cutoff, nfixedvars, naggrvars, ndelconss) );
13508  }
13509 
13510  /* check if an inequality is parallel to the objective function */
13511  if( !cutoff && SCIPconsIsActive(cons) )
13512  {
13513  SCIP_CALL( checkParallelObjective(scip, cons, conshdlrdata) );
13514  }
13515 
13516  /* remember the first changed constraint to begin the next aggregation round with */
13517  if( firstchange == INT_MAX && consdata->changed )
13518  firstchange = c;
13519 
13520  /* remember the first constraint that was not yet tried to be upgraded, to begin the next upgrading round with */
13521  if( firstupgradetry == INT_MAX && !consdata->upgradetried )
13522  firstupgradetry = c;
13523  }
13524  }
13525 
13526  /* process pairs of constraints: check them for redundancy and try to aggregate them;
13527  * only apply this expensive procedure, if the single constraint preprocessing did not find any reductions
13528  * (otherwise, we delay the presolving to be called again next time)
13529  */
13530  if( !cutoff && (conshdlrdata->presolusehashing || conshdlrdata->presolpairwise) && !SCIPisStopped(scip) )
13531  {
13532  if( *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
13533  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides )
13534  {
13535  assert(firstchange >= 0);
13536 
13537  if( firstchange < nconss && conshdlrdata->presolusehashing )
13538  {
13539  /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
13540  SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff,
13541  ndelconss, nchgsides) );
13542  }
13543 
13544  if( firstchange < nconss && conshdlrdata->presolpairwise )
13545  {
13546  SCIP_CONS** usefulconss;
13547  int nusefulconss;
13548  int firstchangenew;
13549  SCIP_Longint npaircomparisons;
13550 
13551  npaircomparisons = 0;
13552  oldndelconss = *ndelconss;
13553  oldnchgsides = *nchgsides;
13554  oldnchgcoefs = *nchgcoefs;
13555 
13556  /* allocate temporary memory */
13557  SCIP_CALL( SCIPallocBufferArray(scip, &usefulconss, nconss) );
13558 
13559  nusefulconss = 0;
13560  firstchangenew = -1;
13561  for( c = 0; c < nconss; ++c )
13562  {
13563  /* update firstchange */
13564  if( c == firstchange )
13565  firstchangenew = nusefulconss;
13566 
13567  /* ignore inactive and modifiable constraints */
13568  if( !SCIPconsIsActive(conss[c]) || SCIPconsIsModifiable(conss[c]) )
13569  continue;
13570 
13571  usefulconss[nusefulconss] = conss[c];
13572  ++nusefulconss;
13573  }
13574  firstchange = firstchangenew;
13575  assert(firstchangenew >= 0 && firstchangenew <= nusefulconss);
13576 
13577  for( c = firstchange; c < nusefulconss && !cutoff && !SCIPisStopped(scip); ++c )
13578  {
13579  /* constraint has become inactive or modifiable during pairwise presolving */
13580  if( usefulconss[c] == NULL )
13581  continue;
13582 
13583  npaircomparisons += (SCIPconsGetData(conss[c])->changed) ? c : (c - firstchange); /*lint !e776*/
13584 
13585  assert(SCIPconsIsActive(usefulconss[c]) && !SCIPconsIsModifiable(usefulconss[c]));
13586  SCIP_CALL( preprocessConstraintPairs(scip, usefulconss, firstchange, c, conshdlrdata->maxaggrnormscale,
13587  &cutoff, ndelconss, nchgsides, nchgcoefs) );
13588 
13589  if( npaircomparisons > conshdlrdata->nmincomparisons )
13590  {
13591  assert(npaircomparisons > 0);
13592  if( ((*ndelconss - oldndelconss) + (*nchgsides - oldnchgsides)/2.0 + (*nchgcoefs - oldnchgcoefs)/10.0) / ((SCIP_Real) npaircomparisons) < conshdlrdata->mingainpernmincomp )
13593  break;
13594  oldndelconss = *ndelconss;
13595  oldnchgsides = *nchgsides;
13596  oldnchgcoefs = *nchgcoefs;
13597  npaircomparisons = 0;
13598  }
13599  }
13600  /* free temporary memory */
13601  SCIPfreeBufferArray(scip, &usefulconss);
13602  }
13603  }
13604  else
13605  delay = TRUE;
13606  }
13607 
13608  /* before upgrading, check whether we can apply some additional dual presolving, because a variable only appears
13609  * in linear constraints and we therefore have full information about it
13610  */
13611  if( !cutoff && firstupgradetry < nconss
13612  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
13613  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
13614  )
13615  {
13616  if( conshdlrdata->dualpresolving && !SCIPisStopped(scip) )
13617  {
13618  SCIP_CALL( fullDualPresolve(scip, conss, nconss, &cutoff, nchgbds) );
13619  }
13620  }
13621 
13622  /* try to upgrade constraints into a more specific constraint type;
13623  * only upgrade constraints, if no reductions were found in this round (otherwise, the linear constraint handler
13624  * may find additional reductions before giving control away to other (less intelligent?) constraint handlers)
13625  */
13626  if( !cutoff
13627  && *nfixedvars == oldnfixedvars && *naggrvars == oldnaggrvars && *nchgbds == oldnchgbds && *ndelconss == oldndelconss
13628  && *nupgdconss == oldnupgdconss && *nchgcoefs == oldnchgcoefs && *nchgsides == oldnchgsides
13629  )
13630  {
13631  for( c = firstupgradetry; c < nconss && !SCIPisStopped(scip); ++c )
13632  {
13633  cons = conss[c];
13634 
13635  /* don't upgrade modifiable constraints */
13636  if( SCIPconsIsModifiable(cons) )
13637  continue;
13638 
13639  consdata = SCIPconsGetData(cons);
13640  assert(consdata != NULL);
13641 
13642  /* only upgrade completely presolved constraints, that changed since the last upgrading call */
13643  if( consdata->upgradetried )
13644  continue;
13645  if( !consdata->presolved )
13646  {
13647  delay = TRUE;
13648  continue;
13649  }
13650 
13651  consdata->upgradetried = TRUE;
13652  if( SCIPconsIsActive(cons) )
13653  {
13654  SCIP_CONS* upgdcons;
13655 
13656  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
13657  if( upgdcons != NULL )
13658  {
13659  /* add the upgraded constraint to the problem */
13660  SCIP_CALL( SCIPaddCons(scip, upgdcons) );
13661  SCIP_CALL( SCIPreleaseCons(scip, &upgdcons) );
13662  (*nupgdconss)++;
13663 
13664  /* mark the linear constraint being upgraded and to be removed after presolving;
13665  * don't delete it directly, because it may help to preprocess other linear constraints
13666  */
13667  assert(!consdata->upgraded);
13668  consdata->upgraded = TRUE;
13669 
13670  /* delete upgraded inequalities immediately;
13671  * delete upgraded equalities, if we don't need it anymore for aggregation and redundancy checking
13672  */
13673  if( SCIPisLT(scip, consdata->lhs, consdata->rhs)
13674  || !conshdlrdata->presolpairwise
13675  || (conshdlrdata->maxaggrnormscale == 0.0) )
13676  {
13677  SCIP_CALL( SCIPdelCons(scip, cons) );
13678  }
13679  }
13680  }
13681  }
13682  }
13683  else
13684  delay = TRUE;
13685 
13686  /* return the correct result code */
13687  if( cutoff )
13688  *result = SCIP_CUTOFF;
13689  else if( delay )
13690  *result = SCIP_DELAYED;
13691  else if( *nfixedvars > oldnfixedvars || *naggrvars > oldnaggrvars || *nchgbds > oldnchgbds || *ndelconss > oldndelconss
13692  || *nupgdconss > oldnupgdconss || *nchgcoefs > oldnchgcoefs || *nchgsides > oldnchgsides )
13693  *result = SCIP_SUCCESS;
13694  else
13695  *result = SCIP_DIDNOTFIND;
13696 
13697  return SCIP_OKAY;
13698 }
13699 
13700 
13701 /** propagation conflict resolving method of constraint handler */
13702 static
13703 SCIP_DECL_CONSRESPROP(consRespropLinear)
13704 { /*lint --e{715}*/
13705 
13706  assert(scip != NULL);
13707  assert(cons != NULL);
13708  assert(result != NULL);
13709 
13710  SCIP_CALL( resolvePropagation(scip, cons, infervar, intToInferInfo(inferinfo), boundtype, bdchgidx, result) );
13711 
13712  return SCIP_OKAY;
13713 }
13714 
13715 
13716 /** variable rounding lock method of constraint handler */
13717 static
13718 SCIP_DECL_CONSLOCK(consLockLinear)
13719 { /*lint --e{715}*/
13720  SCIP_CONSDATA* consdata;
13721  SCIP_Bool haslhs;
13722  SCIP_Bool hasrhs;
13723  int i;
13724 
13725  assert(scip != NULL);
13726  assert(cons != NULL);
13727  consdata = SCIPconsGetData(cons);
13728  assert(consdata != NULL);
13729 
13730  haslhs = !SCIPisInfinity(scip, -consdata->lhs);
13731  hasrhs = !SCIPisInfinity(scip, consdata->rhs);
13732 
13733  /* update rounding locks of every single variable */
13734  for( i = 0; i < consdata->nvars; ++i )
13735  {
13736  if( SCIPisPositive(scip, consdata->vals[i]) )
13737  {
13738  if( haslhs )
13739  {
13740  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
13741  }
13742  if( hasrhs )
13743  {
13744  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksneg, nlockspos) );
13745  }
13746  }
13747  else
13748  {
13749  if( haslhs )
13750  {
13751  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlocksneg, nlockspos) );
13752  }
13753  if( hasrhs )
13754  {
13755  SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos, nlocksneg) );
13756  }
13757  }
13758  }
13759 
13760  return SCIP_OKAY;
13761 }
13762 
13763 
13764 /** variable deletion method of constraint handler */
13765 static
13766 SCIP_DECL_CONSDELVARS(consDelvarsLinear)
13767 {
13768  assert(scip != NULL);
13769  assert(conshdlr != NULL);
13770  assert(conss != NULL || nconss == 0);
13771 
13772  if( nconss > 0 )
13773  {
13774  SCIP_CALL( performVarDeletions(scip, conshdlr, conss, nconss) );
13775  }
13776 
13777  return SCIP_OKAY;
13778 }
13779 
13780 /** constraint display method of constraint handler */
13781 static
13782 SCIP_DECL_CONSPRINT(consPrintLinear)
13783 { /*lint --e{715}*/
13784  assert(scip != NULL);
13785  assert(conshdlr != NULL);
13786  assert(cons != NULL);
13787 
13788  SCIP_CALL( consdataPrint(scip, SCIPconsGetData(cons), file) );
13789 
13790  return SCIP_OKAY;
13791 }
13792 
13793 /** constraint copying method of constraint handler */
13794 static
13795 SCIP_DECL_CONSCOPY(consCopyLinear)
13796 { /*lint --e{715}*/
13797  SCIP_VAR** sourcevars;
13798  SCIP_Real* sourcecoefs;
13799  const char* consname;
13800  int nvars;
13801 
13802  assert(scip != NULL);
13803  assert(sourcescip != NULL);
13804  assert(sourcecons != NULL);
13805 
13806  /* get variables and coefficients of the source constraint */
13807  sourcevars = SCIPgetVarsLinear(sourcescip, sourcecons);
13808  sourcecoefs = SCIPgetValsLinear(sourcescip, sourcecons);
13809  nvars = SCIPgetNVarsLinear(sourcescip, sourcecons);
13810 
13811  if( name != NULL )
13812  consname = name;
13813  else
13814  consname = SCIPconsGetName(sourcecons);
13815 
13816  SCIP_CALL( SCIPcopyConsLinear(scip, cons, sourcescip, consname, nvars, sourcevars, sourcecoefs,
13817  SCIPgetLhsLinear(sourcescip, sourcecons), SCIPgetRhsLinear(sourcescip, sourcecons), varmap, consmap,
13818  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) );
13819  assert(cons != NULL || *valid == FALSE);
13820 
13821  return SCIP_OKAY;
13822 }
13823 
13824 /** constraint parsing method of constraint handler */
13825 static
13826 SCIP_DECL_CONSPARSE(consParseLinear)
13827 { /*lint --e{715}*/
13828  SCIP_VAR** vars;
13829  SCIP_Real* coefs;
13830  int nvars;
13831  int coefssize;
13832  int requsize;
13833  SCIP_Real lhs;
13834  SCIP_Real rhs;
13835  char* endptr;
13836 
13837  assert(scip != NULL);
13838  assert(success != NULL);
13839  assert(str != NULL);
13840  assert(name != NULL);
13841  assert(cons != NULL);
13842 
13843  /* set left and right hand side to their default values */
13844  lhs = -SCIPinfinity(scip);
13845  rhs = SCIPinfinity(scip);
13846 
13847  (*success) = FALSE;
13848 
13849  /* return of string empty */
13850  if( !*str )
13851  return SCIP_OKAY;
13852 
13853  /* ignore whitespace */
13854  while( isspace((unsigned char)*str) )
13855  ++str;
13856 
13857  /* check for left hand side */
13858  if( isdigit((unsigned char)str[0]) || ((str[0] == '-' || str[0] == '+') && isdigit((unsigned char)str[1])) )
13859  {
13860  /* there is a number coming, maybe it is a left-hand-side */
13861  if( !SCIPstrToRealValue(str, &lhs, &endptr) )
13862  {
13863  SCIPerrorMessage("error parsing number from <%s>\n", str);
13864  return SCIP_OKAY;
13865  }
13866 
13867  /* ignore whitespace */
13868  while( isspace((unsigned char)*endptr) )
13869  ++endptr;
13870 
13871  if( endptr[0] != '<' || endptr[1] != '=' )
13872  {
13873  /* no '<=' coming, so it was the first coefficient, but not a left-hand-side */
13874  lhs = -SCIPinfinity(scip);
13875  }
13876  else
13877  {
13878  /* it was indeed a left-hand-side, so continue parsing after it */
13879  str = endptr + 2;
13880 
13881  /* ignore whitespace */
13882  while( isspace((unsigned char)*str) )
13883  ++str;
13884  }
13885  }
13886 
13887  /* initialize buffers for storing the variables and coefficients */
13888  coefssize = 100;
13889  SCIP_CALL( SCIPallocBufferArray(scip, &vars, coefssize) );
13890  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, coefssize) );
13891 
13892  /* parse linear sum to get variables and coefficients */
13893  SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
13894 
13895  if( *success && requsize > coefssize )
13896  {
13897  /* realloc buffers and try again */
13898  coefssize = requsize;
13899  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, coefssize) );
13900  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, coefssize) );
13901 
13902  SCIP_CALL( SCIPparseVarsLinearsum(scip, str, vars, coefs, &nvars, coefssize, &requsize, &endptr, success) );
13903  assert(!*success || requsize <= coefssize); /* if successful, then should have had enough space now */
13904  }
13905 
13906  if( !*success )
13907  {
13908  SCIPerrorMessage("no luck in parsing linear sum '%s'\n", str);
13909  }
13910  else
13911  {
13912  (*success) = FALSE;
13913  str = endptr;
13914 
13915  /* check for left or right hand side */
13916  while( isspace((unsigned char)*str) )
13917  ++str;
13918 
13919  /* check for free constraint */
13920  if( strncmp(str, "[free]", 6) == 0 )
13921  {
13922  if( !SCIPisInfinity(scip, -lhs) )
13923  {
13924  SCIPerrorMessage("cannot have left hand side and [free] status \n");
13925  return SCIP_OKAY;
13926  }
13927  (*success) = TRUE;
13928  }
13929  else
13930  {
13931  switch( *str )
13932  {
13933  case '<':
13934  *success = SCIPstrToRealValue(str+2, &rhs, &endptr);
13935  break;
13936  case '=':
13937  if( !SCIPisInfinity(scip, -lhs) )
13938  {
13939  SCIPerrorMessage("cannot have == on rhs if there was a <= on lhs\n");
13940  return SCIP_OKAY;
13941  }
13942  else
13943  {
13944  *success = SCIPstrToRealValue(str+2, &rhs, &endptr);
13945  lhs = rhs;
13946  }
13947  break;
13948  case '>':
13949  if( !SCIPisInfinity(scip, -lhs) )
13950  {
13951  SCIPerrorMessage("cannot have => on rhs if there was a <= on lhs\n");
13952  return SCIP_OKAY;
13953  }
13954  else
13955  {
13956  *success = SCIPstrToRealValue(str+2, &lhs, &endptr);
13957  break;
13958  }
13959  case '\0':
13960  *success = TRUE;
13961  break;
13962  default:
13963  SCIPerrorMessage("unexpected character %c\n", *str);
13964  return SCIP_OKAY;
13965  }
13966  }
13967 
13968  if( *success )
13969  {
13970  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
13971  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
13972  }
13973  }
13974 
13975  SCIPfreeBufferArray(scip, &coefs);
13976  SCIPfreeBufferArray(scip, &vars);
13977 
13978  return SCIP_OKAY;
13979 }
13980 
13981 
13982 /** constraint method of constraint handler which returns the variables (if possible) */
13983 static
13984 SCIP_DECL_CONSGETVARS(consGetVarsLinear)
13985 { /*lint --e{715}*/
13986  SCIP_CONSDATA* consdata;
13987 
13988  consdata = SCIPconsGetData(cons);
13989  assert(consdata != NULL);
13990 
13991  if( varssize < consdata->nvars )
13992  (*success) = FALSE;
13993  else
13994  {
13995  assert(vars != NULL);
13996 
13997  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
13998  (*success) = TRUE;
13999  }
14000 
14001  return SCIP_OKAY;
14002 }
14003 
14004 /** constraint method of constraint handler which returns the number of variables (if possible) */
14005 static
14006 SCIP_DECL_CONSGETNVARS(consGetNVarsLinear)
14007 { /*lint --e{715}*/
14008  SCIP_CONSDATA* consdata;
14009 
14010  consdata = SCIPconsGetData(cons);
14011  assert(consdata != NULL);
14012 
14013  (*nvars) = consdata->nvars;
14014  (*success) = TRUE;
14015 
14016  return SCIP_OKAY;
14017 }
14018 
14019 /*
14020  * Callback methods of event handler
14021  */
14022 
14023 static
14024 SCIP_DECL_EVENTEXEC(eventExecLinear)
14025 { /*lint --e{715}*/
14026  SCIP_CONS* cons;
14027  SCIP_CONSDATA* consdata;
14028  SCIP_VAR* var;
14029  SCIP_EVENTTYPE eventtype;
14030 
14031  assert(scip != NULL);
14032  assert(eventhdlr != NULL);
14033  assert(eventdata != NULL);
14034  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
14035  assert(event != NULL);
14036 
14037  cons = eventdata->cons;
14038  assert(cons != NULL);
14039  consdata = SCIPconsGetData(cons);
14040  assert(consdata != NULL);
14041 
14042  eventtype = SCIPeventGetType(event);
14043  var = SCIPeventGetVar(event);
14044 
14045  if( (eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) != 0 )
14046  {
14047  SCIP_Real oldbound;
14048  SCIP_Real newbound;
14049  SCIP_Real val;
14050  int varpos;
14051 
14052  varpos = eventdata->varpos;
14053  assert(0 <= varpos && varpos < consdata->nvars);
14054  oldbound = SCIPeventGetOldbound(event);
14055  newbound = SCIPeventGetNewbound(event);
14056  assert(var != NULL);
14057  assert(consdata->vars[varpos] == var);
14058  val = consdata->vals[varpos];
14059 
14060  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
14061  consdata->maxactdelta = SCIP_INVALID;
14062 
14063  /* update the activity values */
14064  if( (eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
14065  consdataUpdateActivitiesLb(scip, consdata, var, oldbound, newbound, val, TRUE);
14066  else
14067  {
14068  assert((eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0);
14069  consdataUpdateActivitiesUb(scip, consdata, var, oldbound, newbound, val, TRUE);
14070  }
14071 
14072  consdata->presolved = FALSE;
14073 
14074  /* bound change can turn the constraint infeasible or redundant only if it was a tightening */
14075  if( (eventtype & SCIP_EVENTTYPE_BOUNDTIGHTENED) != 0 )
14076  {
14077  consdata->propagated = FALSE;
14078  SCIP_CALL( SCIPmarkConsPropagate(scip, cons) );
14079  }
14080 
14081  /* check whether bound tightening might now be successful (if the current bound was relaxed, it might be
14082  * that it can be tightened again)
14083  */
14084  if( consdata->boundstightened )
14085  {
14086  switch( eventtype )
14087  {
14090  consdata->boundstightened = (val > 0.0 && SCIPisInfinity(scip, consdata->rhs))
14091  || (val < 0.0 && SCIPisInfinity(scip, -consdata->lhs));
14092  break;
14095  consdata->boundstightened = (val > 0.0 && SCIPisInfinity(scip, -consdata->lhs))
14096  || (val < 0.0 && SCIPisInfinity(scip, consdata->rhs));
14097  break;
14098  default:
14099  SCIPerrorMessage("invalid event type %d\n", eventtype);
14100  return SCIP_INVALIDDATA;
14101  }
14102  }
14103  }
14104  else if( (eventtype & SCIP_EVENTTYPE_VARFIXED) != 0 )
14105  {
14106  /* we want to remove the fixed variable */
14107  consdata->presolved = FALSE;
14108  consdata->removedfixings = FALSE;
14109 
14110  /* reset maximal activity delta, so that it will be recalculated on the next real propagation */
14111  consdata->maxactdelta = SCIP_INVALID;
14112  }
14113 
14114  else if( (eventtype & SCIP_EVENTTYPE_VARUNLOCKED) != 0 )
14115  {
14116  /* there is only one lock left: we may multi-aggregate the variable as slack of an equation */
14117  assert(SCIPvarGetNLocksDown(var) <= 1);
14118  assert(SCIPvarGetNLocksUp(var) <= 1);
14119  consdata->presolved = FALSE;
14120  }
14121  else if( (eventtype & SCIP_EVENTTYPE_GBDCHANGED) != 0 )
14122  {
14123  SCIP_Real oldbound;
14124  SCIP_Real newbound;
14125  SCIP_Real val;
14126  int varpos;
14127 
14128  varpos = eventdata->varpos;
14129  assert(0 <= varpos && varpos < consdata->nvars);
14130  oldbound = SCIPeventGetOldbound(event);
14131  newbound = SCIPeventGetNewbound(event);
14132  assert(var != NULL);
14133  assert(consdata->vars[varpos] == var);
14134  val = consdata->vals[varpos];
14135 
14136  /* update the activity values */
14137  if( (eventtype & SCIP_EVENTTYPE_GLBCHANGED) != 0 )
14138  consdataUpdateActivitiesGlbLb(scip, consdata, oldbound, newbound, val, TRUE);
14139  else
14140  {
14141  assert((eventtype & SCIP_EVENTTYPE_GUBCHANGED) != 0);
14142  consdataUpdateActivitiesGlbUb(scip, consdata, oldbound, newbound, val, TRUE);
14143  }
14144  }
14145  else
14146  {
14147  assert((eventtype & SCIP_EVENTTYPE_VARDELETED) != 0);
14148  consdata->varsdeleted = TRUE;
14149  }
14150 
14151  return SCIP_OKAY;
14152 }
14153 
14154 
14155 /*
14156  * Callback methods of conflict handler
14157  */
14158 
14159 static
14160 SCIP_DECL_CONFLICTEXEC(conflictExecLinear)
14161 { /*lint --e{715}*/
14162  SCIP_VAR** vars;
14163  SCIP_Real* vals;
14164  SCIP_Real lhs;
14165  int i;
14166 
14167  assert(scip != NULL);
14168  assert(conflicthdlr != NULL);
14169  assert(strcmp(SCIPconflicthdlrGetName(conflicthdlr), CONFLICTHDLR_NAME) == 0);
14170  assert(bdchginfos != NULL || nbdchginfos == 0);
14171  assert(result != NULL);
14172 
14173  /* don't process already resolved conflicts */
14174  if( resolved )
14175  {
14176  *result = SCIP_DIDNOTRUN;
14177  return SCIP_OKAY;
14178  }
14179 
14180  *result = SCIP_DIDNOTFIND;
14181 
14182  /* create array of variables and coefficients: sum_{i \in P} x_i - sum_{i \in N} x_i >= 1 - |N| */
14183  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nbdchginfos) );
14184  SCIP_CALL( SCIPallocBufferArray(scip, &vals, nbdchginfos) );
14185  lhs = 1.0;
14186  for( i = 0; i < nbdchginfos; ++i )
14187  {
14188  assert(bdchginfos != NULL);
14189 
14190  vars[i] = SCIPbdchginfoGetVar(bdchginfos[i]);
14191 
14192  /* we can only treat binary variables */
14193  /**@todo extend linear conflict constraints to some non-binary cases */
14194  if( !SCIPvarIsBinary(vars[i]) )
14195  break;
14196 
14197  /* check whether the variable is fixed to zero (P) or one (N) in the conflict set */
14198  if( SCIPbdchginfoGetNewbound(bdchginfos[i]) < 0.5 )
14199  vals[i] = 1.0;
14200  else
14201  {
14202  vals[i] = -1.0;
14203  lhs -= 1.0;
14204  }
14205  }
14206 
14207  if( i == nbdchginfos )
14208  {
14209  SCIP_CONS* cons;
14210  SCIP_CONS* upgdcons;
14211  char consname[SCIP_MAXSTRLEN];
14212 
14213  /* create a constraint out of the conflict set */
14214  (void) SCIPsnprintf(consname, SCIP_MAXSTRLEN, "cf%"SCIP_LONGINT_FORMAT, SCIPgetNConflictConssApplied(scip));
14215  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, consname, nbdchginfos, vars, vals, lhs, SCIPinfinity(scip),
14216  FALSE, separate, FALSE, FALSE, TRUE, local, FALSE, dynamic, removable, FALSE) );
14217 
14218  /* try to automatically convert a linear constraint into a more specific and more specialized constraint */
14219  SCIP_CALL( SCIPupgradeConsLinear(scip, cons, &upgdcons) );
14220  if( upgdcons != NULL )
14221  {
14222  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
14223  cons = upgdcons;
14224  }
14225 
14226  /* add constraint to SCIP */
14227  SCIP_CALL( SCIPaddConsNode(scip, node, cons, validnode) );
14228  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
14229 
14230  *result = SCIP_CONSADDED;
14231  }
14232 
14233  /* free temporary memory */
14234  SCIPfreeBufferArray(scip, &vals);
14235  SCIPfreeBufferArray(scip, &vars);
14236 
14237  return SCIP_OKAY;
14238 }
14239 
14240 
14241 /*
14242  * Quadratic constraint upgrading
14243  */
14244 
14245 
14246 /** upgrades quadratic constraints with only and at least one linear variables into a linear constraint
14247  */
14248 static
14249 SCIP_DECL_QUADCONSUPGD(upgradeConsQuadratic)
14250 { /*lint --e{715}*/
14251  assert(scip != NULL);
14252  assert(cons != NULL);
14253  assert(nupgdconss != NULL);
14254  assert(upgdconss != NULL);
14255 
14256  *nupgdconss = 0;
14257 
14258  SCIPdebugMessage("upgradeConsQuadratic called for constraint <%s>\n", SCIPconsGetName(cons));
14259  SCIPdebugPrintCons(scip, cons, NULL);
14260 
14261  if( SCIPgetNQuadVarTermsQuadratic(scip, cons) > 0 )
14262  return SCIP_OKAY;
14263  if( SCIPgetNLinearVarsQuadratic(scip, cons) == 0 )
14264  return SCIP_OKAY;
14265 
14266  if( upgdconsssize < 1 )
14267  {
14268  /* signal that we need more memory */
14269  *nupgdconss = -1;
14270  return SCIP_OKAY;
14271  }
14272 
14273  *nupgdconss = 1;
14274  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
14275  SCIPgetNLinearVarsQuadratic(scip, cons),
14276  SCIPgetLinearVarsQuadratic(scip, cons),
14277  SCIPgetCoefsLinearVarsQuadratic(scip, cons),
14278  SCIPgetLhsQuadratic(scip, cons), SCIPgetRhsQuadratic(scip, cons),
14282  SCIPconsIsStickingAtNode(cons)) );
14283  SCIPdebugMessage("created linear constraint:\n");
14284  SCIPdebugPrintCons(scip, upgdconss[0], NULL);
14285 
14286  return SCIP_OKAY;
14287 }
14288 
14289 /** tries to upgrade a nonlinear constraint into a linear constraint */
14290 static
14291 SCIP_DECL_NONLINCONSUPGD(upgradeConsNonlinear)
14292 {
14293  assert(nupgdconss != NULL);
14294  assert(upgdconss != NULL);
14295 
14296  *nupgdconss = 0;
14297 
14298  /* no interest in nonlinear constraints */
14299  if( SCIPgetExprgraphNodeNonlinear(scip, cons) != NULL )
14300  return SCIP_OKAY;
14301 
14302  /* no interest in constant constraints */
14303  if( SCIPgetNLinearVarsNonlinear(scip, cons) == 0 )
14304  return SCIP_OKAY;
14305 
14306  if( upgdconsssize < 1 )
14307  {
14308  /* request larger upgdconss array */
14309  *nupgdconss = -1;
14310  return SCIP_OKAY;
14311  }
14312 
14313  *nupgdconss = 1;
14314  SCIP_CALL( SCIPcreateConsLinear(scip, &upgdconss[0], SCIPconsGetName(cons),
14316  SCIPgetLhsNonlinear(scip, cons), SCIPgetRhsNonlinear(scip, cons),
14320  SCIPconsIsStickingAtNode(cons)) );
14321 
14322  return SCIP_OKAY;
14323 }
14324 
14325 /*
14326  * constraint specific interface methods
14327  */
14328 
14329 /** creates the handler for linear constraints and includes it in SCIP */
14331  SCIP* scip /**< SCIP data structure */
14332  )
14333 {
14334  SCIP_CONSHDLRDATA* conshdlrdata;
14335  SCIP_CONSHDLR* conshdlr;
14336  SCIP_EVENTHDLR* eventhdlr;
14337  SCIP_CONFLICTHDLR* conflicthdlr;
14338 
14339  assert(scip != NULL);
14340 
14341  /* create event handler for bound change events */
14343  eventExecLinear, NULL) );
14344 
14345  /* create conflict handler for linear constraints */
14347  conflictExecLinear, NULL) );
14348 
14349  /* create constraint handler data */
14350  SCIP_CALL( conshdlrdataCreate(scip, &conshdlrdata, eventhdlr) );
14351 
14352  /* include constraint handler */
14355  consEnfolpLinear, consEnfopsLinear, consCheckLinear, consLockLinear,
14356  conshdlrdata) );
14357 
14358  assert(conshdlr != NULL);
14359 
14360  /* set non-fundamental callbacks via specific setter functions */
14361  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLinear, consCopyLinear) );
14362  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLinear) );
14363  SCIP_CALL( SCIPsetConshdlrDelvars(scip, conshdlr, consDelvarsLinear) );
14364  SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLinear) );
14365  SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreLinear) );
14366  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolLinear) );
14367  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeLinear) );
14368  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsLinear) );
14369  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsLinear) );
14370  SCIP_CALL( SCIPsetConshdlrInit(scip, conshdlr, consInitLinear) );
14371  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLinear) );
14372 #ifdef WITH_PRINTORIGCONSTYPES
14373  SCIP_CALL( SCIPsetConshdlrInitpre(scip, conshdlr, consInitpreLinear) );
14374 #endif
14375  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseLinear) );
14376  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinear, CONSHDLR_MAXPREROUNDS, CONSHDLR_DELAYPRESOL) );
14377  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLinear) );
14378  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinear, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
14380  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLinear) );
14381  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinear, consSepasolLinear, CONSHDLR_SEPAFREQ,
14383  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLinear) );
14384 
14385  if( SCIPfindConshdlr(scip, "quadratic") != NULL )
14386  {
14387  /* include function that upgrades quadratic constraint to linear constraints */
14389  }
14390 
14391  if( SCIPfindConshdlr(scip, "nonlinear") != NULL )
14392  {
14393  /* include the linear constraint upgrade in the nonlinear constraint handler */
14395  }
14396 
14397  /* add linear constraint handler parameters */
14398  SCIP_CALL( SCIPaddIntParam(scip,
14399  "constraints/"CONSHDLR_NAME"/tightenboundsfreq",
14400  "multiplier on propagation frequency, how often the bounds are tightened (-1: never, 0: only at root)",
14401  &conshdlrdata->tightenboundsfreq, TRUE, DEFAULT_TIGHTENBOUNDSFREQ, -1, INT_MAX, NULL, NULL) );
14402  SCIP_CALL( SCIPaddIntParam(scip,
14403  "constraints/"CONSHDLR_NAME"/maxrounds",
14404  "maximal number of separation rounds per node (-1: unlimited)",
14405  &conshdlrdata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
14406  SCIP_CALL( SCIPaddIntParam(scip,
14407  "constraints/"CONSHDLR_NAME"/maxroundsroot",
14408  "maximal number of separation rounds per node in the root node (-1: unlimited)",
14409  &conshdlrdata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
14410  SCIP_CALL( SCIPaddIntParam(scip,
14411  "constraints/"CONSHDLR_NAME"/maxsepacuts",
14412  "maximal number of cuts separated per separation round",
14413  &conshdlrdata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
14414  SCIP_CALL( SCIPaddIntParam(scip,
14415  "constraints/"CONSHDLR_NAME"/maxsepacutsroot",
14416  "maximal number of cuts separated per separation round in the root node",
14417  &conshdlrdata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
14419  "constraints/"CONSHDLR_NAME"/presolpairwise",
14420  "should pairwise constraint comparison be performed in presolving?",
14421  &conshdlrdata->presolpairwise, TRUE, DEFAULT_PRESOLPAIRWISE, NULL, NULL) );
14423  "constraints/"CONSHDLR_NAME"/presolusehashing",
14424  "should hash table be used for detecting redundant constraints in advance",
14425  &conshdlrdata->presolusehashing, TRUE, DEFAULT_PRESOLUSEHASHING, NULL, NULL) );
14426  SCIP_CALL( SCIPaddIntParam(scip,
14427  "constraints/"CONSHDLR_NAME"/nmincomparisons",
14428  "number for minimal pairwise presolve comparisons",
14429  &conshdlrdata->nmincomparisons, TRUE, DEFAULT_NMINCOMPARISONS, 1, INT_MAX, NULL, NULL) );
14431  "constraints/"CONSHDLR_NAME"/mingainpernmincomparisons",
14432  "minimal gain per minimal pairwise presolve comparisons to repeat pairwise comparison round",
14433  &conshdlrdata->mingainpernmincomp, TRUE, DEFAULT_MINGAINPERNMINCOMP, 0.0, 1.0, NULL, NULL) );
14435  "constraints/"CONSHDLR_NAME"/maxaggrnormscale",
14436  "maximal allowed relative gain in maximum norm for constraint aggregation (0.0: disable constraint aggregation)",
14437  &conshdlrdata->maxaggrnormscale, TRUE, DEFAULT_MAXAGGRNORMSCALE, 0.0, SCIP_REAL_MAX, NULL, NULL) );
14439  "constraints/"CONSHDLR_NAME"/maxcardbounddist",
14440  "maximal relative distance from current node's dual bound to primal bound compared to best node's dual bound for separating knapsack cardinality cuts",
14441  &conshdlrdata->maxcardbounddist, TRUE, DEFAULT_MAXCARDBOUNDDIST, 0.0, 1.0, NULL, NULL) );
14443  "constraints/"CONSHDLR_NAME"/separateall",
14444  "should all constraints be subject to cardinality cut generation instead of only the ones with non-zero dual value?",
14445  &conshdlrdata->separateall, FALSE, DEFAULT_SEPARATEALL, NULL, NULL) );
14447  "constraints/"CONSHDLR_NAME"/aggregatevariables",
14448  "should presolving search for aggregations in equations",
14449  &conshdlrdata->aggregatevariables, TRUE, DEFAULT_AGGREGATEVARIABLES, NULL, NULL) );
14451  "constraints/"CONSHDLR_NAME"/simplifyinequalities",
14452  "should presolving try to simplify inequalities",
14453  &conshdlrdata->simplifyinequalities, TRUE, DEFAULT_SIMPLIFYINEQUALITIES, NULL, NULL) );
14455  "constraints/"CONSHDLR_NAME"/dualpresolving",
14456  "should dual presolving steps be performed?",
14457  &conshdlrdata->dualpresolving, TRUE, DEFAULT_DUALPRESOLVING, NULL, NULL) );
14459  "constraints/"CONSHDLR_NAME"/sortvars", "apply binaries sorting in decr. order of coeff abs value?",
14460  &conshdlrdata->sortvars, TRUE, DEFAULT_SORTVARS, NULL, NULL) );
14462  "constraints/"CONSHDLR_NAME"/checkrelmaxabs",
14463  "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)?",
14464  &conshdlrdata->checkrelmaxabs, TRUE, DEFAULT_CHECKRELMAXABS, NULL, NULL) );
14466  "constraints/"CONSHDLR_NAME"/detectcutoffbound",
14467  "should presolving try to detect constraints parallel to the objective function defining an upper bound and prevent these constraints from entering the LP?",
14468  &conshdlrdata->detectcutoffbound, TRUE, DEFAULT_DETECTCUTOFFBOUND, NULL, NULL) );
14470  "constraints/"CONSHDLR_NAME"/detectlowerbound",
14471  "should presolving try to detect constraints parallel to the objective function defining a lower bound and prevent these constraints from entering the LP?",
14472  &conshdlrdata->detectlowerbound, TRUE, DEFAULT_DETECTLOWERBOUND, NULL, NULL) );
14474  "constraints/"CONSHDLR_NAME"/detectpartialobjective",
14475  "should presolving try to detect subsets of constraints parallel to the objective function?",
14476  &conshdlrdata->detectpartialobjective, TRUE, DEFAULT_DETECTPARTIALOBJECTIVE, NULL, NULL) );
14477 
14478  return SCIP_OKAY;
14479 }
14480 
14481 /** includes a linear constraint update method into the linear constraint handler */
14483  SCIP* scip, /**< SCIP data structure */
14484  SCIP_DECL_LINCONSUPGD((*linconsupgd)), /**< method to call for upgrading linear constraint */
14485  int priority, /**< priority of upgrading method */
14486  const char* conshdlrname /**< name of the constraint handler */
14487  )
14488 {
14489  SCIP_CONSHDLR* conshdlr;
14490  SCIP_CONSHDLRDATA* conshdlrdata;
14491  SCIP_LINCONSUPGRADE* linconsupgrade;
14492  char paramname[SCIP_MAXSTRLEN];
14493  char paramdesc[SCIP_MAXSTRLEN];
14494 
14495  assert(scip != NULL);
14496  assert(linconsupgd != NULL);
14497  assert(conshdlrname != NULL );
14498 
14499  /* find the linear constraint handler */
14500  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
14501  if( conshdlr == NULL )
14502  {
14503  SCIPerrorMessage("linear constraint handler not found\n");
14504  return SCIP_PLUGINNOTFOUND;
14505  }
14506 
14507  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14508  assert(conshdlrdata != NULL);
14509 
14510  /* check if linear constraint update method already exists in constraint handler data */
14511  if( !conshdlrdataHasUpgrade(scip, conshdlrdata, linconsupgd, conshdlrname) )
14512  {
14513  /* create a linear constraint upgrade data object */
14514  SCIP_CALL( linconsupgradeCreate(scip, &linconsupgrade, linconsupgd, priority) );
14515 
14516  /* insert linear constraint update method into constraint handler data */
14517  SCIP_CALL( conshdlrdataIncludeUpgrade(scip, conshdlrdata, linconsupgrade) );
14518 
14519  /* adds parameter to turn on and off the upgrading step */
14520  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/linear/upgrade/%s", conshdlrname);
14521  (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "enable linear upgrading for constraint handler <%s>", conshdlrname);
14523  paramname, paramdesc,
14524  &linconsupgrade->active, FALSE, TRUE, NULL, NULL) );
14525  }
14526 
14527  return SCIP_OKAY;
14528 }
14529 
14530 /** creates and captures a linear constraint
14531  *
14532  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
14533  */
14535  SCIP* scip, /**< SCIP data structure */
14536  SCIP_CONS** cons, /**< pointer to hold the created constraint */
14537  const char* name, /**< name of constraint */
14538  int nvars, /**< number of nonzeros in the constraint */
14539  SCIP_VAR** vars, /**< array with variables of constraint entries */
14540  SCIP_Real* vals, /**< array with coefficients of constraint entries */
14541  SCIP_Real lhs, /**< left hand side of constraint */
14542  SCIP_Real rhs, /**< right hand side of constraint */
14543  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
14544  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
14545  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
14546  * Usually set to TRUE. */
14547  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
14548  * TRUE for model constraints, FALSE for additional, redundant constraints. */
14549  SCIP_Bool check, /**< should the constraint be checked for feasibility?
14550  * TRUE for model constraints, FALSE for additional, redundant constraints. */
14551  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
14552  * Usually set to TRUE. */
14553  SCIP_Bool local, /**< is constraint only valid locally?
14554  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
14555  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
14556  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
14557  * adds coefficients to this constraint. */
14558  SCIP_Bool dynamic, /**< Is constraint subject to aging?
14559  * Usually set to FALSE. Set to TRUE for own cuts which
14560  * are separated as constraints. */
14561  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
14562  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
14563  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
14564  * if it may be moved to a more global node?
14565  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
14566  )
14567 {
14568  SCIP_CONSHDLRDATA* conshdlrdata;
14569  SCIP_CONSHDLR* conshdlr;
14570  SCIP_CONSDATA* consdata;
14571 
14572  assert(scip != NULL);
14573  assert(cons != NULL);
14574 
14575  /* find the linear constraint handler */
14576  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
14577  if( conshdlr == NULL )
14578  {
14579  SCIPerrorMessage("linear constraint handler not found\n");
14580  return SCIP_PLUGINNOTFOUND;
14581  }
14582 
14583  /* get event handler */
14584  conshdlrdata = SCIPconshdlrGetData(conshdlr);
14585  assert(conshdlrdata != NULL);
14586  assert(conshdlrdata->eventhdlr != NULL);
14587 
14588  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
14589  * constraint after presolving we have to ensure that it holds active variables
14590  */
14591  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE && nvars > 0 )
14592  {
14593  SCIP_VAR** consvars;
14594  SCIP_Real* consvals;
14595  SCIP_Real constant = 0.0;
14596  int nconsvars;
14597  int requiredsize;
14598 
14599  nconsvars = nvars;
14600  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvars, vars, nconsvars) );
14601  SCIP_CALL( SCIPduplicateBufferArray(scip, &consvals, vals, nconsvars) );
14602 
14603  /* get active variables for new constraint */
14604  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
14605 
14606  /* if space was not enough we need to resize the buffers */
14607  if( requiredsize > nconsvars )
14608  {
14609  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
14610  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
14611 
14612  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
14613  assert(requiredsize <= nconsvars);
14614  }
14615 
14616  /* adjust sides and check that we do not subtract infinity values */
14617  if( SCIPisInfinity(scip, REALABS(constant)) )
14618  {
14619  if( constant < 0.0 )
14620  {
14621  if( SCIPisInfinity(scip, lhs) )
14622  {
14623  SCIPfreeBufferArray(scip, &consvals);
14624  SCIPfreeBufferArray(scip, &consvars);
14625 
14626  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);
14627 
14628  SCIPABORT();
14629  return SCIP_INVALIDDATA; /*lint !e527*/
14630  }
14631  if( SCIPisInfinity(scip, rhs) )
14632  {
14633  SCIPfreeBufferArray(scip, &consvals);
14634  SCIPfreeBufferArray(scip, &consvars);
14635 
14636  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);
14637 
14638  SCIPABORT();
14639  return SCIP_INVALIDDATA; /*lint !e527*/
14640  }
14641 
14642  lhs = -SCIPinfinity(scip);
14643  rhs = -SCIPinfinity(scip);
14644  }
14645  else
14646  {
14647  if( SCIPisInfinity(scip, -lhs) )
14648  {
14649  SCIPfreeBufferArray(scip, &consvals);
14650  SCIPfreeBufferArray(scip, &consvars);
14651 
14652  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);
14653 
14654  SCIPABORT();
14655  return SCIP_INVALIDDATA; /*lint !e527*/
14656  }
14657  if( SCIPisInfinity(scip, -rhs) )
14658  {
14659  SCIPfreeBufferArray(scip, &consvals);
14660  SCIPfreeBufferArray(scip, &consvars);
14661 
14662  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);
14663 
14664  SCIPABORT();
14665  return SCIP_INVALIDDATA; /*lint !e527*/
14666  }
14667 
14668  lhs = SCIPinfinity(scip);
14669  rhs = SCIPinfinity(scip);
14670  }
14671  }
14672  else
14673  {
14674  if( !SCIPisInfinity(scip, REALABS(lhs)) )
14675  lhs -= constant;
14676  if( !SCIPisInfinity(scip, REALABS(rhs)) )
14677  rhs -= constant;
14678 
14679  if( SCIPisInfinity(scip, -lhs) )
14680  lhs = -SCIPinfinity(scip);
14681  else if( SCIPisInfinity(scip, lhs) )
14682  lhs = SCIPinfinity(scip);
14683 
14684  if( SCIPisInfinity(scip, rhs) )
14685  rhs = SCIPinfinity(scip);
14686  else if( SCIPisInfinity(scip, -rhs) )
14687  rhs = -SCIPinfinity(scip);
14688  }
14689 
14690  /* create constraint data */
14691  SCIP_CALL( consdataCreate(scip, &consdata, nconsvars, consvars, consvals, lhs, rhs) );
14692  assert(consdata != NULL);
14693 
14694  SCIPfreeBufferArray(scip, &consvals);
14695  SCIPfreeBufferArray(scip, &consvars);
14696  }
14697  else
14698  {
14699  /* create constraint data */
14700  SCIP_CALL( consdataCreate(scip, &consdata, nvars, vars, vals, lhs, rhs) );
14701  assert(consdata != NULL);
14702  }
14703 
14704  /* create constraint */
14705  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
14706  local, modifiable, dynamic, removable, stickingatnode) );
14707 
14708  if( SCIPisTransformed(scip) && needEvents(scip) )
14709  {
14710  /* catch bound change events of variables */
14711  SCIP_CALL( consCatchAllEvents(scip, *cons, conshdlrdata->eventhdlr) );
14712  assert(consdata->eventdatas != NULL);
14713  }
14714 
14715  return SCIP_OKAY;
14716 }
14717 
14718 /** creates and captures a linear constraint
14719  * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
14720  * method SCIPcreateConsLinear(); all flags can be set via SCIPsetConsFLAGNAME-methods in scip.h
14721  *
14722  * @see SCIPcreateConsLinear() for information about the basic constraint flag configuration
14723  *
14724  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
14725  */
14727  SCIP* scip, /**< SCIP data structure */
14728  SCIP_CONS** cons, /**< pointer to hold the created constraint */
14729  const char* name, /**< name of constraint */
14730  int nvars, /**< number of nonzeros in the constraint */
14731  SCIP_VAR** vars, /**< array with variables of constraint entries */
14732  SCIP_Real* vals, /**< array with coefficients of constraint entries */
14733  SCIP_Real lhs, /**< left hand side of constraint */
14734  SCIP_Real rhs /**< right hand side of constraint */
14735  )
14736 {
14737  assert(scip != NULL);
14738 
14739  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, vals, lhs, rhs,
14740  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
14741 
14742  return SCIP_OKAY;
14743 }
14744 
14745 /** creates by copying and captures a linear constraint */
14747  SCIP* scip, /**< target SCIP data structure */
14748  SCIP_CONS** cons, /**< pointer to store the created target constraint */
14749  SCIP* sourcescip, /**< source SCIP data structure */
14750  const char* name, /**< name of constraint */
14751  int nvars, /**< number of variables in source variable array */
14752  SCIP_VAR** sourcevars, /**< source variables of the linear constraints */
14753  SCIP_Real* sourcecoefs, /**< coefficient array of the linear constraint, or NULL if all coefficients are one */
14754  SCIP_Real lhs, /**< left hand side of the linear constraint */
14755  SCIP_Real rhs, /**< right hand side of the linear constraint */
14756  SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding
14757  * variables of the target SCIP */
14758  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
14759  * target constraints */
14760  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
14761  SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
14762  SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
14763  SCIP_Bool check, /**< should the constraint be checked for feasibility? */
14764  SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
14765  SCIP_Bool local, /**< is constraint only valid locally? */
14766  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
14767  SCIP_Bool dynamic, /**< is constraint subject to aging? */
14768  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
14769  SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even
14770  * if it may be moved to a more global node? */
14771  SCIP_Bool global, /**< create a global or a local copy? */
14772  SCIP_Bool* valid /**< pointer to store if the copying was valid */
14773  )
14774 {
14775  SCIP_VAR** vars;
14776  SCIP_Real* coefs;
14777 
14778  SCIP_Real constant;
14779  int requiredsize;
14780  int v;
14781 
14782  if( SCIPisGT(scip, lhs, rhs) )
14783  {
14784  *valid = FALSE;
14785  return SCIP_OKAY;
14786  }
14787 
14788  (*valid) = TRUE;
14789 
14790  if( nvars == 0 )
14791  {
14792  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, 0, NULL, NULL, lhs, rhs,
14793  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
14794  return SCIP_OKAY;
14795  }
14796 
14797  /* duplicate variable array */
14798  SCIP_CALL( SCIPduplicateBufferArray(scip, &vars, sourcevars, nvars) );
14799 
14800  /* duplicate coefficient array */
14801  if( sourcecoefs != NULL )
14802  {
14803  SCIP_CALL( SCIPduplicateBufferArray(scip, &coefs, sourcecoefs, nvars) );
14804  }
14805  else
14806  {
14807  SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nvars) );
14808  for( v = 0; v < nvars; ++v )
14809  coefs[v] = 1.0;
14810  }
14811 
14812  constant = 0.0;
14813 
14814  /* transform source variable to active variables of the source SCIP since only these can be mapped to variables of
14815  * the target SCIP
14816  */
14817  if( !SCIPvarIsOriginal(vars[0]) )
14818  {
14819  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, nvars, &constant, &requiredsize, TRUE) );
14820 
14821  if( requiredsize > nvars )
14822  {
14823  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, requiredsize) );
14824  SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requiredsize) );
14825 
14826  SCIP_CALL( SCIPgetProbvarLinearSum(sourcescip, vars, coefs, &nvars, requiredsize, &constant, &requiredsize, TRUE) );
14827  assert(requiredsize <= nvars);
14828  }
14829  }
14830  else
14831  {
14832  for( v = 0; v < nvars; ++v )
14833  {
14834  assert(SCIPvarIsOriginal(vars[v]));
14835  SCIP_CALL( SCIPvarGetOrigvarSum(&vars[v], &coefs[v], &constant) );
14836  assert(vars[v] != NULL);
14837  }
14838  }
14839 
14840  /* map variables of the source constraint to variables of the target SCIP */
14841  for( v = 0; v < nvars && *valid; ++v )
14842  {
14843  SCIP_VAR* var;
14844  var = vars[v];
14845 
14846  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, var, &vars[v], varmap, consmap, global, valid) );
14847  assert(!(*valid) || vars[v] != NULL);
14848  }
14849 
14850  /* only create the target constraint, if all variables could be copied */
14851  if( *valid )
14852  {
14853  if( !SCIPisInfinity(scip, -lhs) )
14854  lhs -= constant;
14855 
14856  if( !SCIPisInfinity(scip, rhs) )
14857  rhs -= constant;
14858 
14859  SCIP_CALL( SCIPcreateConsLinear(scip, cons, name, nvars, vars, coefs, lhs, rhs,
14860  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
14861  }
14862 
14863  /* free buffer array */
14864  SCIPfreeBufferArray(scip, &coefs);
14865  SCIPfreeBufferArray(scip, &vars);
14866 
14867  return SCIP_OKAY;
14868 }
14869 
14870 /** adds coefficient to linear constraint (if it is not zero) */
14872  SCIP* scip, /**< SCIP data structure */
14873  SCIP_CONS* cons, /**< constraint data */
14874  SCIP_VAR* var, /**< variable of constraint entry */
14875  SCIP_Real val /**< coefficient of constraint entry */
14876  )
14877 {
14878  assert(scip != NULL);
14879  assert(cons != NULL);
14880  assert(var != NULL);
14881 
14882  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
14883  {
14884  SCIPerrorMessage("constraint is not linear\n");
14885  return SCIP_INVALIDDATA;
14886  }
14887 
14888  /* for the solving process we need linear rows, containing only active variables; therefore when creating a linear
14889  * constraint after presolving we have to ensure that it holds active variables
14890  */
14891  if( SCIPgetStage(scip) >= SCIP_STAGE_EXITPRESOLVE )
14892  {
14893  SCIP_CONSDATA* consdata;
14894  SCIP_VAR** consvars;
14895  SCIP_Real* consvals;
14896  SCIP_Real constant = 0.0;
14897  SCIP_Real rhs;
14898  SCIP_Real lhs;
14899  int nconsvars;
14900  int requiredsize;
14901  int v;
14902 
14903  nconsvars = 1;
14904  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nconsvars) );
14905  SCIP_CALL( SCIPallocBufferArray(scip, &consvals, nconsvars) );
14906  consvars[0] = var;
14907  consvals[0] = val;
14908 
14909  /* get active variables for new constraint */
14910  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, nconsvars, &constant, &requiredsize, TRUE) );
14911 
14912  /* if space was not enough we need to resize the buffers */
14913  if( requiredsize > nconsvars )
14914  {
14915  SCIP_CALL( SCIPreallocBufferArray(scip, &consvars, requiredsize) );
14916  SCIP_CALL( SCIPreallocBufferArray(scip, &consvals, requiredsize) );
14917 
14918  SCIP_CALL( SCIPgetProbvarLinearSum(scip, consvars, consvals, &nconsvars, requiredsize, &constant, &requiredsize, TRUE) );
14919  assert(requiredsize <= nconsvars);
14920  }
14921 
14922  consdata = SCIPconsGetData(cons);
14923  assert(consdata != NULL);
14924 
14925  lhs = consdata->lhs;
14926  rhs = consdata->rhs;
14927 
14928  /* adjust sides and check that we do not subtract infinity values */
14929  /* constant is infinite */
14930  if( SCIPisInfinity(scip, REALABS(constant)) )
14931  {
14932  if( constant < 0.0 )
14933  {
14934  if( SCIPisInfinity(scip, lhs) )
14935  {
14936  SCIPfreeBufferArray(scip, &consvals);
14937  SCIPfreeBufferArray(scip, &consvars);
14938 
14939  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));
14940 
14941  SCIPABORT();
14942  return SCIP_INVALIDDATA; /*lint !e527*/
14943  }
14944  if( SCIPisInfinity(scip, rhs) )
14945  {
14946  SCIPfreeBufferArray(scip, &consvals);
14947  SCIPfreeBufferArray(scip, &consvars);
14948 
14949  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));
14950 
14951  SCIPABORT();
14952  return SCIP_INVALIDDATA; /*lint !e527*/
14953  }
14954 
14955  lhs = -SCIPinfinity(scip);
14956  rhs = -SCIPinfinity(scip);
14957  }
14958  else
14959  {
14960  if( SCIPisInfinity(scip, -lhs) )
14961  {
14962  SCIPfreeBufferArray(scip, &consvals);
14963  SCIPfreeBufferArray(scip, &consvars);
14964 
14965  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));
14966 
14967  SCIPABORT();
14968  return SCIP_INVALIDDATA; /*lint !e527*/
14969  }
14970  if( SCIPisInfinity(scip, -rhs) )
14971  {
14972  SCIPfreeBufferArray(scip, &consvals);
14973  SCIPfreeBufferArray(scip, &consvars);
14974 
14975  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));
14976 
14977  SCIPABORT();
14978  return SCIP_INVALIDDATA; /*lint !e527*/
14979  }
14980 
14981  lhs = SCIPinfinity(scip);
14982  rhs = SCIPinfinity(scip);
14983  }
14984  }
14985  /* constant is not infinite */
14986  else
14987  {
14988  if( !SCIPisInfinity(scip, REALABS(lhs)) )
14989  lhs -= constant;
14990  if( !SCIPisInfinity(scip, REALABS(rhs)) )
14991  rhs -= constant;
14992 
14993  if( SCIPisInfinity(scip, -lhs) )
14994  lhs = -SCIPinfinity(scip);
14995  else if( SCIPisInfinity(scip, lhs) )
14996  lhs = SCIPinfinity(scip);
14997 
14998  if( SCIPisInfinity(scip, rhs) )
14999  rhs = SCIPinfinity(scip);
15000  else if( SCIPisInfinity(scip, -rhs) )
15001  rhs = -SCIPinfinity(scip);
15002  }
15003 
15004  /* add all active variables to constraint */
15005  for( v = nconsvars - 1; v >= 0; --v )
15006  {
15007  SCIP_CALL( addCoef(scip, cons, consvars[v], consvals[v]) );
15008  }
15009 
15010  /* update left and right hand sides */
15011  SCIP_CALL( chgLhs(scip, cons, lhs));
15012  SCIP_CALL( chgRhs(scip, cons, rhs));
15013 
15014  SCIPfreeBufferArray(scip, &consvals);
15015  SCIPfreeBufferArray(scip, &consvars);
15016  }
15017  else
15018  {
15019  SCIP_CALL( addCoef(scip, cons, var, val) );
15020  }
15021 
15022  return SCIP_OKAY;
15023 }
15024 
15025 /** gets left hand side of linear constraint */
15027  SCIP* scip, /**< SCIP data structure */
15028  SCIP_CONS* cons /**< constraint data */
15029  )
15030 {
15031  SCIP_CONSDATA* consdata;
15032 
15033  assert(scip != NULL);
15034  assert(cons != NULL);
15035 
15036  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15037  {
15038  SCIPerrorMessage("constraint is not linear\n");
15039  SCIPABORT();
15040  return SCIP_INVALID; /*lint !e527*/
15041  }
15042 
15043  consdata = SCIPconsGetData(cons);
15044  assert(consdata != NULL);
15045 
15046  return consdata->lhs;
15047 }
15048 
15049 /** gets right hand side of linear constraint */
15051  SCIP* scip, /**< SCIP data structure */
15052  SCIP_CONS* cons /**< constraint data */
15053  )
15054 {
15055  SCIP_CONSDATA* consdata;
15056 
15057  assert(scip != NULL);
15058  assert(cons != NULL);
15059 
15060  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15061  {
15062  SCIPerrorMessage("constraint is not linear\n");
15063  SCIPABORT();
15064  return SCIP_INVALID; /*lint !e527*/
15065  }
15066 
15067  consdata = SCIPconsGetData(cons);
15068  assert(consdata != NULL);
15069 
15070  return consdata->rhs;
15071 }
15072 
15073 /** changes left hand side of linear constraint */
15075  SCIP* scip, /**< SCIP data structure */
15076  SCIP_CONS* cons, /**< constraint data */
15077  SCIP_Real lhs /**< new left hand side */
15078  )
15079 {
15080  assert(scip != NULL);
15081  assert(cons != NULL);
15082 
15083  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15084  {
15085  SCIPerrorMessage("constraint is not linear\n");
15086  return SCIP_INVALIDDATA;
15087  }
15088 
15089  SCIP_CALL( chgLhs(scip, cons, lhs) );
15090 
15091  return SCIP_OKAY;
15092 }
15093 
15094 /** changes right hand side of linear constraint */
15096  SCIP* scip, /**< SCIP data structure */
15097  SCIP_CONS* cons, /**< constraint data */
15098  SCIP_Real rhs /**< new right hand side */
15099  )
15100 {
15101  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15102  {
15103  SCIPerrorMessage("constraint is not linear\n");
15104  return SCIP_INVALIDDATA;
15105  }
15106 
15107  SCIP_CALL( chgRhs(scip, cons, rhs) );
15108 
15109  return SCIP_OKAY;
15110 }
15111 
15112 /** gets the number of variables in the linear constraint */
15114  SCIP* scip, /**< SCIP data structure */
15115  SCIP_CONS* cons /**< constraint data */
15116  )
15117 {
15118  SCIP_CONSDATA* consdata;
15119 
15120  assert(scip != NULL);
15121  assert(cons != NULL);
15122 
15123  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15124  {
15125  SCIPerrorMessage("constraint is not linear\n");
15126  SCIPABORT();
15127  return -1; /*lint !e527*/
15128  }
15129 
15130  consdata = SCIPconsGetData(cons);
15131  assert(consdata != NULL);
15132 
15133  return consdata->nvars;
15134 }
15135 
15136 /** gets the array of variables in the linear constraint; the user must not modify this array! */
15138  SCIP* scip, /**< SCIP data structure */
15139  SCIP_CONS* cons /**< constraint data */
15140  )
15141 {
15142  SCIP_CONSDATA* consdata;
15143 
15144  assert(scip != NULL);
15145  assert(cons != NULL);
15146 
15147  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15148  {
15149  SCIPerrorMessage("constraint is not linear\n");
15150  SCIPABORT();
15151  return NULL; /*lint !e527*/
15152  }
15153 
15154  consdata = SCIPconsGetData(cons);
15155  assert(consdata != NULL);
15156 
15157  return consdata->vars;
15158 }
15159 
15160 /** gets the array of coefficient values in the linear constraint; the user must not modify this array! */
15162  SCIP* scip, /**< SCIP data structure */
15163  SCIP_CONS* cons /**< constraint data */
15164  )
15165 {
15166  SCIP_CONSDATA* consdata;
15167 
15168  assert(scip != NULL);
15169  assert(cons != NULL);
15170 
15171  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15172  {
15173  SCIPerrorMessage("constraint is not linear\n");
15174  SCIPABORT();
15175  return NULL; /*lint !e527*/
15176  }
15177 
15178  consdata = SCIPconsGetData(cons);
15179  assert(consdata != NULL);
15180 
15181  return consdata->vals;
15182 }
15183 
15184 /** gets the activity of the linear constraint in the given solution */
15186  SCIP* scip, /**< SCIP data structure */
15187  SCIP_CONS* cons, /**< constraint data */
15188  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
15189  )
15190 {
15191  SCIP_CONSDATA* consdata;
15192 
15193  assert(scip != NULL);
15194  assert(cons != NULL);
15195 
15196  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15197  {
15198  SCIPerrorMessage("constraint is not linear\n");
15199  SCIPABORT();
15200  return SCIP_INVALID; /*lint !e527*/
15201  }
15202 
15203  consdata = SCIPconsGetData(cons);
15204  assert(consdata != NULL);
15205 
15206  if( consdata->row != NULL )
15207  return SCIPgetRowSolActivity(scip, consdata->row, sol);
15208  else
15209  return consdataGetActivity(scip, consdata, sol);
15210 }
15211 
15212 /** gets the feasibility of the linear constraint in the given solution */
15214  SCIP* scip, /**< SCIP data structure */
15215  SCIP_CONS* cons, /**< constraint data */
15216  SCIP_SOL* sol /**< solution, or NULL to use current node's solution */
15217  )
15218 {
15219  SCIP_CONSDATA* consdata;
15220 
15221  assert(scip != NULL);
15222  assert(cons != NULL);
15223 
15224  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15225  {
15226  SCIPerrorMessage("constraint is not linear\n");
15227  SCIPABORT();
15228  return SCIP_INVALID; /*lint !e527*/
15229  }
15230 
15231  consdata = SCIPconsGetData(cons);
15232  assert(consdata != NULL);
15233 
15234  if( consdata->row != NULL )
15235  return SCIPgetRowSolFeasibility(scip, consdata->row, sol);
15236  else
15237  return consdataGetFeasibility(scip, consdata, sol);
15238 }
15239 
15240 /** gets the dual solution of the linear constraint in the current LP */
15242  SCIP* scip, /**< SCIP data structure */
15243  SCIP_CONS* cons /**< constraint data */
15244  )
15245 {
15246  SCIP_CONSDATA* consdata;
15247 
15248  assert(scip != NULL);
15249  assert(cons != NULL);
15250 
15251  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15252  {
15253  SCIPerrorMessage("constraint is not linear\n");
15254  SCIPABORT();
15255  return SCIP_INVALID; /*lint !e527*/
15256  }
15257 
15258  consdata = SCIPconsGetData(cons);
15259  assert(consdata != NULL);
15260 
15261  if( consdata->row != NULL )
15262  return SCIProwGetDualsol(consdata->row);
15263  else
15264  return 0.0;
15265 }
15266 
15267 /** gets the dual Farkas value of the linear constraint in the current infeasible LP */
15269  SCIP* scip, /**< SCIP data structure */
15270  SCIP_CONS* cons /**< constraint data */
15271  )
15272 {
15273  SCIP_CONSDATA* consdata;
15274 
15275  assert(scip != NULL);
15276  assert(cons != NULL);
15277 
15278  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15279  {
15280  SCIPerrorMessage("constraint is not linear\n");
15281  SCIPABORT();
15282  return SCIP_INVALID; /*lint !e527*/
15283  }
15284 
15285  consdata = SCIPconsGetData(cons);
15286  assert(consdata != NULL);
15287 
15288  if( consdata->row != NULL )
15289  return SCIProwGetDualfarkas(consdata->row);
15290  else
15291  return 0.0;
15292 }
15293 
15294 /** returns the linear relaxation of the given linear constraint; may return NULL if no LP row was yet created;
15295  * the user must not modify the row!
15296  */
15298  SCIP* scip, /**< SCIP data structure */
15299  SCIP_CONS* cons /**< constraint data */
15300  )
15301 {
15302  SCIP_CONSDATA* consdata;
15303 
15304  assert(scip != NULL);
15305  assert(cons != NULL);
15306 
15307  if( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
15308  {
15309  SCIPerrorMessage("constraint is not linear\n");
15310  SCIPABORT();
15311  return NULL; /*lint !e527*/
15312  }
15313 
15314  consdata = SCIPconsGetData(cons);
15315  assert(consdata != NULL);
15316 
15317  return consdata->row;
15318 }
15319 
15320 /** tries to automatically convert a linear constraint into a more specific and more specialized constraint */
15322  SCIP* scip, /**< SCIP data structure */
15323  SCIP_CONS* cons, /**< source constraint to try to convert */
15324  SCIP_CONS** upgdcons /**< pointer to store upgraded constraint, or NULL if not successful */
15325  )
15326 {
15327  SCIP_CONSHDLR* conshdlr;
15328  SCIP_CONSHDLRDATA* conshdlrdata;
15329  SCIP_CONSDATA* consdata;
15330  SCIP_VAR* var;
15331  SCIP_Real val;
15332  SCIP_Real lb;
15333  SCIP_Real ub;
15334  SCIP_Real poscoeffsum;
15335  SCIP_Real negcoeffsum;
15336  SCIP_Bool integral;
15337  int nposbin;
15338  int nnegbin;
15339  int nposint;
15340  int nnegint;
15341  int nposimpl;
15342  int nnegimpl;
15343  int nposimplbin;
15344  int nnegimplbin;
15345  int nposcont;
15346  int nnegcont;
15347  int ncoeffspone;
15348  int ncoeffsnone;
15349  int ncoeffspint;
15350  int ncoeffsnint;
15351  int ncoeffspfrac;
15352  int ncoeffsnfrac;
15353  int i;
15354 
15355  assert(scip != NULL);
15356  assert(cons != NULL);
15357  assert(upgdcons != NULL);
15358 
15359  *upgdcons = NULL;
15360 
15361  /* we cannot upgrade a modifiable linear constraint, since we don't know what additional coefficients to expect */
15362  if( SCIPconsIsModifiable(cons) )
15363  return SCIP_OKAY;
15364 
15365  /* check for upgradability */
15366  if( SCIPconsGetNUpgradeLocks(cons) > 0 )
15367  return SCIP_OKAY;
15368 
15369  /* get the constraint handler and check, if it's really a linear constraint */
15370  conshdlr = SCIPconsGetHdlr(cons);
15371  if( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) != 0 )
15372  {
15373  SCIPerrorMessage("constraint is not linear\n");
15374  return SCIP_INVALIDDATA;
15375  }
15376 
15377  /* get constraint handler data and constraint data */
15378  conshdlrdata = SCIPconshdlrGetData(conshdlr);
15379  assert(conshdlrdata != NULL);
15380  consdata = SCIPconsGetData(cons);
15381  assert(consdata != NULL);
15382 
15383  /* check, if the constraint was already upgraded and will be deleted anyway after preprocessing */
15384  if( consdata->upgraded )
15385  return SCIP_OKAY;
15386 
15387  /* check, if the constraint is already stored as LP row */
15388  if( consdata->row != NULL )
15389  {
15390  if( SCIProwIsInLP(consdata->row) )
15391  {
15392  SCIPerrorMessage("cannot upgrade linear constraint that is already stored as row in the LP\n");
15393  return SCIP_INVALIDDATA;
15394  }
15395  else
15396  {
15397  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
15398  }
15399  }
15400 
15401  /* normalize constraint */
15402  SCIP_CALL( normalizeCons(scip, cons) );
15403 
15404 
15405  /*
15406  * calculate some statistics on linear constraint
15407  */
15408 
15409  nposbin = 0;
15410  nnegbin = 0;
15411  nposint = 0;
15412  nnegint = 0;
15413  nposimpl = 0;
15414  nnegimpl = 0;
15415  nposimplbin = 0;
15416  nnegimplbin = 0;
15417  nposcont = 0;
15418  nnegcont = 0;
15419  ncoeffspone = 0;
15420  ncoeffsnone = 0;
15421  ncoeffspint = 0;
15422  ncoeffsnint = 0;
15423  ncoeffspfrac = 0;
15424  ncoeffsnfrac = 0;
15425  integral = TRUE;
15426  poscoeffsum = 0.0;
15427  negcoeffsum = 0.0;
15428 
15429  for( i = 0; i < consdata->nvars; ++i )
15430  {
15431  var = consdata->vars[i];
15432  val = consdata->vals[i];
15433  lb = SCIPvarGetLbLocal(var);
15434  ub = SCIPvarGetUbLocal(var);
15435  assert(!SCIPisZero(scip, val));
15436 
15437  switch( SCIPvarGetType(var) )
15438  {
15439  case SCIP_VARTYPE_BINARY:
15440  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
15441  integral = integral && SCIPisIntegral(scip, val);
15442  if( val >= 0.0 )
15443  nposbin++;
15444  else
15445  nnegbin++;
15446  break;
15447  case SCIP_VARTYPE_INTEGER:
15448  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
15449  integral = integral && SCIPisIntegral(scip, val);
15450  if( val >= 0.0 )
15451  nposint++;
15452  else
15453  nnegint++;
15454  break;
15455  case SCIP_VARTYPE_IMPLINT:
15456  if( SCIPvarIsBinary(var) )
15457  {
15458  if( val >= 0.0 )
15459  nposimplbin++;
15460  else
15461  nnegimplbin++;
15462  }
15463  if( !SCIPisZero(scip, lb) || !SCIPisZero(scip, ub) )
15464  integral = integral && SCIPisIntegral(scip, val);
15465  if( val >= 0.0 )
15466  nposimpl++;
15467  else
15468  nnegimpl++;
15469  break;
15471  integral = integral && SCIPisEQ(scip, lb, ub) && SCIPisIntegral(scip, val * lb);
15472  if( val >= 0.0 )
15473  nposcont++;
15474  else
15475  nnegcont++;
15476  break;
15477  default:
15478  SCIPerrorMessage("unknown variable type\n");
15479  return SCIP_INVALIDDATA;
15480  }
15481  if( SCIPisEQ(scip, val, 1.0) )
15482  ncoeffspone++;
15483  else if( SCIPisEQ(scip, val, -1.0) )
15484  ncoeffsnone++;
15485  else if( SCIPisIntegral(scip, val) )
15486  {
15487  if( SCIPisPositive(scip, val) )
15488  ncoeffspint++;
15489  else
15490  ncoeffsnint++;
15491  }
15492  else
15493  {
15494  if( SCIPisPositive(scip, val) )
15495  ncoeffspfrac++;
15496  else
15497  ncoeffsnfrac++;
15498  }
15499  if( SCIPisPositive(scip, val) )
15500  poscoeffsum += val;
15501  else
15502  negcoeffsum += val;
15503  }
15504 
15505 
15506  /*
15507  * call the upgrading methods
15508  */
15509 
15510  SCIPdebugMessage("upgrading linear constraint <%s> (%d upgrade methods):\n",
15511  SCIPconsGetName(cons), conshdlrdata->nlinconsupgrades);
15512  SCIPdebugMessage(" +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",
15513  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposcont, nnegcont,
15514  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
15515  poscoeffsum, negcoeffsum, integral);
15516 
15517  /* try all upgrading methods in priority order in case the upgrading step is enable */
15518  for( i = 0; i < conshdlrdata->nlinconsupgrades && *upgdcons == NULL; ++i )
15519  {
15520  if( conshdlrdata->linconsupgrades[i]->active )
15521  {
15522  SCIP_CALL( conshdlrdata->linconsupgrades[i]->linconsupgd(scip, cons, consdata->nvars,
15523  consdata->vars, consdata->vals, consdata->lhs, consdata->rhs,
15524  nposbin, nnegbin, nposint, nnegint, nposimpl, nnegimpl, nposimplbin, nnegimplbin, nposcont, nnegcont,
15525  ncoeffspone, ncoeffsnone, ncoeffspint, ncoeffsnint, ncoeffspfrac, ncoeffsnfrac,
15526  poscoeffsum, negcoeffsum, integral,
15527  upgdcons) );
15528  }
15529  }
15530 
15531 #ifdef SCIP_DEBUG
15532  if( *upgdcons != NULL )
15533  {
15534  SCIPdebugPrintCons(scip, cons, NULL);
15535  SCIPdebugMessage(" -> upgraded to constraint type <%s>\n", SCIPconshdlrGetName(SCIPconsGetHdlr(*upgdcons)));
15536  SCIPdebugPrintCons(scip, *upgdcons, NULL);
15537  }
15538 #endif
15539 
15540  return SCIP_OKAY;
15541 }
15542